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)
|
||||
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):
|
||||
"""
|
||||
Get the configured :term:`db handler`.
|
||||
|
@ -1021,3 +1102,10 @@ class GenericHandler:
|
|||
See also :attr:`AppHandler.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.conf import WuttaConfig
|
||||
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):
|
||||
|
@ -546,6 +554,59 @@ app_title = WuttaTest
|
|||
auth = self.app.get_auth_handler()
|
||||
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):
|
||||
try:
|
||||
from wuttjamaican.db.handler import DatabaseHandler
|
||||
|
@ -684,15 +745,17 @@ class TestAppProvider(TestCase):
|
|||
self.assertEqual(self.app.foo_value, 'bar')
|
||||
|
||||
|
||||
class TestGenericHandler(TestCase):
|
||||
class TestGenericHandler(ConfigTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.config = WuttaConfig(appname='wuttatest')
|
||||
self.app = mod.AppHandler(self.config)
|
||||
self.config._app = self.app
|
||||
def make_config(self, **kw):
|
||||
kw.setdefault('appname', 'wuttatest')
|
||||
return super().make_config(**kw)
|
||||
|
||||
def test_constructor(self):
|
||||
handler = mod.GenericHandler(self.config)
|
||||
self.assertIs(handler.config, self.config)
|
||||
self.assertIs(handler.app, self.app)
|
||||
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