Allow factory override in make_config()
also add `winsvc` param for `get_config_paths()` to support RattailFileMonitor service on windows
This commit is contained in:
parent
ed6a5db452
commit
1431555605
|
@ -620,11 +620,12 @@ def generic_default_files(appname):
|
|||
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,
|
||||
appname='wutta'):
|
||||
winsvc=None):
|
||||
"""
|
||||
This function determines which files should ultimately be provided
|
||||
to the config constructor. It is normally called by
|
||||
|
@ -696,6 +697,42 @@ def get_config_paths(
|
|||
|
||||
files = get_config_paths(default_files=mydefaults)
|
||||
|
||||
:param winsvc: Optional internal name of the Windows service for
|
||||
which the config object is being made.
|
||||
|
||||
This is only needed for true Windows services running via
|
||||
"Python for Windows Extensions" - which probably only includes
|
||||
the Rattail File Monitor service.
|
||||
|
||||
In this context there is no way to tell the app which config
|
||||
files to read on startup, so it can only look for "default"
|
||||
files. But by passing a ``winsvc`` name to this function, it
|
||||
will first load the default config file, then read a particular
|
||||
value to determine the "real" config file(s) it should use.
|
||||
|
||||
So for example on Windows you might have a config file at
|
||||
``C:\\ProgramData\\rattail\\rattail.conf`` with contents:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[rattail.config]
|
||||
winsvc.RattailFileMonitor = C:\\ProgramData\\rattail\\filemon.conf
|
||||
|
||||
And then ``C:\\ProgramData\\rattail\\filemon.conf`` would have
|
||||
the actual config for the filemon service.
|
||||
|
||||
When the service starts it calls::
|
||||
|
||||
make_config(winsvc='RattailFileMonitor')
|
||||
|
||||
which first reads the ``rattail.conf`` file (since that is the
|
||||
only sensible default), but then per config it knows to swap
|
||||
that out for ``filemon.conf`` at startup. This is because it
|
||||
finds a config value matching the requested service name. The
|
||||
end result is as if it called this instead::
|
||||
|
||||
make_config(files=[r'C:\\ProgramData\\rattail\\filemon.conf'])
|
||||
|
||||
:returns: List of file paths.
|
||||
"""
|
||||
if env is None:
|
||||
|
@ -748,6 +785,22 @@ def get_config_paths(
|
|||
|
||||
# combine all files
|
||||
files.extend(plus_files)
|
||||
|
||||
# when running as a proper windows service, must first read
|
||||
# "default" file(s) and then consult config to see which file
|
||||
# should "really" be used. because there isn't a way to specify
|
||||
# which config file as part of the actual service definition in
|
||||
# windows, so the service name is used for magic lookup here.
|
||||
if winsvc:
|
||||
config = configparser.SafeConfigParser()
|
||||
config.read(files)
|
||||
section = f'{appname}.config'
|
||||
if config.has_section(section):
|
||||
option = f'winsvc.{winsvc}'
|
||||
if config.has_option(section, option):
|
||||
# replace file paths with whatever config value says
|
||||
files = parse_list(config.get(section, option))
|
||||
|
||||
return files
|
||||
|
||||
|
||||
|
@ -759,10 +812,13 @@ def make_config(
|
|||
env_plus_files_name=None,
|
||||
env=None,
|
||||
default_files=None,
|
||||
winsvc=None,
|
||||
usedb=None,
|
||||
preferdb=None,
|
||||
factory=None,
|
||||
extend=True,
|
||||
extension_entry_points=None):
|
||||
extension_entry_points=None,
|
||||
**kwargs):
|
||||
"""
|
||||
Make a new config object (presumably for global use), initialized
|
||||
per the given parameters and (usually) further modified by all
|
||||
|
@ -771,20 +827,25 @@ def make_config(
|
|||
This function really does 3 things:
|
||||
|
||||
* determine the set of config files to use
|
||||
* pass those files to config constructor
|
||||
* pass those files to config factory
|
||||
* 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 appname: The :term:`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 factory at which point it
|
||||
becomes :attr:`~wuttjamaican.conf.WuttaConfig.appname`.
|
||||
|
||||
:param usedb: Passed to the :class:`WuttaConfig` constructor.
|
||||
:param usedb: Passed to the config factory; becomes
|
||||
:attr:`~wuttjamaican.conf.WuttaConfig.usedb`.
|
||||
|
||||
:param preferdb: Passed to the :class:`WuttaConfig` constructor.
|
||||
:param preferdb: Passed to the config factory; becomes
|
||||
:attr:`~wuttjamaican.conf.WuttaConfig.preferdb`.
|
||||
|
||||
:param factory: Optional factory to use when making the object.
|
||||
Default factory is :class:`WuttaConfig`.
|
||||
|
||||
:param extend: Whether to "auto-extend" the config with all
|
||||
registered extensions.
|
||||
|
@ -813,11 +874,15 @@ def make_config(
|
|||
env_files_name=env_files_name,
|
||||
env_plus_files_name=env_plus_files_name,
|
||||
env=env,
|
||||
default_files=default_files)
|
||||
default_files=default_files,
|
||||
winsvc=winsvc)
|
||||
|
||||
# make config object
|
||||
config = WuttaConfig(files, appname=appname,
|
||||
usedb=usedb, preferdb=preferdb)
|
||||
if not factory:
|
||||
factory = WuttaConfig
|
||||
config = factory(files, appname=appname,
|
||||
usedb=usedb, preferdb=preferdb,
|
||||
**kwargs)
|
||||
|
||||
# maybe extend config object
|
||||
if extend:
|
||||
|
|
|
@ -417,6 +417,18 @@ class TestGenericDefaultFiles(TestCase):
|
|||
self.assertEqual(len(files), 0)
|
||||
|
||||
|
||||
class TestGetConfigPaths(FileConfigTestCase):
|
||||
|
||||
def test_winsvc(self):
|
||||
myconf = self.write_file('my.conf', """
|
||||
[wutta.config]
|
||||
winsvc.RattailFileMonitor = /path/to/other/file
|
||||
""")
|
||||
|
||||
files = conf.get_config_paths(files=[myconf], winsvc='RattailFileMonitor')
|
||||
self.assertEqual(files, ['/path/to/other/file'])
|
||||
|
||||
|
||||
class TestMakeConfig(FileConfigTestCase):
|
||||
|
||||
# nb. we use appname='wuttatest' in this suite to avoid any
|
||||
|
|
Loading…
Reference in a new issue