From be251f04d3006dbd3539ab529ed15c33edbad71b Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 20 Nov 2023 18:16:23 -0600 Subject: [PATCH] Add `get_config_paths()` function, split off from `make_config()` break the latter into steps so we can swap them out more easily --- src/wuttjamaican/conf.py | 201 ++++++++++++++++++++++++++++++--------- 1 file changed, 156 insertions(+), 45 deletions(-) diff --git a/src/wuttjamaican/conf.py b/src/wuttjamaican/conf.py index bac6b2e..9b43f49 100644 --- a/src/wuttjamaican/conf.py +++ b/src/wuttjamaican/conf.py @@ -62,10 +62,10 @@ class WuttaConfig: :param files: List of file paths from which to read config values. - :param appname: This string forms the basis of certain other - things, namely some of the config keys which will be checked to - determine default behavior of the config object itself (if they - are not specified via constructor). + :param defaults: Initial values to use as defaults. This gets + converted to :attr:`defaults` during construction. + + :param appname: Value to assign for :attr:`appname`. :param usedb: Flag indicating whether config values should ever be looked up from the DB. Note that you can override this when @@ -75,8 +75,40 @@ class WuttaConfig: preferred over the values from INI files or app defaults. Note that you can override this when calling :meth:`get()`. + :param configure_logging: Flag indicating whether logging should + be configured during object construction. If not specified, + the config values will determine behavior. + Attributes available on the config instance: + .. attribute:: appname + + Code-friendly name ("key") for the app. This is used as the + basis for various config settings and will therefore determine + what is returned from :meth:`get_app()` etc. + + For instance the default ``appname`` value is ``'wutta'`` which + means a sample config file might look like: + + .. code-block:: ini + + [wutta] + app.handler = wuttjamaican.app:AppHandler + + [wutta.db] + default.url = sqlite:// + + But if the ``appname`` value is e.g. ``'rattail'`` then the + sample config should instead look like: + + .. code-block:: ini + + [rattail] + app.handler = wuttjamaican.app:AppHandler + + [rattail.db] + default.url = sqlite:// + .. attribute:: configuration Reference to the @@ -553,36 +585,45 @@ def generic_default_files(appname): ] -def make_config( +def get_config_paths( files=None, plus_files=None, - appname='wutta', env_files_name=None, env_plus_files_name=None, env=None, default_files=None, - usedb=None, - preferdb=None, - extend=True, - extension_entry_points=None): + appname='wutta'): """ - Returns a new config object (presumably for global use), - initialized per the given parameters and (usually) further - modified by all registered config extensions. + This function determines which files should ultimately be provided + to the config constructor. It is normally called by + :func:`make_config()`. - :param files: Config file path(s) to be loaded. If not specified, - then some "default" behavior will be attempted. (This will - check for env var or fallback to system default paths. Or you - can override all that by specifying some path(s) here.) + In short, the files to be used are determined by typical priority: - :param plus_files: Additional config path(s) to be loaded. You - may specify a "config tweak" file(s) here, and leave ``files`` - empty, to get "defaults plus tweak" behavior. + * function params - ``files`` and ``plus_files`` + * environment variables - e.g. ``WUTTA_CONFIG_FILES`` + * app defaults - e.g. :func:`generic_default_files()` - :param appname: Optional "app name" to use as basis for other - things - namely, constructing the default config file paths - etc. For instance the default ``appname`` value is ``'wutta'`` - which leads to default env vars like ``WUTTA_CONFIG_FILES``. + The "main" and so-called "plus" config files are dealt with + separately, so that "defaults" can be used for the main files, and + any "plus" files are then added to the result. + + In the end it combines everything it finds into a single list. + Note that it does not necessarily check to see if these files + exist. + + :param files: Explicit set of "main" config files. If not + specified, environment variables and/or default lookup will be + done to get the "main" file set. Specify an empty list to + force an empty main file set. + + :param plus_files: Explicit set of "plus" config files. Same + rules apply here as for the ``files`` param. + + :param appname: The "app name" to use as basis for other things - + namely, constructing the default config file paths etc. For + instance the default ``appname`` value is ``'wutta'`` which + leads to default env vars like ``WUTTA_CONFIG_FILES``. :param env_files_name: Name of the environment variable to read, if ``files`` is not specified. The default is @@ -592,34 +633,38 @@ def make_config( read, if ``plus_files`` is not specified. The default is ``WUTTA_CONFIG_PLUS_FILES`` unless you override ``appname``. - :param env: Optional override for the ``os.environ`` dict. + :param env: Optional environment dict; if not specified + ``os.environ`` is used. - :param default_files: Optional way to identify the "default" file - path(s), if neither ``files`` nor ``env_files_name`` yield - anything. This can be a list of potential file paths, or a - callable which returns such a list. If a callable, it should - accept a single ``appname`` arg. + :param default_files: Optional lookup for "default" file paths. - :param usedb: Passed to the :class:`WuttaConfig` constructor. + This is only used a) for the "main" config file lookup (but not + "plus" files), and b) if neither ``files`` nor the environment + variables yielded anything. - :param preferdb: Passed to the :class:`WuttaConfig` constructor. + If not specified, :func:`generic_default_files()` will be used + for the lookup. - :param extend: Whether to "auto-extend" the config with all - registered extensions. + You may specify a single file path as string, or a list of file + paths, or a callable which returns either of those things. For + example any of these could be used:: - As a general rule, ``make_config()`` should only be called - once, upon app startup. This is because some of the config - extensions may do things which should only happen one time. - However if ``extend=False`` is specified, then no extensions - are invoked, so this may be done multiple times. + mydefaults = '/tmp/something.conf' - (Why anyone would need this, is another question..maybe only - useful for tests.) + mydefaults = [ + '/tmp/something.conf', + '/tmp/else.conf', + ] - :param extension_entry_points: Name of the ``setuptools`` entry - points section, used to identify registered config extensions. - The default is ``wutta.config.extensions`` unless you override - ``appname``. + def mydefaults(appname): + return [ + f"/tmp/{appname}.conf", + f"/tmp/{appname}.ini", + ] + + files = get_config_paths(default_files=mydefaults) + + :returns: List of file paths. """ if env is None: env = os.environ @@ -671,6 +716,72 @@ def make_config( # combine all files files.extend(plus_files) + return files + + +def make_config( + files=None, + plus_files=None, + appname='wutta', + env_files_name=None, + env_plus_files_name=None, + env=None, + default_files=None, + usedb=None, + preferdb=None, + extend=True, + extension_entry_points=None): + """ + Make a new config object (presumably for global use), initialized + per the given parameters and (usually) further modified by all + registered config extensions. + + This function really does 3 things: + + * determine the set of config files to use + * pass those files to config constructor + * apply extensions to the resulting config object + + Some params are described in :func:`get_config_paths()` since they + are passed as-is to that function for the first step. + + :param appname: The "app name" to use as basis for other things - + namely, it affects how config files are located. This name is + also passed to the config constructor at which point it becomes + :attr:`wuttjamaican.conf.WuttaConfig.appname`. + + :param usedb: Passed to the :class:`WuttaConfig` constructor. + + :param preferdb: Passed to the :class:`WuttaConfig` constructor. + + :param extend: Whether to "auto-extend" the config with all + registered extensions. + + As a general rule, ``make_config()`` should only be called + once, upon app startup. This is because some of the config + extensions may do things which should only happen one time. + However if ``extend=False`` is specified, then no extensions + are invoked, so this may be done multiple times. + + (Why anyone would need this, is another question..maybe only + useful for tests.) + + :param extension_entry_points: Name of the ``setuptools`` entry + points section, used to identify registered config extensions. + The default is ``wutta.config.extensions`` unless you override + ``appname``. + + :returns: The new config object. + """ + # collect file paths + files = get_config_paths( + files=files, + plus_files=plus_files, + appname=appname, + env_files_name=env_files_name, + env_plus_files_name=env_plus_files_name, + env=env, + default_files=default_files) # make config object config = WuttaConfig(files, appname=appname,