Assuming python3.10
, suppose I have a class in some file:
class Foo(metaclass=ABCMeta):
@classmethod
@abstractmethod
def do_fn(cls, yada, yada_):
pass
@classmethod
@abstractmethod
def that_fn(cls, this, that):
pass
SpecializedFoo(Foo):
@classmethod
def do_fn(cls, yada, yada_):
logger.info("doing it")
@classmethod
def that_fn(cls, this, that):
logger.info("this or that")
And a system interface module that expects do_fn
and that_fn
:
# interface.py
from functools import partial
from specialized_foo import SpecializedFoo
##### A Foo Interface #####
# Optionally leverage the system integration
# Read the docs: https://yankee.doodle.etc/callbacks
do_fn = partial(SpecializedFoo.do_fn)
that_fn = partial(SpecializedFoo.that_fn)
### Done: Foo Interface
Is there a clean or at least automatic and stable way I can define a method in SpecializedFoo
or abstract parent class Foo
such that the system interface interface.py
can simply call:
SpecializedFoo.export_interface()
And the method functions will be exported to the module's list of available module methods as if they were defined in the exact same fashion, e.g.:
do_fn = partial(SpecializedFoo.do_fn)
that_fn = partial(SpecializedFoo.that_fn)
The answer involves a small function added to the parent class:
class Foo(metaclass=ABCMeta):
@classmethod
def export_interface(cls, module_name: str):
module = sys.modules[module_name]
# this can be handled dynamically by matching the `_fn` w/ re
module.do_fn = cls.do_fn
module.that_fn = cls.that_fn
And a single call in the interface.py
:
SpecializedFoo.export_interface(__name__)
The user is responsible for avoiding collisions in the interface.py
, but a system interface constructed this way (using modules as if they are classes) that imposes those kind of duties on the developer anyhow.