Build import graph for Lib modules (full module paths like urllib.request). Uses cross-process shelve cache based on CPython version. Args: lib_prefix: RustPython Lib directory Returns: Dict mapping full_module_path -> set of modules it imports
(lib_prefix: str)
| 1443 | |
| 1444 | |
| 1445 | def _build_lib_import_graph(lib_prefix: str) -> dict[str, set[str]]: |
| 1446 | """Build import graph for Lib modules (full module paths like urllib.request). |
| 1447 | |
| 1448 | Uses cross-process shelve cache based on CPython version. |
| 1449 | |
| 1450 | Args: |
| 1451 | lib_prefix: RustPython Lib directory |
| 1452 | |
| 1453 | Returns: |
| 1454 | Dict mapping full_module_path -> set of modules it imports |
| 1455 | """ |
| 1456 | # In-process cache |
| 1457 | if lib_prefix in _lib_import_graph_cache: |
| 1458 | return _lib_import_graph_cache[lib_prefix] |
| 1459 | |
| 1460 | # Cross-process cache (only for standard Lib directory) |
| 1461 | use_file_cache = _is_standard_lib_path(lib_prefix) |
| 1462 | if use_file_cache: |
| 1463 | version = _get_cpython_version("cpython") |
| 1464 | shelve_key = f"lib_import_graph:{version}" |
| 1465 | try: |
| 1466 | with shelve.open(_get_cache_path()) as db: |
| 1467 | if shelve_key in db: |
| 1468 | import_graph = db[shelve_key] |
| 1469 | _lib_import_graph_cache[lib_prefix] = import_graph |
| 1470 | return import_graph |
| 1471 | except Exception: |
| 1472 | pass |
| 1473 | |
| 1474 | # Build from scratch |
| 1475 | lib_dir = pathlib.Path(lib_prefix) |
| 1476 | if not lib_dir.exists(): |
| 1477 | return {} |
| 1478 | |
| 1479 | import_graph: dict[str, set[str]] = {} |
| 1480 | |
| 1481 | for entry in lib_dir.iterdir(): |
| 1482 | if entry.name.startswith(("_", ".")): |
| 1483 | continue |
| 1484 | if entry.name == "test": |
| 1485 | continue |
| 1486 | |
| 1487 | if entry.is_file() and entry.suffix == ".py": |
| 1488 | content = safe_read_text(entry) |
| 1489 | if content: |
| 1490 | imports = parse_lib_imports(content) |
| 1491 | imports.discard(entry.stem) |
| 1492 | import_graph[entry.stem] = imports |
| 1493 | elif entry.is_dir() and (entry / "__init__.py").exists(): |
| 1494 | for py_file in entry.glob("**/*.py"): |
| 1495 | content = safe_read_text(py_file) |
| 1496 | if content: |
| 1497 | imports = parse_lib_imports(content) |
| 1498 | rel_path = py_file.relative_to(lib_dir) |
| 1499 | if rel_path.name == "__init__.py": |
| 1500 | full_name = str(rel_path.parent).replace("/", ".") |
| 1501 | else: |
| 1502 | full_name = str(rel_path.with_suffix("")).replace("/", ".") |
no test coverage detected