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 the warnings module, which is a subclass of the built-in DeprecationWarning. Note that built-in DeprecationWarnings are ignored by default, so for users to be informed of said warnings they will need to enable them—see the warnings 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 is None, 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 or datetime.date when the decorated method will be removed. The default is None, 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 to None.

  • 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 not None.

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, an UnsupportedWarning 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 the DeprecatedWarning 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 the warnings 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 or callable()) – The component being deprecated.

  • deprecated_in (str, optional, default: None) – The version that component is deprecated in.

  • removed_in (str or datetime, optional, default: None) – The version or datetime.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.

Parameters
  • package_name (str) – Typically use __name__.

  • submodules (set) – List of submodules to attach.

  • submod_attrs (dict) – Dictionary of submodule -> list of attributes / functions. These attributes are imported as they are used.

Returns

__getattr__, __dir__, __all__

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 infer submodules and submod_attrs. This allows static type checkers to find imports, while still providing lazy loading at runtime.

Parameters
  • package_name (str) – Typically use __name__.

  • filename (str) – Path to .py file which has an adjacent .pyi file. Typically use __file__.

Returns

__getattr__, __dir__, __all__ – The same output as attach.

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

1

Creating a singleton in Python on Stack Overflow.

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
  • value (sequence) – Sequence to remove duplicates from.

  • preserve_order (bool, optional, default: True) – If True, preserve item ordering. The first occurrence of duplicated items is kept. Setting to False may slightly improve performance.

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

boolTrue 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

Sorting HOWTO

References

2

Natural sorting on Stack Overflow.

eradiate.util.misc.natsorted(l)[source]#

Sort a list of strings with natural ordering.

Parameters

l (iterable) – List to sort.

Returns

list – List sorted using natsort_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.

Parameters

sections (dict) – A dictionary mapping section names to contents. Section ordering follows the Nompydoc style guide.

Returns

docstring (str) – Formatted docstring.

eradiate.util.numpydoc.parse_doc(doc)[source]#

Parse a docstring formatted with the Numpydoc style.

Parameters

doc (str) – Docstring to parse.

Returns

sections (dict) – A dictionary mapping section names to their content. Special _short_summary and _extended_summary keys are used for summary contents.

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.