caikit.core.modules.meta ======================== .. py:module:: caikit.core.modules.meta .. autoapi-nested-parse:: This module contains an implementation of a metaclass that hijacks all ${class}.load(...) invocations. For a good read on metaclasses, see https://realpython.com/python-metaclasses/ Our goal is to have every instance of a `caikit.core.ModuleBase` automatically populated with metadata when it is constructed, without requiring anything of the module authors. The source of this metadata will be the `config.yml` file that resides within the module directory to be loaded. Since we require the path to that file in order to read the model's metadata, we cannot simply define a base constructor. Instead, we patch over the module's .load() function, which is guaranteed to be called with a path to a serialized module. Additionally, the naive solution of manually patching .load functions does not work when inheritance is involved. For example:: import caikit.core class ParentModule(caikit.core.ModuleBase): @classmethod def load(cls, module_path): return cls() class ChildModule(ParentModule): @classmethod def load(cls, module_path): return super().load() # This is fine! assert isinstance(ChildModule.load(), ChildModule) def injector(load_fn): def injected_load(*args): module = load_fn(*args) module.metadata = {"stuff"} return module return classmethod(injected_load) for clz in (ParentModule, ChildModule): # But this line binds the new load function directly to each class :( clz.load = injector(clz.load) # And this will now raise since ParentModule is returned assert isinstance(ChildModule.load(), ChildModule) Instead of binding new metadata-injecting load functions directly to a class at import time, we need to bind the new load function at contruction time, when the class hierarchy with inheritance is known. Attributes ---------- .. autoapisummary:: caikit.core.modules.meta.log caikit.core.modules.meta.error Classes ------- .. autoapisummary:: caikit.core.modules.meta._ModuleBaseMeta Module Contents --------------- .. py:data:: log .. py:data:: error .. py:class:: _ModuleBaseMeta Bases: :py:obj:`abc.ABCMeta` This is the metaclass used by `caikit.core.ModuleBase`. This metaclass populates the `metadata` property of any module that is created by invoking a `load` classmethod on a derived class. .. py:property:: tasks :type: List[caikit.core.TaskBase] .. py:method:: __setattr__(name, val) Overwrite __setattr__ to warn on any dynamic updates to the load function. We'd rather not lose all the work we did to wrap `.load` with metadata injection in the constructor!