eradiate.util
Contents
eradiate.util
#
eradiate.util.deprecation
#
- eradiate.util.deprecation.deprecated(deprecated_in=None, removed_in=None, details='', current_version=None)[source]#
Decorate a component to signify its deprecation
This component wraps a component (function or class) that will soon be removed and does two things:
The docstring of the method will be modified to include a notice about deprecation, e.g. “Deprecated since 0.9.11. Use foo instead.”
Raises a
DeprecatedWarning
via thewarnings
module, which is a subclass of the built-inDeprecationWarning
. Note that built-inDeprecationWarning
s are ignored by default, so for users to be informed of said warnings they will need to enable them—see thewarnings
module documentation for more details.
- Parameters
deprecated_in (
str
, optional, default:None
) – The version at which the decorated method is considered deprecated. This will usually be the next version to be released when the decorator is added. The default isNone
, which effectively means immediate deprecation. If this is not specified, then the removed_in and current_version arguments are ignored.removed_in (
str
, optional, default:None
) – The version ordatetime.date
when the decorated method will be removed. The default isNone
, specifying that the component is not currently planned to be removed. Note: This parameter cannot be set to a value if deprecated_in is set toNone
.details (
str
, optional) – Extra details to be added to the method docstring and warning. For example, the details may point users to a replacement method, such as “Use the foo_bar method instead”. By default there are no details.current_version (
str
, optional) – Current version. If unset, Eradiate’s package version number is looked up automatically.
- Raises
ValueError – If removed_in is not
None
and deprecated_in is notNone
.
Examples
This decorator allows for specifying the version from which the wrapped component is deprecated, and when it will be retired (this latter argument is optional):
>>> @deprecated(deprecated_in="0.21.1", removed_in="0.22.1") ... def foo(): ... >>> foo()
This will emit a
UnsupportedWarning
, which you can then handle. We can also deprecate classes:>>> @deprecated(deprecated_in="0.21.1", removed_in="0.22.1") ... class SomeClass: ...
If those components are used before v0.21.1, nothing happens. If they are used between v0.21.1 (included) and v0.22.1 (excluded), a
DeprecatedWarning
is emitted. If they are used from v0.22.1 on, anUnsupportedWarning
is emitted.When used with static or class methods, their respective decorators must be applied after this one:
>>> class SomeClass: ... @staticmethod ... @deprecated(deprecated_in="0.21.1", removed_in="0.22.1") ... def staticmethod(): ... ... ... @classmethod ... @deprecated(deprecated_in="0.21.1", removed_in="0.22.1") ... def classmethod(cls): ...
- eradiate.util.deprecation.substitute(subs)[source]#
Generate a simple module
__getattr__()
which redirects outdated attribute lookups to current values with a deprecation warning.- Parameters
subs (
dict
) – A dictionary with outdated names as keys. Values are 2-tuples consisting of the current substitute and a dictionary of keyword arguments passed to theDeprecatedWarning
constructor.- Returns
callable()
– The generated module__getattr__()
function.
Example
>>> __getattr__ = substitute( ... { ... "OneDimExperiment": ( # Old name ... AtmosphereExperiment, # New type ... {"deprecated_in": "0.22.5", "removed_in": "0.22.7"}, # Keyword args ... ) ... } ... )
- exception eradiate.util.deprecation.DeprecatedWarning(component, deprecated_in, removed_in, details='')[source]#
A warning class for deprecated methods
This is a specialization of the built-in
DeprecationWarning
, adding parameters that allow us to get information into the__str__
that ends up being sent through thewarnings
system. The attributes aren’t able to be retrieved after the warning gets raised and passed through the system as only the class–not the instance–and message are what gets preserved.- Parameters
component (
type
orcallable()
) – The component being deprecated.deprecated_in (
str
, optional, default:None
) – The version that component is deprecated in.removed_in (
str
ordatetime
, optional, default:None
) – The version ordatetime.date
specifying when component gets removed.details (
str
, optional) – Optional details about the deprecation. Most often this will include directions on what to use instead of the now deprecated code.
- exception eradiate.util.deprecation.UnsupportedWarning(component, deprecated_in, removed_in, details='')[source]#
A warning class for methods to be removed
This is a subclass of
DeprecatedWarning
and is used to output a proper message about a component being unsupported.
eradiate.util.lazy_loader
#
lazy_loader: Makes it easy to load subpackages and functions on demand.
Note
Copied from https://github.com/scientific-python/lazy_loader.
Date: 2022-08-29
Version: v1.0rc3
- eradiate.util.lazy_loader.attach(package_name, submodules=None, submod_attrs=None)[source]#
Attach lazily loaded submodules, functions, or other attributes.
Typically, modules import submodules and attributes as follows:
import mysubmodule import anothersubmodule from .foo import someattr
The idea is to replace a package’s __getattr__, __dir__, and __all__, such that all imports work exactly the way they would with normal imports, except that the import occurs upon first use.
The typical way to call this function, replacing the above imports, is:
__getattr__, __dir__, __all__ = lazy.attach( __name__, ['mysubmodule', 'anothersubmodule'], {'foo': ['someattr']} )
This functionality requires Python 3.7 or higher.
- eradiate.util.lazy_loader.load(fullname, error_on_import=False)[source]#
Return a lazily imported proxy for a module.
We often see the following pattern:
def myfunc(): from numpy import linalg as la la.norm(...) ....
This is to prevent a module, in this case numpy, from being imported at function definition time, since that can be slow.
This function provides a proxy module that, upon access, imports the actual module. So the idiom equivalent to the above example is:
la = lazy.load("numpy.linalg") def myfunc(): la.norm(...) ....
The initial import time is fast because the actual import is delayed until the first attribute is requested. The overall import time may decrease as well for users that don’t make use of large portions of the library.
- Parameters
fullname (
str
) –The full name of the module or submodule to import. For example:
sp = lazy.load('scipy') # import scipy as sp spla = lazy.load('scipy.linalg') # import scipy.linalg as spla
error_on_import (
bool
) – Whether to postpone raising import errors until the module is accessed. If set to True, import errors are raised as soon as load is called.
- Returns
pm (
importlib.util._LazyModule
) – Proxy module. Can be used like any regularly imported module. Actual loading of the module occurs upon first attribute request.
- eradiate.util.lazy_loader.attach_stub(package_name, filename)[source]#
Attach lazily loaded submodules, functions from a type stub. This is a variant on
attach
that will parse a .pyi stub file to infersubmodules
andsubmod_attrs
. This allows static type checkers to find imports, while still providing lazy loading at runtime.- Parameters
- Returns
__getattr__
,__dir__
,__all__
– The same output asattach
.- Raises
ValueError – If a stub file is not found for filename, or if the stubfile is formmated incorrectly (e.g. if it contains an relative import from outside of the module)
eradiate.util.misc
#
A collection of tools which don’t really fit anywhere else.
- class eradiate.util.misc.LoggingContext(logger, level=None, handler=None, close=True)[source]#
This context manager allows for a temporary override of logger settings.
- class eradiate.util.misc.Singleton[source]#
A simple singleton implementation. See 1 for details.
References
Examples
>>> class MySingleton(metaclass=Singleton): ... >>> my_singleton1 = MySingleton() >>> my_singleton2 = MySingleton() >>> my_singleton1 is my_singleton2 True
- eradiate.util.misc.deduplicate(value, preserve_order=True)[source]#
Remove duplicates from a sequence.
- Parameters
- Returns
list
– List of values with duplicates removed.
- eradiate.util.misc.fullname(obj)[source]#
Get the fully qualified name of obj. Aliases will be dereferenced.
- eradiate.util.misc.get_class_that_defined_method(meth)[source]#
Get the class which defined a method, if relevant. Otherwise, return
None
.
- eradiate.util.misc.is_vector3(value)[source]#
Check if value can be interpreted as a 3-vector.
- Parameters
value – Value to be checked.
- Returns
bool
–True
if a value can be interpreted as a 3-vector.
- eradiate.util.misc.natsort_alphanum_key(x)[source]#
Simple sort key natural order for string sorting. See 2 for details.
See also
References
- eradiate.util.misc.natsorted(l)[source]#
Sort a list of strings with natural ordering.
- Parameters
l (iterable) – List to sort.
- Returns
list
– List sorted usingnatsort_alphanum_key()
.
- eradiate.util.misc.onedict_value(d)[source]#
Get the value of a single-entry dictionary.
- Parameters
d (mapping) – A single-entry mapping.
- Returns
object
– Unwrapped value.- Raises
ValueError – If
d
has more than a single element.
Notes
This function is basically
next(iter(d.values()))
with a safeguard.Examples
>>> onedict_value({"foo": "bar"}) 'bar'
eradiate.util.numpydoc
#
Numpydoc docstring tools.
- eradiate.util.numpydoc.format_doc(sections)[source]#
Assemble docstring sections and format them according to the Numpydoc style.
- eradiate.util.numpydoc.NUMPYDOC_SECTION_TITLES = ['Parameters', 'Fields', 'Attributes', 'Returns', 'Yields', 'Receives', 'Other Parameters', 'Raises', 'Warns', 'Warnings', 'See Also', 'Notes', 'References', 'Examples']#
List of support docstring sections. The “Fields” section is unique to Eradiate.