def test_setup_definitions_3(self): d = DotDict() def fake_mapping_func(source, destination): self.assertTrue(isinstance(source, str)) self.assertEqual(d, destination) saved_original = defsrc.definition_dispatch.copy() try: defsrc.definition_dispatch[str] = fake_mapping_func s = "{}" defsrc.setup_definitions(s, d) finally: defsrc.definition_dispatch = saved_original
def test_setup_definitions_3(self): d = dd.DotDict() def fake_mapping_func(source, destination): self.assertTrue(isinstance(source, str)) self.assertEqual(d, destination) saved_original = defsrc.definition_dispatch.copy() try: defsrc.definition_dispatch[str] = fake_mapping_func s = "{}" defsrc.setup_definitions(s, d) finally: defsrc.definition_dispatch = saved_original
def test_setup_definitions_2(self): d = DotDict() def fake_mapping_func(source, destination): self.assertTrue(source is collections) self.assertEqual(d, destination) saved_original = defsrc.definition_dispatch.copy() try: defsrc.definition_dispatch[type(collections)] = fake_mapping_func s = collections defsrc.setup_definitions(s, d) finally: defsrc.definition_dispatch = saved_original
def test_setup_definitions_2(self): d = dd.DotDict() def fake_mapping_func(source, destination): self.assertTrue(source is collections) self.assertEqual(d, destination) saved_original = defsrc.definition_dispatch.copy() try: defsrc.definition_dispatch[type(collections)] = fake_mapping_func s = collections defsrc.setup_definitions(s, d) finally: defsrc.definition_dispatch = saved_original
def test_setup_definitions_1(self): d = DotDict() def fake_mapping_func(source, destination): self.assertTrue(isinstance(source, collections.Mapping)) self.assertEqual(d, destination) saved_original = defsrc.definition_dispatch.copy() try: defsrc.definition_dispatch[collections.Mapping] = fake_mapping_func s = {} defsrc.setup_definitions(s, d) s = DotDict() defsrc.setup_definitions(s, d) s = Namespace() defsrc.setup_definitions(s, d) finally: defsrc.definition_dispatch = saved_original
def test_setup_definitions_1(self): d = dd.DotDict() def fake_mapping_func(source, destination): self.assertTrue(isinstance(source, collections.Mapping)) self.assertEqual(d, destination) saved_original = defsrc.definition_dispatch.copy() try: defsrc.definition_dispatch[collections.Mapping] = fake_mapping_func s = {} defsrc.setup_definitions(s, d) s = dd.DotDict() defsrc.setup_definitions(s, d) s = config_manager.Namespace() defsrc.setup_definitions(s, d) finally: defsrc.definition_dispatch = saved_original
def __init__( self, definition_source=None, values_source_list=None, argv_source=None, #use_config_files=True, use_auto_help=True, use_admin_controls=True, quit_after_admin=True, options_banned_from_help=None, app_name='', app_version='', app_description='', config_pathname='.', config_optional=True, value_source_object_hook=DotDict, ): """create and initialize a configman object. parameters: definition_source - a namespace or list of namespaces from which configman is to fetch the definitions of the configuration parameters. values_source_list - (optional) a hierarchical list of sources for values for the configuration parameters. As values are copied from these sources, conficting values are resolved with sources on the right getting preference over sources on the left. argv_source - if the values_source_list contains a commandline source, this value is an alternative source for actual command line arguments. Useful for testing or preprocessing command line arguments. use_auto_help - set to True if configman is to automatically set up help output for command line invocations. use_admin_controls - configman can add command line flags that it interprets independently of the app defined arguments. True enables this capability, while, False supresses it. quit_after_admin - if True and admin controls are enabled and used, call sys.exit to end the app. This is useful to stop the app from running if all that was done was to write a config file or stop after help. options_banned_from_help - a list of strings that will censor the output of help to prevent specified options from being listed in the help output. This is useful for hiding debug or secret command line arguments. app_name - assigns a name to the app. This is used in help output and as a default basename for config files. app_version - assigns a version for the app used help output. app_description - assigns a description for the app to be used in the help output. config_pathname - a hard coded path to the directory of or the full path and name of the configuration file. config_optional - a boolean indicating if a missing default config file is optional. Note: this is only for the default config file. If a config file is specified on the commandline, it _must_ exist. value_source_object_hook - a class used for the internal representation of a value source. This is used to enable any special processing, like key translations. """ # instead of allowing mutables as default keyword argument values... if definition_source is None: definition_source_list = [] elif (isinstance(definition_source, collections.Sequence) and not isinstance(definition_source, (six.binary_type, six.text_type))): definition_source_list = list(definition_source) else: if isinstance(definition_source, (six.binary_type, six.text_type)): definition_source = to_str(definition_source) definition_source_list = [definition_source] if argv_source is None: self.argv_source = sys.argv[1:] self.app_invocation_name = sys.argv[0] else: self.argv_source = argv_source self.app_invocation_name = app_name if options_banned_from_help is None: options_banned_from_help = ['application'] self.config_pathname = config_pathname self.config_optional = config_optional self.use_auto_help = use_auto_help self.value_source_object_hook = value_source_object_hook self.app_name = app_name self.app_version = app_version self.app_description = app_description self.args = [] # extra commandline arguments that are not switches # will be stored here. self._config = None # eventual container for DOM-like config object self.option_definitions = Namespace() self.definition_source_list = definition_source_list command_line_value_source = command_line if values_source_list is None: # nothing set, assume defaults if use_admin_controls: values_source_list = (ConfigFileFutureProxy, environment, command_line_value_source) else: values_source_list = (environment, command_line_value_source) # determine which command_line facility to use for help if self.use_auto_help: # we need to iterate through all of our value sources looking for # one that can interact with the user on the commandline. for a_value_source in values_source_list: if inspect.ismodule(a_value_source): handler = \ type_handler_dispatch[a_value_source][0].ValueSource try: # if a value source is able to handle the command line # it will have defined 'command_line_value_source' as # true. Not all values sources may have this attribute if handler.command_line_value_source: handler._setup_auto_help(self) break except AttributeError: # not a commandline source because it doesn't have # the 'command_line_value_source' OR it doesn't have # a method that allows it to setup a help system. # this is OK, we can ignore it and move on until we # find an appropriate source. pass else: # While not actually necessary to have implemented, this # is the case where the value source is not a module. # So we know nothing about its interface. We cannot even # try to use it as a commandline value source. pass admin_tasks_done = False self.keys_blocked_from_output = [ 'help', 'admin.conf', 'admin.dump_conf', 'admin.print_conf', 'admin.strict', 'admin.expose_secrets', ] self.options_banned_from_help = options_banned_from_help if use_admin_controls: admin_options = self._setup_admin_options(values_source_list) self.definition_source_list.append(admin_options) # iterate through the option definitions to create the nested dict # hierarchy of all the options called 'option_definitions' for a_definition_source in self.definition_source_list: try: safe_copy_of_def_source = a_definition_source.safe_copy() except AttributeError: # apparently, the definition source was not in the form of a # Namespace object. This isn't a show stopper, but we don't # know how to make a copy of this object safely: we know from # experience that the stock copy.copy method leads to grief # as many sub-objects within an option definition source can # not be copied that way (classes, for example). # The only action we can take is to trust and continue with the # original copy of the definition source. safe_copy_of_def_source = a_definition_source setup_definitions(safe_copy_of_def_source, self.option_definitions) if use_admin_controls: # the name of the config file needs to be loaded from the command # line prior to processing the rest of the command line options. config_filename = config_filename_from_commandline(self) if (config_filename and ConfigFileFutureProxy in values_source_list): self.option_definitions.admin.conf.default = config_filename self.values_source_list = wrap_with_value_source_api( values_source_list, self) known_keys = self._overlay_expand() self._check_for_mismatches(known_keys) # the app_name, app_version and app_description are to come from # if 'application' option if it is present. If it is not present, # get the app_name,et al, from parameters passed into the constructor. # if those are empty, set app_name, et al, to empty strings try: app_option = self._get_option('application') self.app_name = getattr(app_option.value, 'app_name', '') self.app_version = getattr(app_option.value, 'app_version', '') self.app_description = getattr(app_option.value, 'app_description', '') except NotAnOptionError: # there is no 'application' option, continue to use the # 'app_name' from the parameters passed in, if they exist. pass try: if use_auto_help and self._get_option('help').value: self.output_summary() admin_tasks_done = True except NotAnOptionError: # the current command-line implementation already has a help # mechanism of its own that doesn't require the use of a # option in configman. This error is ignorable pass # keys that end with a "$" are called "blocked_by_suffix". # This means that these options are not to be written out to # configuration files. keys_blocked_by_suffix = [ key for key in self.option_definitions.keys_breadth_first() if key.endswith('$') ] self.keys_blocked_from_output.extend(keys_blocked_by_suffix) if use_admin_controls and self._get_option('admin.print_conf').value: self.print_conf() admin_tasks_done = True if use_admin_controls and self._get_option('admin.dump_conf').value: self.dump_conf() admin_tasks_done = True if quit_after_admin and admin_tasks_done: sys.exit()
def __init__( self, definition_source=None, values_source_list=None, argv_source=None, #use_config_files=True, use_auto_help=True, use_admin_controls=True, quit_after_admin=True, options_banned_from_help=None, app_name='', app_version='', app_description='', config_pathname='.', config_optional=True, value_source_object_hook=DotDict, ): """create and initialize a configman object. parameters: definition_source - a namespace or list of namespaces from which configman is to fetch the definitions of the configuration parameters. values_source_list - (optional) a hierarchical list of sources for values for the configuration parameters. As values are copied from these sources, conficting values are resolved with sources on the right getting preference over sources on the left. argv_source - if the values_source_list contains a commandline source, this value is an alternative source for actual command line arguments. Useful for testing or preprocessing command line arguments. use_auto_help - set to True if configman is to automatically set up help output for command line invocations. use_admin_controls - configman can add command line flags that it interprets independently of the app defined arguments. True enables this capability, while, False supresses it. quit_after_admin - if True and admin controls are enabled and used, call sys.exit to end the app. This is useful to stop the app from running if all that was done was to write a config file or stop after help. options_banned_from_help - a list of strings that will censor the output of help to prevent specified options from being listed in the help output. This is useful for hiding debug or secret command line arguments. app_name - assigns a name to the app. This is used in help output and as a default basename for config files. app_version - assigns a version for the app used help output. app_description - assigns a description for the app to be used in the help output. config_pathname - a hard coded path to the directory of or the full path and name of the configuration file. config_optional - a boolean indicating if a missing default config file is optional. Note: this is only for the default config file. If a config file is specified on the commandline, it _must_ exist. value_source_object_hook - a class used for the internal representation of a value source. This is used to enable any special processing, like key translations. """ # instead of allowing mutables as default keyword argument values... if definition_source is None: definition_source_list = [] elif ( isinstance(definition_source, collections.Sequence) and not isinstance(definition_source, basestring) ): definition_source_list = list(definition_source) else: definition_source_list = [definition_source] if argv_source is None: self.argv_source = sys.argv[1:] self.app_invocation_name = sys.argv[0] else: self.argv_source = argv_source self.app_invocation_name = app_name if options_banned_from_help is None: options_banned_from_help = ['application'] self.config_pathname = config_pathname self.config_optional = config_optional self.value_source_object_hook = value_source_object_hook self.app_name = app_name self.app_version = app_version self.app_description = app_description self.args = [] # extra commandline arguments that are not switches # will be stored here. self._config = None # eventual container for DOM-like config object self.option_definitions = Namespace() self.definition_source_list = definition_source_list if values_source_list is None: # nothing set, assume defaults if use_admin_controls: values_source_list = ( ConfigFileFutureProxy, environment, command_line ) else: values_source_list = ( environment, command_line ) admin_tasks_done = False self.admin_controls_list = [ 'help', 'admin.conf', 'admin.dump_conf', 'admin.print_conf', 'admin.strict', 'admin.expose_secrets', ] self.options_banned_from_help = options_banned_from_help if use_auto_help: self._setup_auto_help() if use_admin_controls: admin_options = self._setup_admin_options(values_source_list) self.definition_source_list.append(admin_options) # iterate through the option definitions to create the nested dict # hierarchy of all the options called 'option_definitions' for a_definition_source in self.definition_source_list: try: safe_copy_of_def_source = a_definition_source.safe_copy() except AttributeError: # apparently, the definition source was not in the form of a # Namespace object. This isn't a show stopper, but we don't # know how to make a copy of this object safely: we know from # experience that the stock copy.copy method leads to grief # as many sub-objects within an option definition source can # not be copied that way (classes, for example). # The only action we can take is to trust and continue with the # original copy of the definition source. safe_copy_of_def_source = a_definition_source setup_definitions( safe_copy_of_def_source, self.option_definitions ) if use_admin_controls: # the name of the config file needs to be loaded from the command # line prior to processing the rest of the command line options. config_filename = config_filename_from_commandline(self) if ( config_filename and ConfigFileFutureProxy in values_source_list ): self.option_definitions.admin.conf.default = config_filename self.values_source_list = wrap_with_value_source_api( values_source_list, self ) known_keys = self._overlay_expand() self._check_for_mismatches(known_keys) # the app_name, app_version and app_description are to come from # if 'application' option if it is present. If it is not present, # get the app_name,et al, from parameters passed into the constructor. # if those are empty, set app_name, et al, to empty strings try: app_option = self._get_option('application') self.app_name = getattr(app_option.value, 'app_name', '') self.app_version = getattr(app_option.value, 'app_version', '') self.app_description = getattr( app_option.value, 'app_description', '' ) except NotAnOptionError: # there is no 'application' option, continue to use the # 'app_name' from the parameters passed in, if they exist. pass if use_auto_help and self._get_option('help').value: self.output_summary() admin_tasks_done = True if use_admin_controls and self._get_option('admin.print_conf').value: self.print_conf() admin_tasks_done = True if use_admin_controls and self._get_option('admin.dump_conf').value: self.dump_conf() admin_tasks_done = True if quit_after_admin and admin_tasks_done: sys.exit()