|
36 | 36 | import importlib_metadata
|
37 | 37 | else:
|
38 | 38 | import importlib.metadata as importlib_metadata
|
39 |
| - |
| 39 | +try: |
| 40 | + _package_map = importlib_metadata.packages_distributions() # load-once to avoid expensive calls |
| 41 | +except Exception: |
| 42 | + _package_map = None |
40 | 43 |
|
41 | 44 | logger = logging.get_logger(__name__) # pylint: disable=invalid-name
|
42 | 45 |
|
|
56 | 59 |
|
57 | 60 |
|
58 | 61 | def _is_package_available(pkg_name: str, get_dist_name: bool = False) -> Tuple[bool, str]:
|
| 62 | + global _package_map |
59 | 63 | pkg_exists = importlib.util.find_spec(pkg_name) is not None
|
60 | 64 | pkg_version = "N/A"
|
61 | 65 |
|
62 | 66 | if pkg_exists:
|
| 67 | + if _package_map is None: |
| 68 | + _package_map = defaultdict(list) |
| 69 | + try: |
| 70 | + # Fallback for Python < 3.10 |
| 71 | + for dist in importlib_metadata.distributions(): |
| 72 | + _top_level_declared = (dist.read_text("top_level.txt") or "").split() |
| 73 | + _infered_opt_names = { |
| 74 | + f.parts[0] if len(f.parts) > 1 else inspect.getmodulename(f) for f in (dist.files or []) |
| 75 | + } - {None} |
| 76 | + _top_level_inferred = filter(lambda name: "." not in name, _infered_opt_names) |
| 77 | + for pkg in _top_level_declared or _top_level_inferred: |
| 78 | + _package_map[pkg].append(dist.metadata["Name"]) |
| 79 | + except Exception as _: |
| 80 | + pass |
63 | 81 | try:
|
64 |
| - package_map = importlib_metadata.packages_distributions() |
65 |
| - except Exception as e: |
66 |
| - package_map = defaultdict(list) |
67 |
| - if isinstance(e, AttributeError): |
68 |
| - try: |
69 |
| - # Fallback for Python < 3.10 |
70 |
| - for dist in importlib_metadata.distributions(): |
71 |
| - _top_level_declared = (dist.read_text("top_level.txt") or "").split() |
72 |
| - _infered_opt_names = { |
73 |
| - f.parts[0] if len(f.parts) > 1 else inspect.getmodulename(f) for f in (dist.files or []) |
74 |
| - } - {None} |
75 |
| - _top_level_inferred = filter(lambda name: "." not in name, _infered_opt_names) |
76 |
| - for pkg in _top_level_declared or _top_level_inferred: |
77 |
| - package_map[pkg].append(dist.metadata["Name"]) |
78 |
| - except Exception as _: |
79 |
| - pass |
80 |
| - |
81 |
| - try: |
82 |
| - if get_dist_name and pkg_name in package_map and package_map[pkg_name]: |
83 |
| - if len(package_map[pkg_name]) > 1: |
| 82 | + if get_dist_name and pkg_name in _package_map and _package_map[pkg_name]: |
| 83 | + if len(_package_map[pkg_name]) > 1: |
84 | 84 | logger.warning(
|
85 |
| - f"Multiple distributions found for package {pkg_name}. Picked distribution: {package_map[pkg_name][0]}" |
| 85 | + f"Multiple distributions found for package {pkg_name}. Picked distribution: {_package_map[pkg_name][0]}" |
86 | 86 | )
|
87 |
| - pkg_name = package_map[pkg_name][0] |
| 87 | + pkg_name = _package_map[pkg_name][0] |
88 | 88 | pkg_version = importlib_metadata.version(pkg_name)
|
89 | 89 | logger.debug(f"Successfully imported {pkg_name} version {pkg_version}")
|
90 | 90 | except (ImportError, importlib_metadata.PackageNotFoundError):
|
|
0 commit comments