|
7 | 7 | import copy |
8 | 8 | import inspect |
9 | 9 | import argparse |
| 10 | +import functools |
10 | 11 | import contextlib |
11 | 12 | import dataclasses |
12 | 13 | from argparse import ArgumentParser |
@@ -278,7 +279,45 @@ def __init__(self): |
278 | 279 | self.dest = None |
279 | 280 |
|
280 | 281 |
|
281 | | -class BaseConfigurable(abc.ABC): |
| 282 | +class BaseConfigurableMetaClass(type, abc.ABC): |
| 283 | + def __new__(cls, name, bases, props, module=None): |
| 284 | + # Create the class |
| 285 | + cls = super(BaseConfigurableMetaClass, cls).__new__( |
| 286 | + cls, name, bases, props |
| 287 | + ) |
| 288 | + # Wrap __init__ |
| 289 | + setattr(cls, "__init__", cls.wrap(cls.__init__)) |
| 290 | + return cls |
| 291 | + |
| 292 | + @classmethod |
| 293 | + def wrap(cls, func): |
| 294 | + """ |
| 295 | + If a subclass of BaseConfigurable is passed keyword arguments, convert |
| 296 | + them into the instance of the CONFIG class. |
| 297 | + """ |
| 298 | + |
| 299 | + @functools.wraps(func) |
| 300 | + def wrapper(self, config: Optional[BaseConfig] = None, **kwargs): |
| 301 | + if config is None and hasattr(self, "CONFIG") and kwargs: |
| 302 | + try: |
| 303 | + config = self.CONFIG(**kwargs) |
| 304 | + except TypeError as error: |
| 305 | + error.args = ( |
| 306 | + error.args[0].replace( |
| 307 | + "__init__", f"{self.CONFIG.__qualname__}" |
| 308 | + ), |
| 309 | + ) |
| 310 | + raise |
| 311 | + if config is None: |
| 312 | + raise TypeError( |
| 313 | + "__init__() missing 1 required positional argument: 'config'" |
| 314 | + ) |
| 315 | + return func(self, config) |
| 316 | + |
| 317 | + return wrapper |
| 318 | + |
| 319 | + |
| 320 | +class BaseConfigurable(metaclass=BaseConfigurableMetaClass): |
282 | 321 | """ |
283 | 322 | Class which produces a config for itself by providing Args to a CMD (from |
284 | 323 | dffml.util.cli.base) and then using a CMD after it contains parsed args to |
@@ -459,7 +498,7 @@ async def __aexit__(self, exc_type, exc_value, traceback): |
459 | 498 |
|
460 | 499 |
|
461 | 500 | class BaseDataFlowFacilitatorObject( |
462 | | - BaseDataFlowFacilitatorObjectContext, BaseConfigurable, Entrypoint, abc.ABC |
| 501 | + BaseDataFlowFacilitatorObjectContext, BaseConfigurable, Entrypoint |
463 | 502 | ): |
464 | 503 | """ |
465 | 504 | Base class for all Data Flow Facilitator objects conforming to the |
|
0 commit comments