fix: add get_batch_handler()
method for app handler
also `get_batch_handler_specs()`
This commit is contained in:
parent
174a17dd5e
commit
a302f323af
|
@ -842,6 +842,87 @@ class AppHandler:
|
||||||
self.handlers['auth'] = factory(self.config, **kwargs)
|
self.handlers['auth'] = factory(self.config, **kwargs)
|
||||||
return self.handlers['auth']
|
return self.handlers['auth']
|
||||||
|
|
||||||
|
def get_batch_handler(self, key, default=None, **kwargs):
|
||||||
|
"""
|
||||||
|
Get the configured :term:`batch handler` for the given type.
|
||||||
|
|
||||||
|
:param key: Unique key designating the :term:`batch type`.
|
||||||
|
|
||||||
|
:param default: Spec string to use as the default, if none is
|
||||||
|
configured.
|
||||||
|
|
||||||
|
:returns: :class:`~wuttjamaican.batch.BatchHandler` instance
|
||||||
|
for the requested type. If no spec can be determined, a
|
||||||
|
``KeyError`` is raised.
|
||||||
|
"""
|
||||||
|
spec = self.config.get(f'{self.appname}.batch.{key}.handler.spec',
|
||||||
|
default=default)
|
||||||
|
if not spec:
|
||||||
|
spec = self.config.get(f'{self.appname}.batch.{key}.handler.default_spec')
|
||||||
|
if not spec:
|
||||||
|
raise KeyError(f"handler spec not found for batch key: {key}")
|
||||||
|
factory = self.load_object(spec)
|
||||||
|
return factory(self.config, **kwargs)
|
||||||
|
|
||||||
|
def get_batch_handler_specs(self, key, default=None):
|
||||||
|
"""
|
||||||
|
Get the :term:`spec` strings for all available handlers of the
|
||||||
|
given batch type.
|
||||||
|
|
||||||
|
:param key: Unique key designating the :term:`batch type`.
|
||||||
|
|
||||||
|
:param default: Default spec string(s) to include, even if not
|
||||||
|
registered. Can be a string or list of strings.
|
||||||
|
|
||||||
|
:returns: List of batch handler spec strings.
|
||||||
|
|
||||||
|
This will gather available spec strings from the following:
|
||||||
|
|
||||||
|
First, the ``default`` as provided by caller.
|
||||||
|
|
||||||
|
Second, the default spec from config, if set; for example:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
[wutta.batch]
|
||||||
|
inventory.handler.default_spec = poser.batch.inventory:InventoryBatchHandler
|
||||||
|
|
||||||
|
Third, each spec registered via entry points. For instance in
|
||||||
|
``pyproject.toml``:
|
||||||
|
|
||||||
|
.. code-block:: toml
|
||||||
|
|
||||||
|
[project.entry-points."wutta.batch.inventory"]
|
||||||
|
poser = "poser.batch.inventory:InventoryBatchHandler"
|
||||||
|
|
||||||
|
The final list will be "sorted" according to the above, with
|
||||||
|
the latter registered handlers being sorted alphabetically.
|
||||||
|
"""
|
||||||
|
handlers = []
|
||||||
|
|
||||||
|
# defaults from caller
|
||||||
|
if isinstance(default, str):
|
||||||
|
handlers.append(default)
|
||||||
|
elif default:
|
||||||
|
handlers.extend(default)
|
||||||
|
|
||||||
|
# configured default, if applicable
|
||||||
|
default = self.config.get(f'{self.config.appname}.batch.{key}.handler.default_spec')
|
||||||
|
if default and default not in handlers:
|
||||||
|
handlers.append(default)
|
||||||
|
|
||||||
|
# registered via entry points
|
||||||
|
registered = []
|
||||||
|
for Handler in load_entry_points(f'{self.appname}.batch.{key}').values():
|
||||||
|
spec = Handler.get_spec()
|
||||||
|
if spec not in handlers:
|
||||||
|
registered.append(spec)
|
||||||
|
if registered:
|
||||||
|
registered.sort()
|
||||||
|
handlers.extend(registered)
|
||||||
|
|
||||||
|
return handlers
|
||||||
|
|
||||||
def get_db_handler(self, **kwargs):
|
def get_db_handler(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
Get the configured :term:`db handler`.
|
Get the configured :term:`db handler`.
|
||||||
|
@ -1021,3 +1102,10 @@ class GenericHandler:
|
||||||
See also :attr:`AppHandler.appname`.
|
See also :attr:`AppHandler.appname`.
|
||||||
"""
|
"""
|
||||||
return self.app.appname
|
return self.app.appname
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_spec(cls):
|
||||||
|
"""
|
||||||
|
Returns the class :term:`spec` string for the handler.
|
||||||
|
"""
|
||||||
|
return f'{cls.__module__}:{cls.__name__}'
|
||||||
|
|
|
@ -19,7 +19,15 @@ from wuttjamaican import app as mod
|
||||||
from wuttjamaican.progress import ProgressBase
|
from wuttjamaican.progress import ProgressBase
|
||||||
from wuttjamaican.conf import WuttaConfig
|
from wuttjamaican.conf import WuttaConfig
|
||||||
from wuttjamaican.util import UNSPECIFIED
|
from wuttjamaican.util import UNSPECIFIED
|
||||||
from wuttjamaican.testing import FileTestCase
|
from wuttjamaican.testing import FileTestCase, ConfigTestCase
|
||||||
|
from wuttjamaican.batch import BatchHandler
|
||||||
|
|
||||||
|
|
||||||
|
class MockBatchHandler(BatchHandler):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class AnotherBatchHandler(BatchHandler):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class TestAppHandler(FileTestCase):
|
class TestAppHandler(FileTestCase):
|
||||||
|
@ -546,6 +554,59 @@ app_title = WuttaTest
|
||||||
auth = self.app.get_auth_handler()
|
auth = self.app.get_auth_handler()
|
||||||
self.assertIsInstance(auth, AuthHandler)
|
self.assertIsInstance(auth, AuthHandler)
|
||||||
|
|
||||||
|
def test_get_batch_handler(self):
|
||||||
|
|
||||||
|
# error if handler not found
|
||||||
|
self.assertRaises(KeyError, self.app.get_batch_handler, 'CannotFindMe!')
|
||||||
|
|
||||||
|
# caller can specify default
|
||||||
|
handler = self.app.get_batch_handler('foo', default='wuttjamaican.batch:BatchHandler')
|
||||||
|
self.assertIsInstance(handler, BatchHandler)
|
||||||
|
|
||||||
|
# default can be configured
|
||||||
|
self.config.setdefault('wuttatest.batch.foo.handler.default_spec',
|
||||||
|
'wuttjamaican.batch:BatchHandler')
|
||||||
|
handler = self.app.get_batch_handler('foo')
|
||||||
|
self.assertIsInstance(handler, BatchHandler)
|
||||||
|
|
||||||
|
# preference can be configured
|
||||||
|
self.config.setdefault('wuttatest.batch.foo.handler.spec',
|
||||||
|
'tests.test_app:MockBatchHandler')
|
||||||
|
handler = self.app.get_batch_handler('foo')
|
||||||
|
self.assertIsInstance(handler, MockBatchHandler)
|
||||||
|
|
||||||
|
def test_get_batch_handler_specs(self):
|
||||||
|
|
||||||
|
# empty by default
|
||||||
|
specs = self.app.get_batch_handler_specs('foo')
|
||||||
|
self.assertEqual(specs, [])
|
||||||
|
|
||||||
|
# caller can specify default as string
|
||||||
|
specs = self.app.get_batch_handler_specs('foo', default='wuttjamaican.batch:BatchHandler')
|
||||||
|
self.assertEqual(specs, ['wuttjamaican.batch:BatchHandler'])
|
||||||
|
|
||||||
|
# caller can specify default as list
|
||||||
|
specs = self.app.get_batch_handler_specs('foo', default=['wuttjamaican.batch:BatchHandler',
|
||||||
|
'tests.test_app:MockBatchHandler'])
|
||||||
|
self.assertEqual(specs, ['wuttjamaican.batch:BatchHandler',
|
||||||
|
'tests.test_app:MockBatchHandler'])
|
||||||
|
|
||||||
|
# default can be configured
|
||||||
|
self.config.setdefault('wuttatest.batch.foo.handler.default_spec',
|
||||||
|
'wuttjamaican.batch:BatchHandler')
|
||||||
|
specs = self.app.get_batch_handler_specs('foo')
|
||||||
|
self.assertEqual(specs, ['wuttjamaican.batch:BatchHandler'])
|
||||||
|
|
||||||
|
# the rest come from entry points
|
||||||
|
with patch.object(mod, 'load_entry_points', return_value={
|
||||||
|
'mock': MockBatchHandler,
|
||||||
|
'another': AnotherBatchHandler,
|
||||||
|
}):
|
||||||
|
specs = self.app.get_batch_handler_specs('foo')
|
||||||
|
self.assertEqual(specs, ['wuttjamaican.batch:BatchHandler',
|
||||||
|
'tests.test_app:AnotherBatchHandler',
|
||||||
|
'tests.test_app:MockBatchHandler'])
|
||||||
|
|
||||||
def test_get_db_handler(self):
|
def test_get_db_handler(self):
|
||||||
try:
|
try:
|
||||||
from wuttjamaican.db.handler import DatabaseHandler
|
from wuttjamaican.db.handler import DatabaseHandler
|
||||||
|
@ -684,15 +745,17 @@ class TestAppProvider(TestCase):
|
||||||
self.assertEqual(self.app.foo_value, 'bar')
|
self.assertEqual(self.app.foo_value, 'bar')
|
||||||
|
|
||||||
|
|
||||||
class TestGenericHandler(TestCase):
|
class TestGenericHandler(ConfigTestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def make_config(self, **kw):
|
||||||
self.config = WuttaConfig(appname='wuttatest')
|
kw.setdefault('appname', 'wuttatest')
|
||||||
self.app = mod.AppHandler(self.config)
|
return super().make_config(**kw)
|
||||||
self.config._app = self.app
|
|
||||||
|
|
||||||
def test_constructor(self):
|
def test_constructor(self):
|
||||||
handler = mod.GenericHandler(self.config)
|
handler = mod.GenericHandler(self.config)
|
||||||
self.assertIs(handler.config, self.config)
|
self.assertIs(handler.config, self.config)
|
||||||
self.assertIs(handler.app, self.app)
|
self.assertIs(handler.app, self.app)
|
||||||
self.assertEqual(handler.appname, 'wuttatest')
|
self.assertEqual(handler.appname, 'wuttatest')
|
||||||
|
|
||||||
|
def test_get_spec(self):
|
||||||
|
self.assertEqual(mod.GenericHandler.get_spec(), 'wuttjamaican.app:GenericHandler')
|
||||||
|
|
Loading…
Reference in a new issue