-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathversioning.py
More file actions
61 lines (48 loc) · 2.1 KB
/
versioning.py
File metadata and controls
61 lines (48 loc) · 2.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import importlib.metadata
from typing import Any
from packaging.specifiers import SpecifierSet
from packaging.version import InvalidVersion, Version
def detect_module_version(module: Any, import_names: tuple[str, ...]) -> str | None:
candidates: list[str] = []
module_name = getattr(module, "__name__", None)
if isinstance(module_name, str) and module_name:
candidates.append(module_name.split(".")[0])
module_package = getattr(module, "__package__", None)
if isinstance(module_package, str) and module_package:
candidates.append(module_package.split(".")[0])
candidates.extend(name.split(".")[0] for name in import_names)
seen: set[str] = set()
for candidate in candidates:
if candidate in seen:
continue
seen.add(candidate)
try:
return importlib.metadata.version(candidate)
except importlib.metadata.PackageNotFoundError:
continue
version = getattr(module, "__version__", None)
return version if isinstance(version, str) else None
def make_specifier(*, min_version: str | None = None, max_version: str | None = None) -> SpecifierSet:
"""Build a :class:`SpecifierSet` from optional min/max bounds."""
spec = SpecifierSet(prereleases=True)
if min_version is not None:
spec &= SpecifierSet(f">={min_version}", prereleases=True)
if max_version is not None:
spec &= SpecifierSet(f"<={max_version}", prereleases=True)
return spec
def version_satisfies(version: str | None, spec: str | SpecifierSet | None) -> bool:
"""Return True if *version* satisfies the PEP 440 *spec*.
When *version* is ``None`` (i.e. we could not detect the installed
version), we optimistically return ``True`` so that patching still
proceeds. A failed detection should not silently disable
instrumentation.
"""
if spec is None:
return True
if version is None:
return True
try:
ss = spec if isinstance(spec, SpecifierSet) else SpecifierSet(spec, prereleases=True)
return Version(version) in ss
except InvalidVersion:
return False