nmk-python 1.11.0__py3-none-any.whl → 1.12.1__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.
- nmk_python/_buildenv/template.py +8 -20
- nmk_python/backends/uv_build_backend.py +0 -5
- nmk_python/build.py +42 -4
- nmk_python/build.yml +6 -1
- nmk_python/version.py +1 -1
- {nmk_python-1.11.0.dist-info → nmk_python-1.12.1.dist-info}/METADATA +1 -1
- {nmk_python-1.11.0.dist-info → nmk_python-1.12.1.dist-info}/RECORD +11 -11
- {nmk_python-1.11.0.dist-info → nmk_python-1.12.1.dist-info}/WHEEL +1 -1
- {nmk_python-1.11.0.dist-info → nmk_python-1.12.1.dist-info}/entry_points.txt +0 -0
- {nmk_python-1.11.0.dist-info → nmk_python-1.12.1.dist-info}/licenses/LICENSE +0 -0
- {nmk_python-1.11.0.dist-info → nmk_python-1.12.1.dist-info}/top_level.txt +0 -0
nmk_python/_buildenv/template.py
CHANGED
|
@@ -67,35 +67,23 @@ class NmkPythonProjectTemplate(NmkBaseProjectTemplate):
|
|
|
67
67
|
|
|
68
68
|
def handle_dependencies(self, packages: list[str]) -> dict[str, NmkConfigType]:
|
|
69
69
|
# Iterate on packages
|
|
70
|
-
|
|
71
|
-
simple_refs: list[str] = []
|
|
72
|
-
file_refs: list[str] = []
|
|
70
|
+
other_refs: list[str] = []
|
|
73
71
|
dep_refs: list[str] = []
|
|
72
|
+
|
|
73
|
+
# Pre-filter non-dev dependencies
|
|
74
74
|
for package in packages:
|
|
75
75
|
# Check for dependency groups (no group means it's a regular dependency, otherwise it's a dev dependency)
|
|
76
76
|
if ":" not in package:
|
|
77
77
|
dep_refs.append(package)
|
|
78
|
-
# Dev dependencies
|
|
79
78
|
else:
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
file_refs.append(package)
|
|
85
|
-
elif (Path.cwd() / package).is_file():
|
|
86
|
-
file_refs.append(f"${{PROJECTDIR}}/{package}")
|
|
87
|
-
else:
|
|
88
|
-
simple_refs.append(package)
|
|
89
|
-
else:
|
|
90
|
-
simple_refs.append(package)
|
|
79
|
+
other_refs.append(package)
|
|
80
|
+
|
|
81
|
+
# Delegate to normal processing
|
|
82
|
+
config_items: dict[str, NmkConfigType] = super().handle_dependencies(other_refs)
|
|
91
83
|
|
|
92
84
|
# Build settings
|
|
93
|
-
if dep_refs:
|
|
85
|
+
if dep_refs: # pragma: no branch
|
|
94
86
|
config_items["pythonPackageRequirements"] = dep_refs
|
|
95
|
-
if simple_refs:
|
|
96
|
-
config_items["venvPkgDeps"] = simple_refs
|
|
97
|
-
if file_refs:
|
|
98
|
-
config_items["venvArchiveDeps"] = file_refs
|
|
99
87
|
|
|
100
88
|
return config_items
|
|
101
89
|
|
|
@@ -39,11 +39,6 @@ class UvBuildBackend(PythonBuildBackend):
|
|
|
39
39
|
# Name for wheel sub-directory
|
|
40
40
|
wheel_sub_dir = "wheel_dist"
|
|
41
41
|
|
|
42
|
-
# Check for (experimental) uv-build backend
|
|
43
|
-
if self._model.config["pythonUseUvBuildBackend"].value:
|
|
44
|
-
# Prepare project version (without updating the venv)
|
|
45
|
-
self._env_backend.subprocess(["version", "--active", "--no-sync", wheel_version], cwd=build_dir)
|
|
46
|
-
|
|
47
42
|
# Delegate to uv
|
|
48
43
|
build_args = ["build", "--wheel", "--out-dir", wheel_sub_dir]
|
|
49
44
|
self._env_backend.subprocess(build_args, cwd=build_dir)
|
nmk_python/build.py
CHANGED
|
@@ -4,6 +4,7 @@ Python package build module
|
|
|
4
4
|
|
|
5
5
|
import importlib.metadata
|
|
6
6
|
import json
|
|
7
|
+
import os
|
|
7
8
|
import shutil
|
|
8
9
|
from fnmatch import fnmatch
|
|
9
10
|
from itertools import product
|
|
@@ -17,6 +18,7 @@ from nmk.model.model import NmkModel
|
|
|
17
18
|
from nmk.model.resolver import NmkDictConfigResolver, NmkListConfigResolver, NmkStrConfigResolver
|
|
18
19
|
from nmk.utils import is_windows
|
|
19
20
|
from packaging.requirements import Requirement
|
|
21
|
+
from packaging.version import Version
|
|
20
22
|
from tomlkit import loads
|
|
21
23
|
from tomlkit.toml_file import TOMLFile
|
|
22
24
|
|
|
@@ -67,7 +69,7 @@ class PackageBuilder(NmkTaskBuilder):
|
|
|
67
69
|
project_root = project_path.parent
|
|
68
70
|
for source_dir in map(Path, source_dirs):
|
|
69
71
|
shutil.copytree(source_dir, build_path / source_dir.relative_to(project_root))
|
|
70
|
-
for candidate in filter(lambda p: p.is_file(), map(Path, [project_path,
|
|
72
|
+
for candidate in filter(lambda p: p.is_file(), map(Path, [project_path, project_root / "README.md", project_root / "LICENSE"])):
|
|
71
73
|
dest = build_path / candidate.relative_to(project_root)
|
|
72
74
|
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
73
75
|
shutil.copyfile(candidate, dest)
|
|
@@ -266,12 +268,14 @@ class DepsMetadataBuilder(NmkTaskBuilder):
|
|
|
266
268
|
Generate python dependencies metadata file
|
|
267
269
|
"""
|
|
268
270
|
|
|
269
|
-
def build(self, root_name: str, local_deps: list[str]): # pyright: ignore[reportIncompatibleMethodOverride]
|
|
271
|
+
def build(self, root_name: str, local_deps: list[str], constraints: list[str], fail_on_error: bool): # pyright: ignore[reportIncompatibleMethodOverride]
|
|
270
272
|
"""
|
|
271
273
|
Generate python dependencies metadata file
|
|
272
274
|
|
|
273
275
|
:param root_name: name of the root package
|
|
274
276
|
:param local_deps: list of workspace local dependencies patterns
|
|
277
|
+
:param constraints: list of package constraints (may contain comments) to be checked against found dependencies
|
|
278
|
+
:param fail_on_error: if there are mismatches between actual dependencies and constraints, and if true, and the build in error
|
|
275
279
|
"""
|
|
276
280
|
|
|
277
281
|
# Normalization implementation
|
|
@@ -325,6 +329,40 @@ class DepsMetadataBuilder(NmkTaskBuilder):
|
|
|
325
329
|
)
|
|
326
330
|
)
|
|
327
331
|
|
|
332
|
+
# Check constraints vs external deps if any
|
|
333
|
+
filtered_constraints = [line for line in constraints if not line.startswith("# ")]
|
|
334
|
+
if filtered_constraints and output_data[_EXTERNAL_DEPS_KEY]: # pragma: no branch
|
|
335
|
+
try:
|
|
336
|
+
self._check_constraints(filtered_constraints, output_data[_EXTERNAL_DEPS_KEY], fail_on_error)
|
|
337
|
+
except Exception as e:
|
|
338
|
+
# Touch output file to force task to be retriggered on next build
|
|
339
|
+
input_state = self.main_input.stat()
|
|
340
|
+
os.utime(self.main_output, (input_state.st_atime, input_state.st_mtime))
|
|
341
|
+
raise e
|
|
342
|
+
|
|
343
|
+
def _check_constraints(self, constraints: list[str], deps: dict[str, str], fail_on_error: bool):
|
|
344
|
+
# Build all requirements
|
|
345
|
+
all_reqs = {r[0].name: r for r in [(Requirement(line), line) for line in constraints]}
|
|
346
|
+
|
|
347
|
+
# Count errors
|
|
348
|
+
errors = 0
|
|
349
|
+
|
|
350
|
+
# Browse dependencies
|
|
351
|
+
for name, version in deps.items():
|
|
352
|
+
# Check missing constraint on actual dependency
|
|
353
|
+
if name not in all_reqs:
|
|
354
|
+
self.logger.warning(f"Found dependency with missing constraint: {name}")
|
|
355
|
+
errors += 1
|
|
356
|
+
continue
|
|
357
|
+
|
|
358
|
+
# Check mismatch version
|
|
359
|
+
req, req_line = all_reqs[name]
|
|
360
|
+
if Version(version) not in req.specifier:
|
|
361
|
+
self.logger.warning(f"Found dependency with constraint mismatch: {name} ({version}) vs '{req_line}'")
|
|
362
|
+
errors += 1
|
|
363
|
+
|
|
364
|
+
assert (errors == 0) or not fail_on_error, f"{errors} error(s) found while checking dependencies vs constraints"
|
|
365
|
+
|
|
328
366
|
|
|
329
367
|
class PythonIgnoredLockfileResolver(NmkListConfigResolver):
|
|
330
368
|
"""
|
|
@@ -338,8 +376,8 @@ class PythonIgnoredLockfileResolver(NmkListConfigResolver):
|
|
|
338
376
|
|
|
339
377
|
# Ignore uv.lock file if using uv env backend and project is not locked
|
|
340
378
|
if not self.model.env_backend.is_locked and self.model.env_backend.name == "uv":
|
|
341
|
-
return ["uv.lock"]
|
|
342
|
-
return []
|
|
379
|
+
return ["uv.lock"]
|
|
380
|
+
return [] # pragma: no cover
|
|
343
381
|
|
|
344
382
|
|
|
345
383
|
class PythonMergedConstraintsResolver(NmkListConfigResolver):
|
nmk_python/build.yml
CHANGED
|
@@ -78,7 +78,7 @@ config:
|
|
|
78
78
|
with:
|
|
79
79
|
user: __token__
|
|
80
80
|
password: ${{ secrets.pypi_password }}
|
|
81
|
-
packages_dir: ${r!
|
|
81
|
+
packages_dir: ${r!pythonBuildDir}/wheel_dist
|
|
82
82
|
|
|
83
83
|
# Wheel install arguments (for pip backend)
|
|
84
84
|
pythonWheelPipInstallArgs:
|
|
@@ -121,6 +121,9 @@ config:
|
|
|
121
121
|
constraints: ${pythonConstraints}
|
|
122
122
|
constraints_files: ${pythonConstraintsFiles}
|
|
123
123
|
|
|
124
|
+
# Constraints check mode (strict or not)
|
|
125
|
+
pythonConstraintsStrictCheck: false
|
|
126
|
+
|
|
124
127
|
tasks:
|
|
125
128
|
# Python editable install
|
|
126
129
|
py.editable:
|
|
@@ -154,6 +157,8 @@ tasks:
|
|
|
154
157
|
params:
|
|
155
158
|
root_name: ${pythonPackage}
|
|
156
159
|
local_deps: ${pythonLocalDepsPatterns}
|
|
160
|
+
constraints: ${pythonMergedConstraints}
|
|
161
|
+
fail_on_error: ${pythonConstraintsStrictCheck}
|
|
157
162
|
|
|
158
163
|
# Python wheel build
|
|
159
164
|
py.build:
|
nmk_python/version.py
CHANGED
|
@@ -59,7 +59,7 @@ class PythonSupportedVersionsResolver(NmkListConfigResolver):
|
|
|
59
59
|
assert len(min_split) == len(max_split), prefix + "not the same segments count"
|
|
60
60
|
assert len(min_split) == 2, prefix + "can only deal with X.Y versions (2 segments expected)"
|
|
61
61
|
assert min_split[0] == max_split[0], prefix + "can't deal with different major versions"
|
|
62
|
-
assert max_split[1]
|
|
62
|
+
assert max_split[1] >= min_split[1], prefix + "max isn't greater than min"
|
|
63
63
|
|
|
64
64
|
# Also verifies current runtime is in range
|
|
65
65
|
p_ver = platform.python_version()
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
nmk_python/__init__.py,sha256=EouCWXbAeObby1vOCx0Vx_WaGC2fEEFDMCen3JZt4TU,446
|
|
2
2
|
nmk_python/badges.yml,sha256=LzElZecCXKxdF-oPkvIwfnbQlOcAM_zUj6MelClmAug,749
|
|
3
|
-
nmk_python/build.py,sha256=
|
|
4
|
-
nmk_python/build.yml,sha256=
|
|
3
|
+
nmk_python/build.py,sha256=V2CiDI-srmFriYR7XuKJWZPuuBAv7LYX8drMz06jmug,16828
|
|
4
|
+
nmk_python/build.yml,sha256=nsHgL_2zrWKDV2bkiSMKZTtU_FKVCDXXRThajKylcsw,6527
|
|
5
5
|
nmk_python/doc.yml,sha256=12amAlYylH7JAHaqBIOoEZ_LrXY_bPNKuHrrwUkIj8w,932
|
|
6
6
|
nmk_python/files.py,sha256=K6Y-XKXuf8jh4x333Qgj6G1MyB-BgZ5Kd2-XCZhsfR4,2000
|
|
7
7
|
nmk_python/files.yml,sha256=jlp87gW9rTASUnsy7id7VWanaMUMN_py82bMa2adniM,813
|
|
@@ -11,15 +11,15 @@ nmk_python/ruff.py,sha256=TBmn5nFflcFRvjj36JtJGJ-GYHOK6XfhK9Jp-2dO5_E,1557
|
|
|
11
11
|
nmk_python/ruff.yml,sha256=L3vSTLGI3ZP46D64VxenhF9Gz3lo5-J9cRwgKBrVl48,2732
|
|
12
12
|
nmk_python/tests.py,sha256=p2dl41eZW8cpUMOa2DXi3CN3iVQEnElC88Ke89PRyy8,1597
|
|
13
13
|
nmk_python/tests.yml,sha256=by_Ml1JXjgt1-J96AMp-6gwhISVFVylRZowUvaMkfpk,1636
|
|
14
|
-
nmk_python/version.py,sha256=
|
|
14
|
+
nmk_python/version.py,sha256=ivSff_1l-u-rSACF91s58zX_EUzl0ate_JcX_l7dSQk,2739
|
|
15
15
|
nmk_python/version.yml,sha256=D_rUnEzjEtCmCgUhfaDPSsANaRkcDW7aZgPX6GZOUIk,1159
|
|
16
16
|
nmk_python/_buildenv/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
|
-
nmk_python/_buildenv/template.py,sha256
|
|
17
|
+
nmk_python/_buildenv/template.py,sha256=-yugMcl93gcKfPKrLYTmIMOEIoNvVWGVnqkY3-z4JF8,3922
|
|
18
18
|
nmk_python/backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
19
|
nmk_python/backends/build_backend.py,sha256=WO0wZaxGdPna4K2yK7pNLtZX3cKf6atLLa00931N43Y,1400
|
|
20
20
|
nmk_python/backends/factory.py,sha256=NMYByORffwSSIjeNMLkOnwh6x1xhJQVhoV-0rSooq6Q,953
|
|
21
21
|
nmk_python/backends/pip_build_backend.py,sha256=4MGYghBeMjZhUlKTwE0svSHArYwOAaK1I6_gmeNnwaI,1698
|
|
22
|
-
nmk_python/backends/uv_build_backend.py,sha256=
|
|
22
|
+
nmk_python/backends/uv_build_backend.py,sha256=gpM1L5FuJ5CF-OkRORnAbZHACPNhjkoO1sKZtdAhpf0,1671
|
|
23
23
|
nmk_python/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
24
|
nmk_python/templates/build.toml.jinja,sha256=D-RYPUGiqkYUKyQt_dP_tNFU-83eer7bnv57k4pMmIw,2137
|
|
25
25
|
nmk_python/templates/pytest.toml.jinja,sha256=zQ3SRWnF23Omxm7zInE54j0l3OyjXSOn5pQ5Pak8Boo,641
|
|
@@ -30,9 +30,9 @@ nmk_python/templates/src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
|
|
|
30
30
|
nmk_python/templates/src/__init__.py.jinja,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
31
31
|
nmk_python/templates/src/sample.py.jinja,sha256=OOTps7EjviwYFCIb5GpMHcidxhBY5NLQVlcFLqxuxNU,227
|
|
32
32
|
nmk_python/templates/src/test_sample.py.jinja,sha256=u-ShBoKDF3se9KvgQ1SzO4NwymjqNowwURF4Q1oR3wo,221
|
|
33
|
-
nmk_python-1.
|
|
34
|
-
nmk_python-1.
|
|
35
|
-
nmk_python-1.
|
|
36
|
-
nmk_python-1.
|
|
37
|
-
nmk_python-1.
|
|
38
|
-
nmk_python-1.
|
|
33
|
+
nmk_python-1.12.1.dist-info/licenses/LICENSE,sha256=PROo9EW7wP6jmSr_90OluItAsIB411b_CAqEBioMKpI,1074
|
|
34
|
+
nmk_python-1.12.1.dist-info/METADATA,sha256=kODo2u7iSzu4SF_YRJYprLfxncTzvvM5qZGLIhRqaZ0,3205
|
|
35
|
+
nmk_python-1.12.1.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
36
|
+
nmk_python-1.12.1.dist-info/entry_points.txt,sha256=QLXIIXl6wODHDnVkh7KuiLv_XzfFtNfdWwpxyB675ak,88
|
|
37
|
+
nmk_python-1.12.1.dist-info/top_level.txt,sha256=MCb5w_hoOZ0kk3Dajxrd9Pz6lZ3pyuS6TQCRA3vddTo,11
|
|
38
|
+
nmk_python-1.12.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|