From b59e83907c00411d9289ba10d4aa9fc59b4ccc4a Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Fri, 24 Nov 2023 18:45:10 -0600 Subject: [PATCH] Add config extension class, tests, docs --- docs/narr/config/object.rst | 39 +++++++++++++++++++++++++++++++++++++ src/wuttjamaican/conf.py | 16 +++++++++++++++ tests/test_conf.py | 9 +++++++++ 3 files changed, 64 insertions(+) diff --git a/docs/narr/config/object.rst b/docs/narr/config/object.rst index e36d1c4..b792133 100644 --- a/docs/narr/config/object.rst +++ b/docs/narr/config/object.rst @@ -54,3 +54,42 @@ to solve the "chicken-vs-egg" problem:: config = make_config() app = config.get_app() + + +Extending the Config Object +--------------------------- + +Some packages may need to "extend" the config object somehow, to add +various attributes which they may reference later when certain code +runs. + +A typical example would be for an "integration" package, which is +responsible for communicating with a third party database. This +package might extend the config by loading some database connections +based on config values, and attaching those directly to the config +object (and usually, configuring a ``Session`` class). + +But here is a simpler example; add this to e.g. ``poser/config.py``:: + + from wuttjamaican.conf import WuttaConfigExtension + + class PoserConfigExtension(WuttaConfigExtension): + """ + Custom config extension for Poser + """ + key = 'poser' + + def configure(self, config): + foo = config.setdefault('poser.foo', 'bar') + config.poser_foo = foo + +Then you must register an :term:`entry point` in your ``setup.cfg``: + +.. code-block:: ini + + [options.entry_points] + wutta.config.extensions = + poser = poser.config:PoserConfigExtension + +After your ``poser`` package is installed, the extension logic should +automatically run when the config object is being made. diff --git a/src/wuttjamaican/conf.py b/src/wuttjamaican/conf.py index 542723a..ee4f237 100644 --- a/src/wuttjamaican/conf.py +++ b/src/wuttjamaican/conf.py @@ -573,6 +573,22 @@ class WuttaConfig: return self.app +class WuttaConfigExtension: + """ + Base class for all config extensions. + """ + key = None + + def __repr__(self): + return f"WuttaConfigExtension(key={self.key})" + + def configure(self, config): + """ + Subclass should override this method, to extend the config + object in any way necessary. + """ + + def generic_default_files(appname): """ Returns a list of default file paths which might be used for diff --git a/tests/test_conf.py b/tests/test_conf.py index 15a5c2d..dbc2bd6 100644 --- a/tests/test_conf.py +++ b/tests/test_conf.py @@ -382,6 +382,15 @@ configure_logging = true self.assertIs(type(app), AppHandler) +class TestWuttaConfigExtension(TestCase): + + def test_basic(self): + config = conf.WuttaConfig() + ext = conf.WuttaConfigExtension() + self.assertIsNone(ext.key) + self.assertEqual(repr(ext), 'WuttaConfigExtension(key=None)') + + class TestGenericDefaultFiles(TestCase): def test_linux(self):