API Reference

Locations

Location

Arbitrary importable location.

ModuleLocation

Package-based importable location, e.g. foo.bar:obj.

PathLocation

Filesystem-based importable location, e.g. foo/bar.py:obj.

Utils

get_instances

Get object members that are instances of specified type.

get_subclasses

Get object members that are subclasses of specified class (excluding the class itself).

getattr_nested

Get nested attribute value.

random_name

Generate random module name based on UUID4.

Locations

To use any of supported concrete location types, use generic Location class. Upon construction, it will return one of specific location objects supported: ModuleLocation or PathLocation. Alternatively, construct specific location types directly to enforce corresponding location type.

Location

Format

PathLocation

(?P<path>.*/[^/]*\.py)(:(?P<obj>[^./:]+(?:\.[^./:]+)*))?

ModuleLocation

(?P<module>[^./:]+(?:\.[^./:]+)*)(:(?P<obj>[^./:]+(?:\.[^./:]+)*))?

Location

Examples

PathLocation

svc1/main.py:app, svc1/exceptions.py, ../config.py

ModuleLocation

app.__main__:cli, logging:StreamHandler

Location

+spec : str

+obj : str | None

+load(modname, on_conflict, rename)

+match(spec: str)

ModuleLocation

+module : str

PathLocation

+path : Path

Location

+spec : str

+obj : str | None

+load(modname, on_conflict, rename)

+match(spec: str)

ModuleLocation

+module : str

PathLocation

+path : Path

class ConflictResolution(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)[source]

Conflict resolution strategy when module with given name is already imported.

REUSE = 'reuse'

Don’t import again, use existing module from sys.modules.

RELOAD = 'reload'

Don’t import again, apply importlib.reload to existing module in sys.modules.

REPLACE = 'replace'

Delete existing module and use the imported one.

RENAME = 'rename'

Retry module import with new generated name, and raise ModuleNameConflict exception if conflict appears again.

RAISE = 'raise'

Raise ModuleNameConflict exception.

class Location(self, spec: str)[source]

Arbitrary importable location.

Parameters:

spec – location specification string.

Raises:

InvalidLocation – when location string format is incorrect.

classmethod match(spec: str) Match[str] | None[source]

Match location specification string with regular expression for specific location type.

Parameters:

spec – location specification string.

load(modname: str | Callable[[Self], str] | None = None, on_conflict: ConflictResolution | str = 'raise', rename: Callable[[str, Self], str] | None = None) object | ModuleType[source]

Import requested object or the whole module object from location.

This operation is atomic:

  • on import error, previous module with the same name is restored

  • on import error, new partially initialized module is removed from sys.modules

Parameters:
  • modname – name under which the module will be imported; if str, use modname itself; if Callable, use result of calling modname() with current Location object; otherwise, use default value (see ModuleLocation.load and PathLocation.load for details).

  • on_conflict – behaviour if modname is already present in sys.modules (see ConflictResolution for details).

  • rename – callable used to generate new module name on name conflict and if on_conflict is rename; first string argument is modname that leads to conflict, second argument is current Location.

Raises:
Returns:

object when obj part was specified, otherwise ModuleType.

class ModuleLocation(self, spec: str)[source]
class ModuleLocation(self, *, module: str, obj: str | None = None)

Package-based importable location, e.g. foo.bar:obj

Parameters:
  • spec – location specification string; if spec is passed, other arguments must be absent or None.

  • module – importable module name; required, if spec is not passed.

  • obj – dot-separated object name to be imported; when missing, the whole module will be loaded

Raises:
classmethod match(spec: str) Match[str] | None[source]

Match location specification string with corresponding regular expression.

Parameters:

spec – location specification string.

load(modname: str | Callable[[Self], str] | None = None, on_conflict: ConflictResolution | str = 'raise', rename: Callable[[str, Self], str] | None = None) object | ModuleType[source]

Import requested object or the whole module object from importable module.

This operation is atomic:

  • on import error, previous module with the same name is restored

  • on import error, new partially initialized module is removed from sys.modules

Parameters:
  • modname – name under which the module will be imported; if str, use modname itself; if Callable, use result of calling modname() with current Location object; by default, use module from spec.

  • on_conflict – behaviour if modname is already present in sys.modules (see ConflictResolution for details).

  • rename – callable used to generate new module name on name conflict and if on_conflict is rename; first string argument is modname that leads to conflict, second argument is current Location.

Raises:
Returns:

object when obj part was specified, otherwise ModuleType.

class PathLocation(self, spec: str)[source]
class PathLocation(self, *, path: Path | str, obj: str | None = None)

Filesystem-based importable location, e.g. foo/bar.py:obj

Parameters:
  • spec – location specification string or Path object; if spec is passed, other arguments must be absent or None.

  • path – path to python source file to import from; required, if spec is not passed.

  • obj – dot-separated object name to be imported; when missing, the whole file will be imported as module

Raises:
classmethod match(spec: str) Match[str] | None[source]

Match location specification string with corresponding regular expression.

Parameters:

spec – location specification string.

load(modname: str | Callable[[Self], str] | None = None, on_conflict: ConflictResolution | str = 'raise', rename: Callable[[str, Self], str] | None = None) object | ModuleType[source]

Import requested object or the whole module object from location.

This operation is atomic:

  • on import error, previous module with the same name is restored

  • on import error, new partially initialized module is removed from sys.modules

Parameters:
  • modname – name under which the module will be imported; if str, use modname itself; if Callable, use result of calling modname() with current Location object; by default, use path stem from spec.

  • on_conflict – behaviour if modname is already present in sys.modules (see ConflictResolution for details).

  • rename – callable used to generate new module name on name conflict and if on_conflict is rename; first string argument is modname that leads to conflict, second argument is current Location.

Raises:
Returns:

object when obj part was specified, otherwise ModuleType.

unload(module: str | ModuleType) None[source]

Unload previously imported module. The module is not guaranteed to be garbage collected (other objects might be referencing it).

This function roughly equals to

del sys.modules[module]
del module
Parameters:

module – imported module name or module object to be deleted.

Raises:

KeyError – when there is no imported module with given name.

Exceptions

exception InvalidLocation[source]

Incorrect format of location specification string.

exception ModuleNameConflict(modname: str, *args: Any, **kwargs: Any)[source]

Module with this name is already imported.

Utils

get_instances(obj: object, cls: type[T], order: OrderBy | str | Callable[[T], Any] = 'name') list[T][source]

Get object members that are instances of specified type. Uses inspect.getmembers and isinstance.

Parameters:
  • obj (object) – object to get members from.

  • cls (type) – type of members to be returned.

  • order (OrderBy | str | Callable[[T], Any]) – sorting method or sort key function; defaults to 'name'.

Raises:

TypeError – or other Exception raised by inspect.getfile and inspect.getsourcelines when sorting order='source'.

Return type:

list[object]

Example

>>> import app.plugins
>>> plugins = get_instances(app.plugins, Plugin)
get_subclasses(obj: object, cls: type[T], order: OrderBy | str | Callable[[T], Any] = 'name') list[type[T]][source]

Get object members that are subclasses of specified class (excluding the class itself). Uses inspect.getmembers and issubclass.

Parameters:
  • obj (object) – object to get members from.

  • cls (type) – base class for returned subclasses.

  • order (OrderBy | str | Callable[[T], Any]) – sorting method or sort key function; defaults to 'name'.

Raises:

TypeError – or other Exception raised by inspect.getfile and inspect.getsourcelines when sorting order='source'.

Return type:

list[object]

Example

>>> from unittest import TestCase
>>> from tests import test_usage
>>> cases = get_subclasses(test_usage, TestCase, order='source')
getattr_nested(obj: object, name: str, default: type[Exception] | ~typing.Any = <class 'AttributeError'>) object[source]

Get nested attribute value. If attribute chain does not exist, raise exception or return default value.

Parameters:
  • obj (object) – object to get attribute value from.

  • name (str) – dot-separated nested attribute name.

  • default (Exception | Any) – raise exception if default is an Exception type (AttributeError by default); otherwise return default value.

Raises:
Returns:

nested attribute value or default value, if specified and not an Exception subclass.

Example

>>> from app import config
>>> options = getattr_nested(config, f'{config.primary}.options')
>>> missing = getattr_nested(config, 'does.not.exist', None)
random_name(*args: Any, **kwargs: Any) str[source]

Generate random module name based on UUID4.

All arguments passed to this function will be ignored.

Example

>>> random_name()
'ufoh3xjrrozfcvfheyktg62pzia'
class OrderBy(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)[source]

Objects sorting method.

NAME = 'name'

Order by object name.

SOURCE = 'source'

Order by definition order in the source file, first by source filename path, then by first line number. This sorting method uses inspect.getsourcefile and inspect.getsourcelines, and inherits their requirements on objects and exceptions raised.

class T

Arbitrary type.

alias of TypeVar(‘T’, bound=object)