hbutils.reflection.module

Utilities for temporarily modifying Python’s import environment.

This module provides context-managed helpers for mounting custom PYTHONPATH entries and isolating sys.modules state. It enables predictable import behavior by allowing you to activate a snapshot of paths and modules, then restore the original environment when the context exits.

The module exposes the following public components:

Note

All modifications to sys.path and sys.modules are reverted on context exit. Use the keep argument of PythonPathEnv.mount() to persist changes into the snapshot.

Example:

>>> from hbutils.reflection import mount_pythonpath
>>> with mount_pythonpath('path/to/plugins') as env:
...     import my_plugin
...     print(my_plugin.__name__)
my_plugin
>>> # `my_plugin` is no longer importable outside the context

__all__

hbutils.reflection.module.__all__ = ['mount_pythonpath', 'PythonPathEnv']

Built-in mutable sequence.

If no argument is given, the constructor creates a new empty list. The argument must be an iterable if specified.

PythonPathEnv

class hbutils.reflection.module.PythonPathEnv(pythonpath: List[str], modules: Mapping[str, ModuleType])[source]

Snapshot of a Python import environment.

This class captures a specific PYTHONPATH and module set so that it can be mounted later. It is typically created by mount_pythonpath().

Parameters:
  • pythonpath (List[str]) – Python path list to be used in this environment.

  • modules (Mapping[str, types.ModuleType]) – Dictionary of modules loaded in this environment.

Variables:
  • pythonpath (List[str]) – Stored path entries used when mounted.

  • modules (Dict[str, types.ModuleType]) – Stored module mapping used when mounted.

__init__(pythonpath: List[str], modules: Mapping[str, ModuleType])[source]

Constructor of PythonPathEnv.

Parameters:
  • pythonpath (List[str]) – Python path list to be used in this environment.

  • modules (Mapping[str, types.ModuleType]) – Dictionary of modules loaded in this environment.

mount(keep: bool = True) Iterator[PythonPathEnv][source]

Mount the stored PYTHONPATH and modules of this environment.

This method activates the environment by setting sys.path and sys.modules to the values stored in this PythonPathEnv instance. When the context exits, the original environment is restored.

Parameters:

keep (bool) – If True, changes made during the context (new imports, module modifications) will be kept in this PythonPathEnv instance for future mounts. If False, changes are discarded. Defaults to True.

Returns:

Context manager that yields this PythonPathEnv instance.

Return type:

Iterator[PythonPathEnv]

Examples:

>>> from hbutils.reflection import mount_pythonpath
>>> with mount_pythonpath('test/testfile/igm') as env:
...     from gf1 import FIXED
...     print('FIXED in igm:', FIXED)
FIXED in igm: 1234567
>>> with env.mount():
...     from gf1 import FIXED
...     print('FIXED in igm:', FIXED)
FIXED in igm: 1234567

mount_pythonpath

hbutils.reflection.module.mount_pythonpath(*path: str) Iterator[PythonPathEnv][source]

Prepend paths to PYTHONPATH within a context manager.

This function temporarily inserts directories into sys.path and restores both sys.path and sys.modules when the context exits, ensuring isolation.

Parameters:

path (str) – One or more directory paths to prepend to sys.path.

Returns:

Context manager that yields a PythonPathEnv instance representing the mounted environment.

Return type:

Iterator[PythonPathEnv]

Examples:

Here is the testfile directory structure:

>>> import os
>>> os.system('tree test/testfile')
test/testfile
├── dir1
│   ├── gf1.py
├── dir2
│   ├── gf1.py
└── igm
    └── gf1.py

We can import values from different directories:

>>> from hbutils.reflection import mount_pythonpath
>>> with mount_pythonpath('test/testfile/igm'):
...     from gf1 import FIXED
...     print('FIXED in igm:', FIXED)
FIXED in igm: 1234567
>>>
>>> with mount_pythonpath('test/testfile/dir1'):
...     from gf1 import FIXED
...     print('FIXED in dir1:', FIXED)
FIXED in dir1: 233
>>>
>>> with mount_pythonpath('test/testfile/dir2'):
...     from gf1 import FIXED
...     print('FIXED in dir2:', FIXED)
FIXED in dir2: 455
>>>
>>> from gf1 import FIXED  # cannot import outside the context
ModuleNotFoundError: No module named 'gf1'