Source code for modelrunner.utils

"""
Miscellaneous utility methods

.. autosummary::
   :nosignatures:

   hybridmethod
   import_class

.. codeauthor:: David Zwicker <david.zwicker@ds.mpg.de>
"""

from __future__ import annotations

import importlib


[docs]class hybridmethod: """decorator to use a method both as a classmethod and an instance method Note: The decorator can be used like so: .. code-block:: python @hybridmethod def method(cls, ...): ... @method.instancemethod def method(self, ...): ... Adapted from https://stackoverflow.com/a/28238047 """ def __init__(self, fclass, finstance=None, doc=None): self.fclass = fclass self.finstance = finstance self.__doc__ = doc or fclass.__doc__ # support use on abstract base classes self.__isabstractmethod__ = bool(getattr(fclass, "__isabstractmethod__", False))
[docs] def classmethod(self, fclass): return type(self)(fclass, self.finstance, None)
[docs] def instancemethod(self, finstance): return type(self)(self.fclass, finstance, self.__doc__)
def __get__(self, instance, cls): if instance is None or self.finstance is None: # either bound to the class, or no instance method available return self.fclass.__get__(cls, None) return self.finstance.__get__(instance, cls)
[docs]def import_class(identifier: str): """import a class or module given an identifier Args: identifier (str): The identifier can be a module or a class. For instance, calling the function with the string `identifier == 'numpy.linalg.norm'` is roughly equivalent to running `from numpy.linalg import norm` and would return a reference to `norm`. """ module_path, _, class_name = identifier.rpartition(".") if module_path: module = importlib.import_module(module_path) return getattr(module, class_name) else: # this happens when identifier does not contain a dot return importlib.import_module(class_name)