| Conditions | 6 |
| Total Lines | 91 |
| Code Lines | 21 |
| Lines | 0 |
| Ratio | 0 % |
| Changes | 0 | ||
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
| 1 | """This module is responsible to provide a formal way of registering phi functions |
||
| 46 | @classmethod |
||
| 47 | def register(cls, phi_name=''): |
||
| 48 | r"""Add a new phi function to phi function registry and notify listeners/observers. |
||
| 49 | |||
| 50 | Use this decorator around either a callable function (defined with the 'def' python special word) or a class |
||
| 51 | with a takes-no-arguments (or all-optional-arguments) constructor and a __call__ magic method. |
||
| 52 | |||
| 53 | All phi functions are expected to be registered with a __name__ and a __doc__ attribute. |
||
| 54 | |||
| 55 | You can select your custom phi_name under which to register the phi function or default to an automatic |
||
| 56 | determination of the phi_name to use. |
||
| 57 | |||
| 58 | Automatic determination of phi_name is done by examining either the __name__ attribute of the function or the |
||
| 59 | class name of the class. |
||
| 60 | |||
| 61 | Example: |
||
| 62 | |||
| 63 | >>> from so_magic.data.features.phi import PhiFunctionRegistry, PhiFunctionRegistrator |
||
| 64 | |||
| 65 | >>> registered_phis = PhiFunctionRegistry() |
||
| 66 | |||
| 67 | >>> @PhiFunctionRegistrator.register() |
||
| 68 | ... def f1(x): |
||
| 69 | ... '''Multiply by 2.''' |
||
| 70 | ... return x * 2 |
||
| 71 | Registering input function f1 as phi function, at key f1. |
||
| 72 | |||
| 73 | >>> registered_phis.get('f1').__doc__ |
||
| 74 | 'Multiply by 2.' |
||
| 75 | |||
| 76 | >>> input_value = 5 |
||
| 77 | >>> print(f"{input_value} * 2 = {registered_phis.get('f1')(input_value)}") |
||
| 78 | 5 * 2 = 10 |
||
| 79 | |||
| 80 | >>> @PhiFunctionRegistrator.register() |
||
| 81 | ... class f2: |
||
| 82 | ... def __call__(self, data, **kwargs): |
||
| 83 | ... return data + 5 |
||
| 84 | Registering input class f2 instance as phi function, at key f2. |
||
| 85 | |||
| 86 | >>> input_value = 1 |
||
| 87 | >>> print(f"{input_value} + 5 = {registered_phis.get('f2')(input_value)}") |
||
| 88 | 1 + 5 = 6 |
||
| 89 | |||
| 90 | >>> @PhiFunctionRegistrator.register('f3') |
||
| 91 | ... class MyCustomClass: |
||
| 92 | ... def __call__(self, data, **kwargs): |
||
| 93 | ... return data + 1 |
||
| 94 | Registering input class MyCustomClass instance as phi function, at key f3. |
||
| 95 | |||
| 96 | >>> input_value = 3 |
||
| 97 | >>> print(f"{input_value} + 1 = {registered_phis.get('f3')(input_value)}") |
||
| 98 | 3 + 1 = 4 |
||
| 99 | |||
| 100 | Args: |
||
| 101 | phi_name (str, optional): custom name to register the phi function. Defaults to automatic computation. |
||
| 102 | """ |
||
| 103 | def wrapper(a_callable): |
||
| 104 | """Add a callable object to the phi function registry and preserve info for __name__ and __doc__ attributes. |
||
| 105 | |||
| 106 | The callable object should either be function (defined with def) or a class (defined with class). In case of |
||
| 107 | a class the class must have a constructor that takes no arguments (or all arguments are optional) and a |
||
| 108 | __call__ magic method. |
||
| 109 | |||
| 110 | Registers the callable as a phi function under the given or automatically computed name, makes sure the |
||
| 111 | __name__ and __doc__ attributes preserve information and notifies potential listeners/observers. |
||
| 112 | |||
| 113 | Args: |
||
| 114 | a_callable (Callable): the object (function or class) to register as phi function |
||
| 115 | """ |
||
| 116 | if hasattr(a_callable, '__code__'): # it is a function (def func_name ..) |
||
| 117 | logging.info("Registering input function %s as phi function.", a_callable.__code__.co_name) |
||
| 118 | key = phi_name if phi_name else cls.get_name(a_callable) |
||
| 119 | print(f"Registering input function {a_callable.__code__.co_name} as phi function, at key {key}.") |
||
| 120 | cls._register(a_callable, key) |
||
| 121 | else: |
||
| 122 | if not hasattr(a_callable, '__call__'): |
||
| 123 | raise RuntimeError("Expected an class definition with a '__call__' instance method defined 1." |
||
| 124 | f" Got {type(a_callable)}") |
||
| 125 | members = inspect.getmembers(a_callable) |
||
| 126 | if ('__call__', a_callable.__call__) not in members: |
||
| 127 | raise RuntimeError("Expected an class definition with a '__call__' instance method defined 2." |
||
| 128 | f" Got {type(a_callable)}") |
||
| 129 | instance = a_callable() |
||
| 130 | instance.__name__ = a_callable.__name__ |
||
| 131 | instance.__doc__ = a_callable.__call__.__doc__ |
||
| 132 | key = phi_name if phi_name else cls.get_name(instance) |
||
| 133 | print(f"Registering input class {a_callable.__name__} instance as phi function, at key {key}.") |
||
| 134 | cls._register(instance, key) |
||
| 135 | return a_callable |
||
| 136 | return wrapper |
||
| 137 | |||
| 175 |