|
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