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:
object
This 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:
object
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.
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_min
andbar_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
LimitViolationException
is 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.