Skip to content

import_tools

PatchImporter

Context manager that 'patches' in the latest compatible subdirectory of cas_lib_dir according to SemVer into sys.path, allowing modules within this directory to be imported.

Any patches directories are then removed from sys.path upon closure of the context manager.

Parameters:

Name Type Description Default
version Version

Version folder to seek.

required
cas_lib_dir Path

Directory to look into

required
Source code in cassini/ext/cassini_lib/import_tools.py
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
class PatchImporter:
    """
    Context manager that 'patches' in the latest compatible subdirectory of `cas_lib_dir` according to SemVer
    into `sys.path`, allowing modules within this directory to be imported.

    Any patches directories are then removed from `sys.path` upon closure of the context manager.

    Parameters
    ----------
    version: Version
        Version folder to seek.
    cas_lib_dir: Path
        Directory to look into
    """

    _imported: Set[object] = set()

    def __init__(self, version: Version, cas_lib_dir: Path) -> None:
        self._modules_before = None
        spec = SimpleSpec(
            "{major}.{minor}.*".format(major=version.major, minor=version.minor)
        )
        max_compatible = spec.select(
            Version(entry.name)
            for entry in os.scandir(cas_lib_dir)
            if validate(entry.name)
        )

        if max_compatible is None:
            raise ImportError(
                "No compatible version of cas_lib exists to match {}".format(spec)
            )

        print("Using cas_lib version {}".format(max_compatible))

        self.path = str(cas_lib_dir / str(max_compatible))

    def __enter__(self):
        while self._imported:
            del sys.modules[self._imported.pop()]

        sys.path.append(self.path)
        self._modules_before = set(sys.modules)

    def __exit__(self, *args):
        sys.path.remove(self.path)
        self._imported.update(set(sys.modules) - self._modules_before)