fix: add get_batch_handler() method for app handler
				
					
				
			also `get_batch_handler_specs()`
This commit is contained in:
		
							parent
							
								
									174a17dd5e
								
							
						
					
					
						commit
						a302f323af
					
				
					 2 changed files with 157 additions and 6 deletions
				
			
		|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue