Skip to content

Commit 43d6462

Browse files
committed
fix(utils): look up package versions without scanning all installed packages
1 parent d565fed commit 43d6462

2 files changed

Lines changed: 31 additions & 0 deletions

File tree

‎sentry_sdk/utils.py‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@
2828
# Python 3.10 and below
2929
BaseExceptionGroup = None # type: ignore
3030

31+
try:
32+
from importlib import metadata as importlib_metadata
33+
except ImportError:
34+
importlib_metadata = None # type: ignore[assignment]
35+
3136
from typing import TYPE_CHECKING
3237

3338
import sentry_sdk
@@ -1841,6 +1846,14 @@ def package_version(package: str) -> "Optional[Tuple[int, ...]]":
18411846
_replace_hyphens_dots_and_underscores_with_dashes(package)
18421847
)
18431848

1849+
if importlib_metadata is not None:
1850+
# Look up the single distribution instead of scanning (and parsing
1851+
# the metadata of) every installed package on each call.
1852+
try:
1853+
return parse_version(importlib_metadata.version(normalized_package))
1854+
except importlib_metadata.PackageNotFoundError:
1855+
return None
1856+
18441857
installed_packages = {
18451858
_replace_hyphens_dots_and_underscores_with_dashes(module): v
18461859
for module, v in _get_installed_modules().items()

‎tests/test_utils.py‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1412,6 +1412,24 @@ def test_package_version_is_none():
14121412
assert package_version("non_existent_package") is None
14131413

14141414

1415+
@pytest.mark.skipif(sys.version_info < (3, 8), reason="requires importlib.metadata")
1416+
def test_package_version_installed_package():
1417+
from importlib import metadata
1418+
1419+
assert package_version("pytest") == parse_version(metadata.version("pytest"))
1420+
1421+
1422+
@pytest.mark.skipif(sys.version_info < (3, 8), reason="requires importlib.metadata")
1423+
def test_package_version_does_not_scan_all_installed_packages(monkeypatch):
1424+
def _fail():
1425+
raise AssertionError("package_version must not scan all installed packages")
1426+
1427+
monkeypatch.setattr("sentry_sdk.utils._get_installed_modules", _fail)
1428+
1429+
assert package_version("pytest") is not None
1430+
assert package_version("non_existent_package") is None
1431+
1432+
14151433
@pytest.mark.parametrize(
14161434
"kwargs, expected",
14171435
[

0 commit comments

Comments
 (0)