<s> import log <EOL> from log import PAGEDUMP <EOL> import argparse <EOL> import sys <EOL> import io <EOL> from argparse import Namespace <EOL> from copy import copy <EOL> _logger = log . getChild ( '<STR_LIT>' ) <EOL> def _dumpconfig ( parser , level = PAGEDUMP ) : <EOL> _logger . log ( level , '<STR_LIT>' ) <EOL> for section_name , section in parser . items ( ) : <EOL> _logger . log ( level , '<STR_LIT>' , section_name ) <EOL> _logger . log ( level , '<STR_LIT>' ) <EOL> for key , value in section . items ( ) : <EOL> _logger . log ( level , '<STR_LIT>' , key , value ) <EOL> _logger . log ( level , '<STR_LIT>' ) <EOL> str_to_bool = lambda x : True if bool ( x ) and x . lower ( ) != '<STR_LIT:false>' else False <EOL> class ConfigParameter : <EOL> '''<STR_LIT>''' <EOL> def __init__ ( self , name , defaults = None , type = None , choices = None , help = '<STR_LIT>' , loader_srcs = None , loader_opts = None ) : <EOL> '''<STR_LIT>''' <EOL> self . logger = log . getChild ( self . __class__ . __name__ ) <EOL> self . name = str ( name ) <EOL> self . validate_name ( ) <EOL> self . defaults = defaults if isinstance ( defaults , dict ) else { '<STR_LIT:*>' : defaults } <EOL> if type is not None : self . type = type <EOL> if choices is not None : self . choices = choices <EOL> self . help = help <EOL> self . loader_opts = loader_opts if loader_opts is not None else dict ( ) <EOL> self . loader_srcs = loader_srcs if loader_srcs is not None else [ '<STR_LIT:all>' ] <EOL> self . logger . debug ( '<STR_LIT>' , self ) <EOL> def validate_name ( self ) : <EOL> if any ( map ( lambda x : x . isspace ( ) , self . name ) ) : <EOL> self . logger . error ( '<STR_LIT>' , self . name ) <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> def get_default ( self , platform = None ) : <EOL> if not platform : <EOL> platform = sys . platform <EOL> if platform not in self . defaults : <EOL> platform = '<STR_LIT:*>' <EOL> return self . defaults [ platform ] <EOL> def get_option ( self , loader_key , option_name , default = None ) : <EOL> opts = self . loader_opts . get ( loader_key , dict ( ) ) <EOL> if option_name in opts : <EOL> return opts [ option_name ] <EOL> else : <EOL> return default <EOL> def is_loader_supported ( self , loader_name ) : <EOL> return '<STR_LIT:all>' in self . loader_srcs or loader_name in self . loader_srcs <EOL> def type_cast ( self , value ) : <EOL> if hasattr ( self , '<STR_LIT:type>' ) : <EOL> return self . type ( value ) <EOL> return value <EOL> def __repr__ ( self ) : <EOL> return '''<STR_LIT>''' . format ( <EOL> self . __class__ . __name__ , <EOL> repr ( self . name ) , <EOL> repr ( self . defaults ) , <EOL> repr ( self . type if hasattr ( self , '<STR_LIT:type>' ) else None ) , <EOL> repr ( self . choices if hasattr ( self , '<STR_LIT>' ) else None ) , <EOL> repr ( self . help ) , <EOL> repr ( self . loader_opts ) <EOL> ) <EOL> def __eq__ ( self , other ) : <EOL> return self . name == other . name <EOL> class ConfigDatabase : <EOL> def __init__ ( self , prog , description = None , parameters = None ) : <EOL> self . logger = log . getChild ( self . __class__ . __name__ ) <EOL> self . prog = prog <EOL> self . description = description <EOL> self . parameters = list ( parameters ) if parameters is not None else list ( ) <EOL> def add_param ( self , param ) : <EOL> if param not in self . parameters : <EOL> self . parameters . append ( param ) <EOL> self . logger . debug ( '<STR_LIT>' , param , self . prog ) <EOL> else : <EOL> raise NameError ( '<STR_LIT>' % ( param . name , ) ) <EOL> def __repr__ ( self ) : <EOL> return '<STR_LIT>' . format ( <EOL> self . __class__ . __name__ , <EOL> repr ( self . prog ) , <EOL> repr ( self . description ) , <EOL> repr ( self . parameters ) <EOL> ) <EOL> class ConfigLoader : <EOL> def load ( self , db , generate_default = False , * args , ** kwargs ) : <EOL> raise NotImplemented ( ) <EOL> class ConfigDumper : <EOL> def dump ( self , db , conf , buf , * args , ** kwargs ) : <EOL> raise NotImplemented ( ) <EOL> from configparser import ConfigParser <EOL> class ConfigFileLoader ( ConfigLoader ) : <EOL> '''<STR_LIT>''' <EOL> OPT_KEY = '<STR_LIT>' <EOL> class ConfigValueError ( ValueError ) : pass <EOL> def load_value ( self , param , parser , ans , generate_default ) : <EOL> section = param . get_option ( self . OPT_KEY , '<STR_LIT>' , None ) <EOL> if section is None : section = parser . default_section <EOL> key = param . get_option ( self . OPT_KEY , '<STR_LIT:key>' , param . name ) <EOL> converter = param . get_option ( self . OPT_KEY , '<STR_LIT>' , param . type_cast ) <EOL> if parser . has_option ( section , key ) : <EOL> value = parser . get ( section , key ) <EOL> loaded = True <EOL> elif generate_default : <EOL> value = param . get_default ( ) <EOL> loaded = True <EOL> else : <EOL> value = None <EOL> loaded = False <EOL> if loaded : <EOL> value = converter ( value ) <EOL> if hasattr ( param , '<STR_LIT>' ) and value not in param . choices : <EOL> raise ConfigFileLoader . ConfigValueError ( <EOL> "<STR_LIT>" % ( <EOL> section , key , value , "<STR_LIT:U+002CU+0020>" . join ( param . choices ) ) <EOL> ) <EOL> return loaded , key , value <EOL> def load ( self , db , data , generate_default = False ) : <EOL> ans = Namespace ( ) <EOL> parser = ConfigParser ( ) <EOL> parser . read_file ( data ) <EOL> _dumpconfig ( parser ) <EOL> for param in db . parameters : <EOL> if not param . is_loader_supported ( self . OPT_KEY ) : continue <EOL> loaded , key , value = self . load_value ( param , parser , ans , generate_default ) <EOL> if loaded : <EOL> setattr ( ans , key , value ) <EOL> return ans <EOL> class ConfigFileDumper ( ConfigDumper ) : <EOL> '''<STR_LIT>''' <EOL> OPT_KEY = '<STR_LIT>' <EOL> def get_param_by_name ( self , db , name ) : <EOL> key_comparator = lambda param : name == param . get_option ( self . OPT_KEY , '<STR_LIT:key>' , None ) <EOL> name_comparator = lambda param : name == param . name <EOL> by_key = list ( filter ( key_comparator , db . parameters ) ) <EOL> if len ( by_key ) > <NUM_LIT:1> : <EOL> raise ValueError ( '<STR_LIT>' . format ( name ) ) <EOL> elif len ( by_key ) == <NUM_LIT:1> : <EOL> return by_key [ <NUM_LIT:0> ] <EOL> by_name = list ( filter ( name_comparator , db . parameters ) ) <EOL> if len ( by_name ) > <NUM_LIT:1> : <EOL> raise ValueError ( '<STR_LIT>' . format ( name ) ) <EOL> elif len ( by_name ) == <NUM_LIT:1> : <EOL> return by_name [ <NUM_LIT:0> ] <EOL> else : <EOL> return None <EOL> def dump ( self , db , conf , buf , * args , ** kwargs ) : <EOL> parser = ConfigParser ( ) <EOL> for k , v in vars ( conf ) . items ( ) : <EOL> param = self . get_param_by_name ( db , k ) <EOL> if param is None : <EOL> _logger . warn ( '<STR_LIT>' , k , v ) <EOL> if not param . is_loader_supported ( self . OPT_KEY ) : continue <EOL> section = param . get_option ( self . OPT_KEY , '<STR_LIT>' , parser . default_section ) <EOL> if section != parser . default_section and not parser . has_section ( section ) : <EOL> parser . add_section ( section ) <EOL> formatter = param . get_option ( self . OPT_KEY , '<STR_LIT>' , str ) <EOL> parser . set ( section , k , formatter ( v ) ) <EOL> _dumpconfig ( parser ) <EOL> parser . write ( buf , kwargs . get ( '<STR_LIT>' , True ) ) <EOL> if _logger . isEnabledFor ( PAGEDUMP ) : <EOL> dbg_buf = io . StringIO ( ) <EOL> parser . write ( dbg_buf , kwargs . get ( '<STR_LIT>' , True ) ) <EOL> _logger . log ( PAGEDUMP , '<STR_LIT>' , dbg_buf . getvalue ( ) ) <EOL> class CommandLineArgumentsLoader ( ConfigLoader ) : <EOL> '''<STR_LIT>''' <EOL> OPT_KEY = '<STR_LIT>' <EOL> @ staticmethod <EOL> def param_to_arg_opts ( param , generate_default ) : <EOL> opts = { <EOL> '<STR_LIT>' : param . help , <EOL> '<STR_LIT>' : param . name , <EOL> } <EOL> if hasattr ( param , '<STR_LIT:type>' ) : opts [ '<STR_LIT:type>' ] = param . type <EOL> if hasattr ( param , '<STR_LIT>' ) : opts [ '<STR_LIT>' ] = param . choices <EOL> if generate_default : <EOL> opts [ '<STR_LIT:default>' ] = param . get_default ( ) <EOL> else : <EOL> opts [ '<STR_LIT:default>' ] = argparse . SUPPRESS <EOL> specific_opts = param . loader_opts . get ( CommandLineArgumentsLoader . OPT_KEY , dict ( ) ) <EOL> opts . update ( specific_opts ) <EOL> if '<STR_LIT>' in opts : del ( opts [ '<STR_LIT>' ] ) <EOL> _logger . debug ( '<STR_LIT>' , opts ) <EOL> return opts <EOL> @ staticmethod <EOL> def param_to_arg_flags ( param ) : <EOL> flags = param . get_option ( CommandLineArgumentsLoader . OPT_KEY , '<STR_LIT>' , None ) <EOL> if flags : <EOL> ans = flags <EOL> elif len ( param . name ) == <NUM_LIT:1> : <EOL> ans = [ '<STR_LIT:->' + param . name , ] <EOL> else : <EOL> ans = [ '<STR_LIT>' + param . name , ] <EOL> _logger . debug ( '<STR_LIT>' , ans ) <EOL> return ans <EOL> @ staticmethod <EOL> def assemble_parser ( db , generate_default ) : <EOL> parser = argparse . ArgumentParser ( prog = db . prog , description = db . description ) <EOL> for param in db . parameters : <EOL> if not param . is_loader_supported ( CommandLineArgumentsLoader . OPT_KEY ) : continue <EOL> _logger . debug ( '<STR_LIT>' , param ) <EOL> parser . add_argument ( <EOL> * CommandLineArgumentsLoader . param_to_arg_flags ( param ) , <EOL> ** CommandLineArgumentsLoader . param_to_arg_opts ( param , generate_default ) <EOL> ) <EOL> return parser <EOL> def load ( self , db , data , generate_default = False ) : <EOL> _logger . debug ( '<STR_LIT>' , data ) <EOL> parser = CommandLineArgumentsLoader . assemble_parser ( db , generate_default ) <EOL> return parser . parse_args ( data ) <EOL> class DefaultValueLoader ( ConfigLoader ) : <EOL> OPT_KEY = '<STR_LIT>' <EOL> def __init__ ( self , platform = None ) : <EOL> self . platform = platform <EOL> def load ( self , db , data = None , generate_default = True ) : <EOL> ans = Namespace ( ) <EOL> if not generate_default : return ans <EOL> for param in db . parameters : <EOL> if not param . is_loader_supported ( self . OPT_KEY ) : continue <EOL> val = param . get_default ( self . platform ) <EOL> val = param . type ( val ) if hasattr ( param , '<STR_LIT:type>' ) else val <EOL> setattr ( ans , param . name , val ) <EOL> return ans <EOL> def merge_config ( config , increment ) : <EOL> _logger . debug ( '<STR_LIT>' , increment , config ) <EOL> ans = copy ( config ) <EOL> ans . __dict__ . update ( increment . __dict__ ) <EOL> _logger . debug ( '<STR_LIT>' , ans ) <EOL> return ans <EOL> def pretty ( config , sep = '<STR_LIT:\n>' ) : <EOL> lines = [ '<STR_LIT>' . format ( str ( k ) , repr ( v ) ) for k , v in config . __dict__ . items ( ) ] <EOL> lines . sort ( ) <EOL> return sep . join ( lines ) <EOL> def to_file ( db , config , filename , dumper = None ) : <EOL> dumper = ConfigFileDumper ( ) if not dumper else dumper <EOL> with open ( filename , '<STR_LIT:w>' , encoding = '<STR_LIT:utf-8>' ) as outf : <EOL> dumper . dump ( db , config , outf ) <EOL> outf . flush ( ) <EOL> def from_file ( db , filename , loader = None ) : <EOL> loader = ConfigFileLoader ( ) if not loader else loader <EOL> with open ( filename , '<STR_LIT:r>' , encoding = '<STR_LIT:utf-8>' ) as inf : <EOL> return loader . load ( db , inf ) </s>
