Source code for tmtk.params.ParamsBase

import os
import glob

from ..utils import PathError, merge_two_dicts, ValidateMixin

[docs]class ParamsBase(ValidateMixin): """ Base class for parameter files. """ def __init__(self, path=None, parameters=None, subdir=None, parent=None): """ :param path: describes the path to the params file. :param parameters: a dictionary you can provide to setup the parameter file. :param subdir: is the key that is given by Study class. :param parent: can be used to find the parent instance of this object. """ self.path = path self.dirname = os.path.dirname(path) self.datatype = os.path.basename(path).split('.params')[0] self._parent = parent self.subdir = subdir if parameters: self.__dict__.update(**parameters) elif os.path.exists(self.path): self.__dict__.update(**self._params_in_file) def __str__(self): return 'Params: {} ({})'.format(self.datatype, self.path) def __repr__(self): return 'Params: {} ({})'.format(self.datatype, self.path)
[docs] def get(self, parameter, default=None): """ Return value for parameter. :param parameter: string will be converted to uppercase. :param default: return default if value is not found. :return: value for this parameter if set, else None. """ return self.__dict__.get(parameter.upper(), default)
[docs] def set(self, parameter, value): self.__dict__[parameter.upper()] = value
@property def _params_in_file(self): """ Dictionary with all variables in file.""" params_dict = {} with open(self.path, 'r') as f: for line in f.readlines(): # Only keep things before a comment character line = line.split('#', 1)[0] line = line.strip() if '=' not in line: continue parameter = line.split('=') param = parameter[0] value = parameter[1].strip("\'\"") if param == 'PLATFORM': value = value.upper() if param == 'DATA_FILE_PREFIX': param = 'DATA_FILE' params_dict[param] = value return params_dict
[docs] def write_to(self, path, overwrite=False): """ Writes parameters in object to file in path. Does not overwrite existing files unless specifically told. :param path: path to store parameters to. :param overwrite: allow overwriting existing files. """ def _write_dict(f, d): for param, d in d.items(): value = self.get(param) if value: row = '# {}\n{}={}\n'.format(d.get('helptext'), param, value) f.write(row) if not path: raise PathError(path) if not overwrite and os.path.exists(path): raise PathError( "{} already exists. Consider setting `overwrite=True`".format(self.path)) os.makedirs(os.path.dirname(path), exist_ok=True) with open(path, 'w') as f: f.write('### Mandatory\n') _write_dict(f, self.mandatory) f.write('\n### Optional\n') _write_dict(f, self.optional)
[docs] def save(self): """Overwrite the original file with the current parameters.""" self.write_to(self.path, overwrite=True)
[docs] def update(self): """Iterate over parameters to change them interactively.""" print(' '.join(['=' * 10, str(self) + ' params', '=' * 10])) for param, d in merge_two_dicts(self.mandatory, self.optional).items(): current = self.get(param) default = d.get('default') is_file = 'FILE' in param print('Updating: {}'.format(param), end='') if current: print('={}.'.format(current)) elif default: print('={} (default).'.format(default)) else: print(' (not set)') print('Helptext: {}'.format(d.get('helptext'))) if is_file: files_in_dir = [os.path.basename(f) for f in glob.glob(os.path.join(self.dirname, '*')) if not os.path.isdir(f)] for i, f in enumerate(files_in_dir): print('- {}. {}'.format(i, f)) new_setting = input('Change to: ') if is_file: try: choice = int(new_setting) new_setting = files_in_dir[choice] except (ValueError, IndexError): pass if new_setting and new_setting != current: print('Updating! ({}={})'.format(param, new_setting)) self.__dict__[param] = new_setting print('-' * 20)
def _validate_correct_params(self): for param in self.mandatory: value = self.get(param) if not value: self.msgs.error('No {} given.'.format(param)) for param, value in self.__dict__.items(): if param.islower(): continue'Detected parameter {}={}.'.format(param, value)) if param not in self.mandatory and param not in self.optional: self.msgs.error('Illegal param found: {}.'.format(param)) elif 'FILE' in param: if not os.path.exists(os.path.join(self.dirname, value)): self.msgs.error('{}={} cannot be found on disk.'.format(param, value)) else: self.msgs.okay('{}={} found.'.format(param, value))