Package: registry-factory
RegistryFactoryAn abstract implementation of the software design pattern called registry proposed in (Hartog et. al., 2023),
providing a factory for creating registries to which categorically similar modules can be organized.Installation|Dependencies|Usage|CitationOverviewThe registry design patterns provides a way to organize modular
functionalities dynamically and achieve a unified, reusable, and interchangeable interface.
It extends the Factory design pattern without the explicit class dependency.
Additionally, the registry supports optional meta information such as versioning, accreditation,
testing, etc.
The UML diagrams show the differences between the factory and registry patterns.Created with BioRender.comInstallationThe codebase can be installed from PyPI usingpip, or your package manager of choice, with$pipinstallregistry-factoryDependenciesNo third-party dependencies are required to use the minimal functionality of the RegistryFactory.UsageThe workflow of creating a registry is the following. 1) Identify a part of the code that can be
separated from the rest. 2) Modularize the section to be independent of the rest of the code. 3)
Create a registry from the RegistryFactory. 4) Register any modules that provide similar
functionalities. 5) Call the optional module from the registry from the main workflow. See below.Created with BioRender.comFurther available options and use-cases are described in the following sections.A basic registryA simple registry is created as such.fromregistry_factory.factoryimportFactoryclassRegistries(Factory):TestRegistry=Factory.create_registry(shared=False)Next, any models can be added to the ModelRegistry as such.importtorch.nnasnn@Registries.ModelRegistry.register(call_name="simple_model")classSimpleModel(nn.Module):...Shared modulesA registry can be created to store shared modules. Shared modules are modules that are used in multiple registries (e.g. a model and a module).fromregistry_factory.factoryimportFactoryclassRegistries(Factory):ModelRegistry=Factory.create_registry(shared=True)ModuleRegistry=Factory.create_registry(shared=True)@Registries.ModelRegistry.register(call_name="encoder")classEncoder(nn.Module):...Registries.ModuleRegistry.get("encoder")ArgumentsA registry can be created to store modules with arguments. The arguments can be set when registering a module.fromregistry_factory.factoryimportFactoryclassRegistries(Factory):ModelRegistry=Factory.create_registry(shared=True)@Registries.ModelRegistry.register_arguments(key="simple_model")@dataclassclassSimpleModelArguments:input_size:intoutput_size:intOnly dataclasses can be used as arguments.Versioning and accreditationTwo examples of additional meta information that can be stored in a registry is module versioning
and accreditation regarding how and to who credit should be attributed the module.Versioning can be used to keep track of changes in a module. The version can be set when registering a module.fromregistry_factory.factoryimportFactoryfromregistry_factory.checks.versioningimportVersioningclassRegistries(Factory):ModelRegistry=Factory.create_registry(checks=[Versioning(forced=False)])@Registries.ModelRegistry.register(call_name="simple_model",version="1.0.0")classSimpleModel(nn.Module):...Registries.ModelRegistry.get("simple_model")# Error, version not specified.Registries.ModelRegistry.get("simple_model",version="1.0.0")# Returns the module.Accreditation can be used to keep track of how and to who credit should be attributed the module.
The accreditation can be set when registering a module.fromregistry_factory.factoryimportFactoryfromregistry_factory.checks.accreditationimportAccreditationclassRegistries(Factory):ModelRegistry=Factory.create_registry(checks=[Accreditation(forced=False)])@Registries.ModelRegistry.register(call_name="simple_model",author="Author name",credit_type="reference",additional_information="Reference published work in (link).")classSimpleModel(nn.Module):...Registries.ModelRegistry.get("simple_model")# Returns the module.Registries.ModelRegistry.get_info("simple_model")# Returns all meta information including the accreditation information.The reason why accreditation can return an object without specification is because the accreditation does not have "key" information. In the versioning module, the version is the key information which is used to grab the module from the registry. Without specifying the version, the registry will not know which module to return. In the accreditation module, the author, credit type, and additional information are not key information. Without specifying the author, credit type, and additional information, the registry will still know which module to return.Testing and Factory PatternsWe also provide defining tests and post checks applied to all modules in a registry. Define test
or post checks as follows when creating the registry.classPattern:"""Test pattern."""def__init__(self):passdefhello_world(self):"""Hello world."""print("Hello world")classRegistries(Factory):ModelRegistry=Factory.create_registry(shared=False,checks=[FactoryPattern(factory_pattern=Pattern,forced=False)])# No error, the module passes the test.@ModelRegistry.register(call_name="hello_world")classHelloWorld(Pattern):pass# No error, the module passes the test.@ModelRegistry.register(call_name="hello_world2")classHelloWorld:def__init__(self):passdefhello_world(self):"""Hello world."""print("Hello world")# Error, the module does not pass the test.@ModelRegistry.register(call_name="hello_world2")classHelloWorld:def__init__(self):passdefgoodday_world(self):"""Good day world."""print("Good day world")The factory also supports adding a callable test module to the registry. The callable test module can be specified to be called when a module is registered. The callable test module can be used to test the module when it is registered. The callable test module can be specified as follows when creating the registry.classCallableTestModule:"""Module to test."""def__init__(self,key:str,obj:Any,**kwargs):self.name=objself.assert_name()defassert_name(self):assertself.name=="test","Name is not test"classRegistries(Factory):ModelRegistry=Factory.create_registry(shared=False,checks=[Testing(test_module=CallableTestModule,forced=True)])Registries.ModelRegistry.register_prebuilt(key="name_test",obj="test")# No error, the module passes the test.CitationOur paper in which we propose the registry design pattern, on which this package is built, is currently
available as a preprint. If you make use of the design pattern or this package please cite our work accordingly.!!!!!! ADD PAPER LINK !!!!!!FundingThe work behind this package has received funding from the European Union’s Horizon 2020
research and innovation programme under the Marie Skłodowska-Curie
Actions, grant agreement “Advanced machine learning for Innovative Drug
Discovery (AIDD)” No 956832”.Homepage.