checkup-python 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+ # version
2
+ # black
3
+ # ruff
4
+ # dep manager which,
@@ -0,0 +1,3 @@
1
+ from checkup_python.metrics.version import PythonVersionMetric
2
+
3
+ __all__ = ["PythonVersionMetric"]
@@ -0,0 +1,7 @@
1
+ def parse_semantic_version(version: str) -> tuple[int, ...]:
2
+ """
3
+ Parse version string into tuple of integers for comparison.
4
+ """
5
+
6
+ parts = version.split(".")
7
+ return tuple(int(part) for part in parts if part.isdigit())
@@ -0,0 +1,112 @@
1
+ import re
2
+ import sys
3
+ from pathlib import Path
4
+ from typing import ClassVar
5
+
6
+ from checkup.metric import Metric
7
+ from checkup.types import Context
8
+ from checkup_python.metrics.utils import parse_semantic_version
9
+
10
+
11
+ class PythonVersionMetric(Metric):
12
+ """
13
+ Metric to detect the Python version configured for a project.
14
+
15
+ Checks (in order):
16
+ 1. .python-version file
17
+ 2. pyproject.toml
18
+ 3. Falls back to current runtime version
19
+ """
20
+
21
+ name: ClassVar[str] = "python_version"
22
+ description: ClassVar[str] = "The Python version configured for the project"
23
+ unit: ClassVar[str] = "version"
24
+
25
+ def calculate(self, context: Context, metrics: dict[type[Metric], Metric]) -> None:
26
+ path = None
27
+
28
+ if "path" in context:
29
+ path = Path(context["path"])
30
+ else:
31
+ path = Path.cwd()
32
+
33
+ version = (
34
+ self._read_python_version_file(path)
35
+ or self._read_pyproject_toml(path)
36
+ or self._get_runtime_version()
37
+ )
38
+
39
+ self.value = version
40
+
41
+ def _read_python_version_file(self, path: Path) -> str | None:
42
+ """
43
+ Read version from `.python-version`.
44
+ """
45
+
46
+ version_file = path / ".python-version"
47
+ if not version_file.exists():
48
+ return None
49
+
50
+ return (
51
+ version_file.read_text().strip().removeprefix("python-").removeprefix("py")
52
+ )
53
+
54
+ def _read_pyproject_toml(self, path: Path) -> str | None:
55
+ """
56
+ Extract Python version from `pyproject.toml`.
57
+ """
58
+
59
+ pyproject_file = path / "pyproject.toml"
60
+ if not pyproject_file.exists():
61
+ return None
62
+
63
+ content = pyproject_file.read_text()
64
+ # Look for requires-python = ">=3.11" or similar
65
+ match = re.search(r'requires-python\s*=\s*["\']([^"\']+)["\']', content)
66
+ if not match:
67
+ return None
68
+
69
+ version_spec = match.group(1)
70
+ # Extract version number from spec like ">=3.11", "^3.11", "~=3.11.0"
71
+ version_match = re.search(r"(\d+\.\d+(?:\.\d+)?)", version_spec)
72
+ if not version_match:
73
+ return None
74
+
75
+ return version_match.group(1)
76
+
77
+ def _get_runtime_version(self) -> str:
78
+ """
79
+ Get the current runtime Python version.
80
+ """
81
+
82
+ return f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
83
+
84
+ def __lt__(self, other) -> bool:
85
+ if not isinstance(other, PythonVersionMetric):
86
+ return NotImplemented
87
+ return parse_semantic_version(self.value) < parse_semantic_version(other.value)
88
+
89
+ def __le__(self, other) -> bool:
90
+ if not isinstance(other, PythonVersionMetric):
91
+ return NotImplemented
92
+ return parse_semantic_version(self.value) <= parse_semantic_version(other.value)
93
+
94
+ def __gt__(self, other) -> bool:
95
+ if not isinstance(other, PythonVersionMetric):
96
+ return NotImplemented
97
+ return parse_semantic_version(self.value) > parse_semantic_version(other.value)
98
+
99
+ def __ge__(self, other) -> bool:
100
+ if not isinstance(other, PythonVersionMetric):
101
+ return NotImplemented
102
+ return parse_semantic_version(self.value) >= parse_semantic_version(other.value)
103
+
104
+ def __eq__(self, other) -> bool:
105
+ if not isinstance(other, PythonVersionMetric):
106
+ return NotImplemented
107
+ return parse_semantic_version(self.value) == parse_semantic_version(other.value)
108
+
109
+ def __ne__(self, other) -> bool:
110
+ if not isinstance(other, PythonVersionMetric):
111
+ return NotImplemented
112
+ return parse_semantic_version(self.value) != parse_semantic_version(other.value)
@@ -0,0 +1,36 @@
1
+ from typing import ClassVar
2
+
3
+ from checkup.metric import Metric
4
+ from checkup.types import Context
5
+ from checkup_python.metrics.utils import parse_semantic_version
6
+ from checkup_python.metrics.version import PythonVersionMetric
7
+
8
+
9
+ class PythonVersionCheckMetric(Metric):
10
+ """
11
+ Metric that checks the Python version of the current project
12
+ and compares it to given thresholds.
13
+ """
14
+
15
+ name: ClassVar[str] = "python_version_check"
16
+ description: ClassVar[str] = (
17
+ "The Python version adheres to a minimum and maximum boundary"
18
+ )
19
+ unit: ClassVar[str] = "bool"
20
+
21
+ min_version: str
22
+ max_version: str
23
+
24
+ @classmethod
25
+ def depends_on(cls) -> list[type[Metric]]:
26
+ return [PythonVersionMetric]
27
+
28
+ def calculate(self, context: Context, metrics: dict[type[Metric], Metric]) -> None:
29
+ version_metric = metrics[PythonVersionMetric]
30
+ actual_version = version_metric.value
31
+
32
+ actual = parse_semantic_version(actual_version)
33
+ min_ver = parse_semantic_version(self.min_version)
34
+ max_ver = parse_semantic_version(self.max_version)
35
+
36
+ self.value = min_ver <= actual <= max_ver
@@ -0,0 +1,6 @@
1
+ Metadata-Version: 2.4
2
+ Name: checkup-python
3
+ Version: 0.2.0
4
+ Summary: Python metrics for checkup
5
+ Requires-Python: >=3.12
6
+ Requires-Dist: checkup
@@ -0,0 +1,8 @@
1
+ checkup_python/__init__.py,sha256=A2MO43t3qfaZzsCwjdC0Z7OKE3h9Y3i5dg71XBCBA10,46
2
+ checkup_python/metrics/__init__.py,sha256=qxHEK2U1en27kQt7_eRm4vxHlch5vROGDROabR9Jngs,98
3
+ checkup_python/metrics/utils.py,sha256=D8WQniMljWgnAwVhfBo6G6IK1K_58S2g3hiGpS-ZI8s,237
4
+ checkup_python/metrics/version.py,sha256=QY_CYtUzzsArlbCANtY74hzq-7TmuwRzEr_zHMhWMp8,3667
5
+ checkup_python/metrics/version_check.py,sha256=tV2SfdQ2u3LAfPF1b1VY0AlAI-HlKWY7-y3lAPtYIUc,1143
6
+ checkup_python-0.2.0.dist-info/METADATA,sha256=RdVOb_6CVv9VUKvVVSsCl6vFaKdHyvw-k49n5SbmwZE,141
7
+ checkup_python-0.2.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
8
+ checkup_python-0.2.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.29.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any