| 60 | |
| 61 | |
| 62 | class ModuleGatherer: |
| 63 | def __init__( |
| 64 | self, |
| 65 | paths: Iterable[str | Path] | None = None, |
| 66 | skiplist: Sequence[str] | None = None, |
| 67 | ) -> None: |
| 68 | """Initialize module gatherer with all modules in `paths`, which should be a list of |
| 69 | directory names. If `paths` is not given, `sys.path` will be used.""" |
| 70 | |
| 71 | # Cached list of all known modules |
| 72 | self.modules: set[str] = set() |
| 73 | # Set of (st_dev, st_ino) to compare against so that paths are not repeated |
| 74 | self.paths: set[_LoadedInode] = set() |
| 75 | # Patterns to skip |
| 76 | self.skiplist: Sequence[str] = ( |
| 77 | skiplist if skiplist is not None else tuple() |
| 78 | ) |
| 79 | self.fully_loaded = False |
| 80 | |
| 81 | if paths is None: |
| 82 | self.modules.update(sys.builtin_module_names) |
| 83 | paths = sys.path |
| 84 | |
| 85 | self.find_iterator = self.find_all_modules( |
| 86 | Path(p).resolve() if p else Path.cwd() for p in paths |
| 87 | ) |
| 88 | |
| 89 | def module_matches(self, cw: str, prefix: str = "") -> set[str]: |
| 90 | """Modules names to replace cw with""" |
| 91 | |
| 92 | full = f"{prefix}.{cw}" if prefix else cw |
| 93 | matches = ( |
| 94 | name |
| 95 | for name in self.modules |
| 96 | if (name.startswith(full) and name.find(".", len(full)) == -1) |
| 97 | ) |
| 98 | if prefix: |
| 99 | return {match[len(prefix) + 1 :] for match in matches} |
| 100 | else: |
| 101 | return set(matches) |
| 102 | |
| 103 | def attr_matches( |
| 104 | self, cw: str, prefix: str = "", only_modules: bool = False |
| 105 | ) -> set[str]: |
| 106 | """Attributes to replace name with""" |
| 107 | full = f"{prefix}.{cw}" if prefix else cw |
| 108 | module_name, _, name_after_dot = full.rpartition(".") |
| 109 | if module_name not in sys.modules: |
| 110 | return set() |
| 111 | module = sys.modules[module_name] |
| 112 | if only_modules: |
| 113 | matches = { |
| 114 | name |
| 115 | for name in dir(module) |
| 116 | if name.startswith(name_after_dot) |
| 117 | and f"{module_name}.{name}" in sys.modules |
| 118 | } |
| 119 | else: |