from argparse import ArgumentParser from os import path, sep class Parse: """ Parser of configs, arguments, parameters """ def __init__(self, parameters, block: str = None): """ Object constructor :param parameters: dictionary as "key":"value" or ArgumentParser class object or string path to the file or string as "var1=val1;var2=val2" :param block: string name of target block from text """ self.data = {} if type(parameters) is dict: self._dict2dict(parameters) if type(parameters) is ArgumentParser: self._dict2dict(self.argv2dict(parameters)) if type(parameters) is str: if path.exists(parameters): self._dict2dict(self.strs2dict(self.conf2strs(parameters), block)) else: self._dict2dict(self.strs2dict(parameters, block)) def __str__(self): """ Overrides method for print(object) :return: string with contents of the object's dictionary """ string = '' for key, val in self.data.items(): string += str(type(val)) + ' ' + str(key) + ' = ' + str(val) + '\n' return string def _dict2dict(self, dictionary: dict): """ Updates or adds dictionary data :param dictionary: dictionary as "key":"value" :return: None """ self.data.update(dictionary) def expand(self, store: str = None): """ Expand dictionary "key":"name.conf" to dictionary "key":{subkey: subval} :param store: string path to directory with name.conf :return: expanded dictionary as "key":{subkey: subval} """ for key in self.data: if store: config = store + sep + self.data[key] else: config = self.data[key] with open(config) as file: self.data[key] = Parse(file.read()).data return self.data @classmethod def argv2dict(cls, parser: ArgumentParser): """ Converts startup arguments to a dictionary :param parser: argparse.ArgumentParser class object :return: dictionary as "key":"value" """ parser = ArgumentParser(add_help=False, parents=[parser]) return vars(parser.parse_args()) @classmethod def conf2strs(cls, config: str): """ Builds a dictionary from a file containing parameters :param config: string path to the file :return: string as "var1=val1;\nvar2=val2;" """ with open(config) as file: raw = file.read() strs = '' for line in raw.splitlines(): if not line.lstrip().startswith('#'): strs += line + '\n' return strs @classmethod def strs2dict(cls, strings: str, blockname: str): """ Builds a dictionary from a strings containing parameters :param strings: string as "var1=val1;var2=val2;" :param blockname: string name of target block from text :return: dictionary as "key":"value" """ dictionary = {} if blockname: strings = cls.block(blockname, strings) for line in strings.replace('\n', ';').split(';'): if not line.lstrip().startswith('#') and "=" in line: dictionary[line.split('=')[0].strip()] = line.split('=')[1].strip().split(';')[0].strip() return dictionary @classmethod def str2bool(cls, value: str): """ Converts a string value to boolean :param value: string containing "true" or "false", "yes" or "no", "1" or "0" :return: bool True or False """ return str(value).lower() in ("true", "yes", "1") @classmethod def block(cls, blockname: str, text: str): """ Cuts a block of text between line [blockname] and line [next block] or EOF :param blockname: string in [] after which the block starts :param text: string of text from which the block is needed :return: string of text between line [block name] and line [next block] """ level = 1 save = False result = '' for line in text.splitlines(): if line.startswith('[') and blockname in line: level = line.count('[') save = True elif line.startswith('[') and '['*level in line: save = False elif save: result += line + '\n' return result if __name__ == "__main__": pass