lewis.core.utils
This module contains some useful helper classes and functions that are not specific to a certain module contained in the Core API.
Members
This is a utility class for importing classes from a module or replacing them with dummy types if the module can not be loaded. |
|
This decorator helps to make sure that the parameter of a property setter (or any other method with one argument) is within certain numerical limits. |
|
This function updates base_dict with update_dict if and only if update_dict does not contain keys that are not already in base_dict. |
|
This function tries to extract a valid module name from the basename of the supplied path. |
|
A very thin wrapper around textwrap.fill to consistently wrap documentation text for display in a command line environment. |
|
Returns all members of an object for which the supplied predicate is true and that do not begin with __. |
|
This function imports all sub-modules of the supplied module and returns a dictionary with module names as keys and the sub-module objects as values. |
|
This is a small helper function that returns the elapsed seconds since start using datetime.datetime.now(). |
- class lewis.core.utils.FromOptionalDependency(module, exception=None)[source]
Bases:
objectThis is a utility class for importing classes from a module or replacing them with dummy types if the module can not be loaded.
Assume module ‘a’ that does:
from b import C, D
and module ‘e’ which does:
from a import F
where ‘b’ is a hard to install dependency which is thus optional. To still be able to do:
import e
without raising an error, for example for inspection purposes, this class can be used as a workaround in module ‘a’:
C, D = FromOptionalDependency("b").do_import("C", "D")
which is not as pretty as the actual syntax, but at least it can be read in a similar way. If the module ‘b’ can not be imported, stub-types are created that are called ‘C’ and ‘D’. Everything depending on these types will work until any of those are instantiated - in that case an exception is raised.
The exception can be controlled via the exception-parameter. If it is a string, a LewisException is constructed from it. Alternatively it can be an instance of an exception-type. If not provided, a LewisException with a standard message is constructed. If it is anything else, a RuntimeError is raised.
Essentially, this class helps deferring ImportErrors until anything from the module that was attempted to load is actually used.
- Parameters:
module – Module from that symbols should be imported.
exception – Text for LewisException or custom exception object.
- do_import(*names)[source]
Tries to import names from the module specified on initialization of the FromOptionalDependency-object. In case an ImportError occurs, the requested names are replaced with stub objects.
- Parameters:
names – List of strings that are used as type names.
- Returns:
Tuple of actual symbols or stub types with provided names. If there is only one element in the tuple, that element is returned.
- class lewis.core.utils.check_limits(lower=None, upper=None, silent=False)[source]
Bases:
objectThis decorator helps to make sure that the parameter of a property setter (or any other method with one argument) is within certain numerical limits.
It’s possible to set static limits using floats or ints:
class Foo: _bar = 0 @property def bar(self): return self._bar @bar.setter @check_limits(0, 15) def bar(self, new_value): self._bar = new_value
But sometimes this is not flexible enough, so it’s also possible to supply strings, which are the names of attributes of the object the decorated method belongs with:
class Foo: _bar = 0 bar_min = 0 bar_max = 24 @property def bar(self): return self._bar @bar.setter @check_limits("bar_min", "bar_max") def bar(self, new_value): self._bar = new_value
This will make sure that the new value is always between
bar_minandbar_max, even if they change at runtime. If the limit isNone(default), the value will not be limited in that direction.Upper and lower limit can also be used exclusively, for example for a property that has a lower bound but not an upper, say a temperature:
class Foo: _temp = 273.15 @check_limits(lower=0) def set_temperature(self, t_in_kelvin): self._temp = t_in_kelvin
If the value is outside the specified limits, the decorated function is not called and a
LimitViolationExceptionis raised if thesilent- parameter isFalse(default). If that option is active, the call is simply silently ignored.- Parameters:
lower – Numerical lower limit or name of attribute that contains limit.
upper – Numerical upper limit or name of attribute that contains limit.
silent – A limit violation will not raise an exception if this option is
True.
- lewis.core.utils.dict_strict_update(base_dict, update_dict) None[source]
This function updates base_dict with update_dict if and only if update_dict does not contain keys that are not already in base_dict. It is essentially a more strict interpretation of the term “updating” the dict.
If update_dict contains keys that are not in base_dict, a RuntimeError is raised.
- Parameters:
base_dict – The dict that is to be updated. This dict is modified.
update_dict – The dict containing the new values.
- lewis.core.utils.extract_module_name(absolute_path)[source]
This function tries to extract a valid module name from the basename of the supplied path. If it’s a directory, the directory name is returned, if it’s a file, the file name without extension is returned. If the basename starts with _ or . or it’s a file with an ending different from .py, the function returns None
- Parameters:
absolute_path – Absolute path of something that might be a module.
- Returns:
Module name or None.
- lewis.core.utils.format_doc_text(text)[source]
A very thin wrapper around textwrap.fill to consistently wrap documentation text for display in a command line environment. The text is wrapped to 99 characters with an indentation depth of 4 spaces. Each line is wrapped independently in order to preserve manually added line breaks.
- Parameters:
text – The text to format, it is cleaned by inspect.cleandoc.
- Returns:
The formatted doc text.
- lewis.core.utils.get_members(obj, predicate=None)[source]
Returns all members of an object for which the supplied predicate is true and that do not begin with __. Keep in mind that the supplied function must accept a potentially very broad range of inputs, because the members of an object can be of any type. The function puts those members into a dict with the member names as keys and returns it. If no predicate is supplied, all members are put into the dict.
- Parameters:
obj – Object from which to get the members.
predicate – Filter function for the members, only members for which True is returned are part of the resulting dict.
- Returns:
Dict with name-object pairs of members of obj for which predicate returns true.
- lewis.core.utils.get_submodules(module) dict[str, ModuleType][source]
This function imports all sub-modules of the supplied module and returns a dictionary with module names as keys and the sub-module objects as values. If the supplied parameter is not a module object, a RuntimeError is raised.
- Parameters:
module – Module object from which to import sub-modules.
- Returns:
Dict with name-module pairs.