diff --git a/configman/__init__.py b/configman/__init__.py index 9ec0c2c..37cb569 100644 --- a/configman/__init__.py +++ b/configman/__init__.py @@ -36,7 +36,7 @@ # # ***** END LICENSE BLOCK ***** -__version__ = '1.0' +__version__ = '1.0.1' # Having these here makes it possible to easily import once configman is # installed. @@ -45,9 +45,11 @@ # from configman import Namespace, ConfigurationManager # -from .config_manager import ConfigurationManager +from .config_manager import ConfigurationManager, RequiredConfig from .namespace import Namespace +from .converters import class_converter, regex_converter, timedelta_converter + # constants used to refer to Value Source concepts generically from config_file_future_proxy import ConfigFileFutureProxy diff --git a/configman/converters.py b/configman/converters.py index 36bc1fa..03d7564 100644 --- a/configman/converters.py +++ b/configman/converters.py @@ -42,7 +42,10 @@ import types import inspect -import datetime_util as dtu +from .datetime_util import datetime_from_ISO_string as datetime_converter +from .datetime_util import date_from_ISO_string as date_converter + +import datetime_util #------------------------------------------------------------------------------ @@ -187,18 +190,19 @@ def regex_converter(input_str): compiled_regexp_type = type(re.compile(r'x')) #------------------------------------------------------------------------------ -from_string_converters = {int: int, - float: float, - str: str, - unicode: unicode, - bool: boolean_converter, - datetime.datetime: dtu.datetime_from_ISO_string, - datetime.date: dtu.date_from_ISO_string, - datetime.timedelta: timedelta_converter, - type: class_converter, - types.FunctionType: class_converter, - compiled_regexp_type: regex_converter, - } +from_string_converters = { + int: int, + float: float, + str: str, + unicode: unicode, + bool: boolean_converter, + datetime.datetime: datetime_converter, + datetime.date: date_converter, + datetime.timedelta: timedelta_converter, + type: class_converter, + types.FunctionType: class_converter, + compiled_regexp_type: regex_converter, +} #------------------------------------------------------------------------------ @@ -215,18 +219,19 @@ def py_obj_to_str(a_thing): #------------------------------------------------------------------------------ -to_string_converters = {int: str, - float: str, - str: str, - unicode: unicode, - bool: lambda x: 'True' if x else 'False', - datetime.datetime: dtu.datetime_to_ISO_string, - datetime.date: dtu.date_to_ISO_string, - datetime.timedelta: dtu.timedelta_to_str, - type: py_obj_to_str, - types.FunctionType: py_obj_to_str, - compiled_regexp_type: lambda x: x.pattern, - } +to_string_converters = { + int: str, + float: str, + str: str, + unicode: unicode, + bool: lambda x: 'True' if x else 'False', + datetime.datetime: datetime_util.datetime_to_ISO_string, + datetime.date: datetime_util.date_to_ISO_string, + datetime.timedelta: datetime_util.timedelta_to_str, + type: py_obj_to_str, + types.FunctionType: py_obj_to_str, + compiled_regexp_type: lambda x: x.pattern, +} #------------------------------------------------------------------------------ diff --git a/demo/advanced_demo2.py b/demo/advanced_demo2.py index 75b4470..1191c9f 100755 --- a/demo/advanced_demo2.py +++ b/demo/advanced_demo2.py @@ -48,9 +48,7 @@ import contextlib import threading -import configman as cm -import configman.config_manager as config_man - +from configman import RequiredConfig, ConfigurationManager, Namespace #------------------------------------------------------------------------------ class FakeDatabaseConnection(): @@ -84,13 +82,13 @@ def rollback(self): #============================================================================== -class PGTransaction(config_man.RequiredConfig): +class PGTransaction(RequiredConfig): """a configman complient class for setup of a Postgres transaction""" #-------------------------------------------------------------------------- # configman parameter definition section # here we're setting up the minimal parameters required for connecting # to a database. - required_config = cm.Namespace() + required_config = Namespace() required_config.add_option( name='database_host', default='localhost', @@ -235,7 +233,7 @@ def transaction_factory(config, local_config, args): if __name__ == "__main__": - definition_source = cm.Namespace() + definition_source = Namespace() # setup the option that will specify which database connection/transaction # factory will be used. Condfig man will query the class for additional # config options for the database connection parameters. @@ -252,9 +250,9 @@ def transaction_factory(config, local_config, args): function=transaction_factory ) - c = cm.ConfigurationManager(definition_source, - app_name='demo4', - app_description=__doc__) + c = ConfigurationManager(definition_source, + app_name='demo4', + app_description=__doc__) with c.context() as config: print "\n**** First query will succeed" with config.db_transaction() as trans: diff --git a/demo/advanced_demo3.py b/demo/advanced_demo3.py index 6098e56..8c63154 100755 --- a/demo/advanced_demo3.py +++ b/demo/advanced_demo3.py @@ -81,8 +81,7 @@ import time import socket -import configman as cm -import configman.config_manager as config_man +from configman import RequiredConfig, ConfigurationManager, Namespace #------------------------------------------------------------------------------ @@ -140,13 +139,13 @@ def rollback(self): #============================================================================== -class Postgres(config_man.RequiredConfig): +class Postgres(RequiredConfig): """a configman compliant class for setup of Postgres transactions""" #-------------------------------------------------------------------------- # configman parameter definition section # here we're setting up the minimal parameters required for connecting # to a database. - required_config = cm.Namespace() + required_config = Namespace() required_config.add_option( name='database_host', default='localhost', @@ -333,8 +332,8 @@ def transaction_factory(config, local_config, args): #============================================================================== -class TransactionExecutor(config_man.RequiredConfig): - required_config = cm.Namespace() +class TransactionExecutor(RequiredConfig): + required_config = Namespace() # setup the option that will specify which database connection/transaction # factory will be used. Config man will query the class for additional # config options for the database connection parameters. @@ -363,7 +362,7 @@ def do_transaction(self, function, *args, **kwargs): #============================================================================== class TransactionExecutorWithBackoff(TransactionExecutor): # back off times - required_config = cm.Namespace() + required_config = Namespace() required_config.add_option('backoff_delays', default=[2, 4, 6, 10, 15], doc='delays in seconds between retries', @@ -427,14 +426,14 @@ def query2(conn): #============================================================================== if __name__ == "__main__": - definition_source = cm.Namespace() + definition_source = Namespace() definition_source.add_option('transaction_executor_class', default=TransactionExecutorWithBackoff, doc='a class that will execute transactions') - c = cm.ConfigurationManager(definition_source, - app_name='advanced_demo_3', - app_description=__doc__) + c = ConfigurationManager(definition_source, + app_name='advanced_demo_3', + app_description=__doc__) with c.context() as config: # the configuration has a class that can execute transactions diff --git a/demo/demo1.py b/demo/demo1.py index d9948fa..616eec6 100755 --- a/demo/demo1.py +++ b/demo/demo1.py @@ -45,7 +45,7 @@ # we run the application. import sys -import configman as cm +from configman import ConfigurationManager, Namespace # the following three functions are the business logic of the application. @@ -63,7 +63,7 @@ def upper(x): # create the definitions for the parameters that are to come from # the command line or config file. First we create a container called a # namespace for the configuration parameters. -definition_source = cm.Namespace() +definition_source = Namespace() # now we start adding options to the container. This first option # defines on the command line '--text' and '-t' swiches. For configuration # files, this defines a top level entry of 'text' and assigns the value @@ -87,9 +87,9 @@ def upper(x): # any values loaded from a config file specified by the --admin.conf command # line switch, values from the os environment and finally overrides from the # commandline. -c = cm.ConfigurationManager(definition_source, - app_name='demo1', - app_description=__doc__) +c = ConfigurationManager(definition_source, + app_name='demo1', + app_description=__doc__) # fetch the DOM-like instance that gives access to the configuration info config = c.get_config() diff --git a/demo/demo1j.py b/demo/demo1j.py index 350691b..7a8ff05 100755 --- a/demo/demo1j.py +++ b/demo/demo1j.py @@ -46,7 +46,7 @@ # we run the application. import sys -import configman as cm +from configman import ConfigurationManager # the following three functions are the business logic of the application. @@ -74,9 +74,9 @@ def upper(x): # any values loaded from a config file specified by the --admin.conf command # line switch, values from the os environment and finally overrides from the # commandline. -c = cm.ConfigurationManager(definition_source, - app_name='demo1j', - app_description=__doc__) +c = ConfigurationManager(definition_source, + app_name='demo1j', + app_description=__doc__) # fetch the DOM-like instance that gives access to the configuration info config = c.get_config() diff --git a/demo/demo2.py b/demo/demo2.py index 51c1c6d..14e36e1 100755 --- a/demo/demo2.py +++ b/demo/demo2.py @@ -47,8 +47,9 @@ # application is specified in configuration. The last line of the file invokes # the action. -import configman as cm -import configman.converters as conv +from configman import ConfigurationManager, Namespace +from configman import environment, command_line +from configman.converters import class_converter # the following three functions are the business logic of the application. @@ -74,7 +75,7 @@ def action_converter(action): return action_dispatch[action] except KeyError: try: - f = conv.class_converter(action) + f = class_converter(action) except Exception: raise Exception("'%s' is not a valid action" % action) if f in action_dispatch.values(): @@ -83,7 +84,7 @@ def action_converter(action): # create the definitions for the parameters that are to come from # the command line or config file. -definition_source = cm.Namespace() +definition_source = Namespace() definition_source.add_option('text', 'Socorro Forever', 'the text input value', @@ -108,17 +109,17 @@ def action_converter(action): # config file of their own. After reading the hard coded config file, the # ConfigurationManager will apply values it got from the environment and then, # finally, apply values that it gets from the command line. -value_sources = ('demo2.ini', cm.environment, cm.command_line) +value_sources = ('demo2.ini', environment, command_line) # the value_sources sequence can contian any object that is a derivation of the # type collections.Mapping, a module, or instances of any of the registered # handlers. cm.environment is just an alias for os.environ. cm.command_line is # an alias for the 'getopt' module, a registerd handler. # set up the manager with the definitions and values -c = cm.ConfigurationManager(definition_source, - value_sources, - app_name='demo2', - app_description=__doc__) +c = ConfigurationManager(definition_source, + value_sources, + app_name='demo2', + app_description=__doc__) # fetch the DotDict version of the values config = c.get_config() diff --git a/demo/demo3.py b/demo/demo3.py index bfbfa01..e382eb2 100755 --- a/demo/demo3.py +++ b/demo/demo3.py @@ -56,12 +56,11 @@ # 5) the app class defines a parameterless 'main' function that executes the # business logic of the application -import configman as cm -import configman.config_manager as config_man +from configman import RequiredConfig, Namespace # the following class embodies the business logic of the application. -class Demo3App(config_man.RequiredConfig): +class Demo3App(RequiredConfig): app_name = 'demo3_app' app_version = '0.1' @@ -69,7 +68,7 @@ class Demo3App(config_man.RequiredConfig): # create the definitions for the parameters that are to come from # the command line or config file. - required_config = cm.Namespace() + required_config = Namespace() required_config.add_option('text', 'Socorro Forever', 'the input value', short_form='t') diff --git a/demo/dyn_app.py b/demo/dyn_app.py index 1025a6b..d70f66f 100755 --- a/demo/dyn_app.py +++ b/demo/dyn_app.py @@ -46,13 +46,12 @@ # another. It offers fake versions of Postgres, MySQL and HBase as the # data sources and sinks. -import configman as cm -import configman.config_manager as config_man -import configman.converters as conv +from configman import RequiredConfig, Namespace +from configman.converters import class_converter # the following class embodies the business logic of the application. -class DynApp(config_man.RequiredConfig): +class DynApp(RequiredConfig): app_name = 'dyn' app_version = '0.1' @@ -60,23 +59,23 @@ class DynApp(config_man.RequiredConfig): # create the definitions for the parameters that are to come from # the command line or config file. - required_config = cm.Namespace() + required_config = Namespace() # we're going to have two namespaces, one for the source and another # for the destination. We use separate namespaces to avoid name # collisions. For example, both the source and destination are going # to have 'hostname' and we don't want to mix them up. - required_config.source = s = cm.Namespace() - required_config.destination = d = cm.Namespace() + required_config.source = s = Namespace() + required_config.destination = d = Namespace() # when the data source class is loaded, it will bring in more # configuration parameters gleaned from the loaded class itself. s.add_option('storage', 'data_store.CannedDataSource', 'the class to handle database interaction for input', short_form='s', - from_string_converter=conv.class_converter) + from_string_converter=class_converter) d.add_option('storage', 'data_store.CannedDataSink', 'the class to handle database interaction for output', short_form='d', - from_string_converter=conv.class_converter) + from_string_converter=class_converter) def __init__(self, config): super(DynApp, self).__init__() diff --git a/demo/generic_app.py b/demo/generic_app.py index 440941a..aa51525 100755 --- a/demo/generic_app.py +++ b/demo/generic_app.py @@ -43,14 +43,16 @@ import inspect import configman as cm -import configman.converters as conv +from configman import ConfigurationManager, Namespace +from configman import ConfigFileFutureProxy, environment, command_line +from configman.converters import class_converter # This main function will load an application object, initialize it and then # call its 'main' function def main(app_object=None): if isinstance(app_object, basestring): - app_object = conv.class_converter(app_object) + app_object = class_converter(app_object) # the only config parameter is a special one that refers to a class or # module that defines an application. In order to qualify, a class must @@ -58,13 +60,13 @@ def main(app_object=None): # input parameter. It must also have a 'main' function that accepts no # parameters. For a module to be acceptable, it must have a main # function that accepts a DotDict derivative as its input parameter. - app_definition = cm.Namespace() - app_definition.admin = admin = cm.Namespace() + app_definition = Namespace() + app_definition.admin = admin = Namespace() admin.add_option('application', doc='the fully qualified module or class of the ' 'application', default=app_object, - from_string_converter=conv.class_converter + from_string_converter=class_converter ) app_name = getattr(app_object, 'app_name', 'unknown') app_version = getattr(app_object, 'app_version', '0.0') @@ -77,22 +79,22 @@ def main(app_object=None): # First the os.environ values will be applied. Then any values from an ini # file parsed by getopt. Finally any values supplied on the command line # will be applied. - value_sources = (cm.ConfigFileFutureProxy, # alias for allowing the user - # to specify a config file on - # the command line - cm.environment, # alias for os.environ - cm.command_line) # alias for getopt + value_sources = (ConfigFileFutureProxy, # alias for allowing the user + # to specify a config file on + # the command line + environment, # alias for os.environ + command_line) # alias for getopt # set up the manager with the definitions and values # it isn't necessary to provide the app_name because the # app_object passed in or loaded by the ConfigurationManager will alredy # have that information. - config_manager = cm.ConfigurationManager(app_definition, - value_sources, - app_name=app_name, - app_version=app_version, - app_description=app_description, - ) + config_manager = ConfigurationManager(app_definition, + value_sources, + app_name=app_name, + app_version=app_version, + app_description=app_description, + ) config = config_manager.get_config() app_object = config.admin.application