nmk-python 1.10.3__py3-none-any.whl → 1.11.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.
nmk_python/build.py CHANGED
@@ -11,12 +11,14 @@ from pathlib import Path
11
11
  from typing import cast
12
12
 
13
13
  from nmk.envbackend import EnvBackend
14
- from nmk.logs import NmkLogWrapper
14
+ from nmk.logs import NmkLogger, NmkLogWrapper
15
15
  from nmk.model.builder import NmkTaskBuilder
16
16
  from nmk.model.model import NmkModel
17
17
  from nmk.model.resolver import NmkDictConfigResolver, NmkListConfigResolver, NmkStrConfigResolver
18
18
  from nmk.utils import is_windows
19
19
  from packaging.requirements import Requirement
20
+ from tomlkit import loads
21
+ from tomlkit.toml_file import TOMLFile
20
22
 
21
23
  from nmk_python.backends.factory import BuildBackendFactory
22
24
 
@@ -70,6 +72,16 @@ class PackageBuilder(NmkTaskBuilder):
70
72
  dest.parent.mkdir(parents=True, exist_ok=True)
71
73
  shutil.copyfile(candidate, dest)
72
74
 
75
+ # Update project file scm root
76
+ build_project = build_path / project_path.name
77
+ with build_project.open() as f:
78
+ project_doc = loads(f.read())
79
+ scm_config = cast(dict[str, dict[str, str]], project_doc.get("tool")).get("setuptools_scm") # type: ignore
80
+ assert scm_config is not None, "Can't find setuptools_scm config in project file"
81
+ scm_config["root"] = "/".join([".."] * len(build_path.relative_to(project_root).parts))
82
+ project_output = TOMLFile(build_project)
83
+ project_output.write(project_doc)
84
+
73
85
  # Handle extra resources
74
86
  for src, dst in extra_resources.items():
75
87
  src_path, dst_path = Path(src), Path(dst)
@@ -328,3 +340,38 @@ class PythonIgnoredLockfileResolver(NmkListConfigResolver):
328
340
  if not self.model.env_backend.is_locked and self.model.env_backend.name == "uv":
329
341
  return ["uv.lock"] # pragma: no cover
330
342
  return []
343
+
344
+
345
+ class PythonMergedConstraintsResolver(NmkListConfigResolver):
346
+ """
347
+ Python merged constraints resolver
348
+ """
349
+
350
+ def get_value(self, name: str, constraints: list[str], constraints_files: list[str]) -> list[str]: # pyright: ignore[reportIncompatibleMethodOverride]
351
+ """
352
+ Return the merged list of constraints, coming from raw items and files
353
+ """
354
+
355
+ all_constraints: list[str] = []
356
+
357
+ # Step 1: read files
358
+ for constraints_file in map(Path, constraints_files):
359
+ # Check file existence
360
+ if not constraints_file.is_file():
361
+ NmkLogger.warning(f"Constraints file not found: {constraints_file}")
362
+ continue
363
+
364
+ def clean_line(line: str) -> str | None:
365
+ line = line.strip()
366
+ if not line.startswith("#"):
367
+ # Remove end of line comments (keep full line ones)
368
+ line = line.split("#", 1)[0].strip()
369
+ return line
370
+
371
+ # Get lines
372
+ all_constraints.extend(filter(None, map(clean_line, constraints_file.read_text().splitlines())))
373
+
374
+ # Step 2: add items
375
+ all_constraints.extend(constraints)
376
+
377
+ return all_constraints
nmk_python/build.yml CHANGED
@@ -108,6 +108,19 @@ config:
108
108
  # Generated python dependencies metadata file
109
109
  pythonDepsMetadata: ${outputDir}/python_deps.json
110
110
 
111
+ # Python constraints, raw listed in nmk.yml files
112
+ pythonConstraints: []
113
+
114
+ # Python constraints files
115
+ pythonConstraintsFiles: []
116
+
117
+ # Merged constraints (from items + files)
118
+ pythonMergedConstraints:
119
+ __resolver__: nmk_python.build.PythonMergedConstraintsResolver
120
+ params:
121
+ constraints: ${pythonConstraints}
122
+ constraints_files: ${pythonConstraintsFiles}
123
+
111
124
  tasks:
112
125
  # Python editable install
113
126
  py.editable:
@@ -1,5 +1,5 @@
1
1
  [build-system]
2
- requires = ["{% if pythonUseUvBuildBackend %}uv_build>=0.9.18,<0.10.0{% else %}setuptools{% endif %}"]
2
+ requires = ["{% if pythonUseUvBuildBackend %}uv_build>=0.9.18,<0.10.0{% else %}setuptools", "setuptools_scm", "wheel{% endif %}"]
3
3
  build-backend = "{% if pythonUseUvBuildBackend %}uv_build{% else %}setuptools.build_meta{% endif %}"
4
4
 
5
5
  [project]
@@ -38,8 +38,10 @@ namespaces = false
38
38
  [tool.setuptools.package-data]
39
39
  "*" = ["*"]
40
40
 
41
- [tool.setuptools.dynamic.version]
42
- file = "{{ pythonVersionStamp }}"
41
+ [tool.setuptools_scm]
42
+ version_scheme = "{{ pythonVersionScheme }}"
43
+ local_scheme = "{{ pythonVersionLocalScheme }}"
44
+ fallback_version = "{{ pythonVersionFallback }}"
43
45
 
44
46
  {% endif %}[tool.distutils.bdist_wheel]
45
47
  plat-name = "{{ pythonPackagePlatform }}"
@@ -47,4 +49,11 @@ plat-name = "{{ pythonPackagePlatform }}"
47
49
  [tool.pyright]
48
50
  include = {{ pythonSrcFolders }}
49
51
  typeCheckingMode = "{{ pythonTypeCheckingMode }}"
50
- reportMissingTypeStubs = false
52
+ reportMissingTypeStubs = false{% if not backendUseRequirements %}
53
+
54
+ [tool.uv]
55
+ cache-keys = [{ file = "pyproject.toml" }, { git = { commit = true, tags = true } }]
56
+ {% if pythonMergedConstraints %}
57
+ constraint-dependencies = {{ pythonMergedConstraints }}
58
+ {% endif %}
59
+ {% endif %}
nmk_python/version.py CHANGED
@@ -3,13 +3,11 @@ Python version handling
3
3
  """
4
4
 
5
5
  import platform
6
- import re
6
+ from typing import cast
7
7
 
8
8
  from nmk.model.builder import NmkTaskBuilder
9
9
  from nmk.model.resolver import NmkListConfigResolver, NmkStrConfigResolver
10
-
11
- # Git version pattern
12
- _GIT_VERSION_PATTERN = re.compile("([^-]+)(?:-([0-9]+))?(?:-(.+))?")
10
+ from setuptools_scm import get_version
13
11
 
14
12
 
15
13
  class PythonVersionResolver(NmkStrConfigResolver):
@@ -17,26 +15,12 @@ class PythonVersionResolver(NmkStrConfigResolver):
17
15
  Python version resolver
18
16
  """
19
17
 
20
- def get_value(self, name: str) -> str:
18
+ def get_value(self, name: str, root: str, version_scheme: str, local_scheme: str, fallback_version: str) -> str: # type: ignore
21
19
  """
22
- Turn the git version in the Python way
20
+ Delegates to setuptools_scm to get the version from git
23
21
  """
24
- git_version = self.model.config["gitVersion"].value
25
- m = _GIT_VERSION_PATTERN.match(git_version)
26
- if m is not None:
27
- # Build python version from git version segments
28
- out = m.group(1)
29
- if m.group(2) is not None:
30
- # Add commits count
31
- out += f".post{m.group(2)}"
32
- if m.group(3) is not None:
33
- # Add hash/dirty
34
- out += f"+{m.group(3)}".replace("-", ".")
35
- return out
36
-
37
- # Probably a simpler version (without segments)
38
- # Assume it is already compliant...
39
- return git_version
22
+
23
+ return get_version(root=root, version_scheme=version_scheme, local_scheme=local_scheme, fallback_version=fallback_version)
40
24
 
41
25
 
42
26
  class PythonVersionRefresh(NmkTaskBuilder):
@@ -44,11 +28,11 @@ class PythonVersionRefresh(NmkTaskBuilder):
44
28
  Python version builder
45
29
  """
46
30
 
47
- def build(self, version: str):
31
+ def build(self, version: str): # type: ignore
48
32
  """
49
33
  Simple python version dump
50
34
  """
51
- self.logger.info(self.task.emoji, self.task.description)
35
+ self.logger.info(self.task.emoji, self.task.description) # type: ignore
52
36
  with self.main_output.open("w") as f:
53
37
  f.write(version)
54
38
 
@@ -69,7 +53,7 @@ class PythonSupportedVersionsResolver(NmkListConfigResolver):
69
53
  return list(map(int, v.split(".")))
70
54
 
71
55
  # Get min/max values, and verify consistency
72
- min_ver, max_ver = self.model.config["pythonMinVersion"].value, self.model.config["pythonMaxVersion"].value
56
+ min_ver, max_ver = cast(tuple[str, str], (self.model.config["pythonMinVersion"].value, self.model.config["pythonMaxVersion"].value))
73
57
  min_split, max_split = _split_version(min_ver), _split_version(max_ver)
74
58
  prefix = "Inconsistency in python min/max supported versions: "
75
59
  assert len(min_split) == len(max_split), prefix + "not the same segments count"
nmk_python/version.yml CHANGED
@@ -1,28 +1,38 @@
1
1
  config:
2
- # The python version itself
3
- pythonVersion:
4
- __resolver__: nmk_python.version.PythonVersionResolver
2
+ # Automated version computing from git tags -- see https://setuptools-scm.readthedocs.io/en/latest/config/
3
+ pythonVersionScheme: no-guess-dev
4
+ pythonVersionLocalScheme: node-and-date
5
+ pythonVersionFallback: "0.0.0"
5
6
 
6
- # Python version stamp file
7
- pythonVersionStamp: ${outputDir}/.pythonversion
7
+ # The python version itself
8
+ pythonVersion:
9
+ __resolver__: nmk_python.version.PythonVersionResolver
10
+ params:
11
+ root: ${PROJECTDIR}
12
+ version_scheme: ${pythonVersionScheme}
13
+ local_scheme: ${pythonVersionLocalScheme}
14
+ fallback_version: ${pythonVersionFallback}
8
15
 
9
- # Python supported versions range (min-max)
10
- pythonMinVersion: "3.10"
11
- pythonMaxVersion: "3.14"
12
- pythonSupportedVersions:
13
- __resolver__: nmk_python.version.PythonSupportedVersionsResolver
16
+ # Python version stamp file
17
+ pythonVersionStamp: ${outputDir}/.pythonversion
18
+
19
+ # Python supported versions range (min-max)
20
+ pythonMinVersion: "3.10"
21
+ pythonMaxVersion: "3.14"
22
+ pythonSupportedVersions:
23
+ __resolver__: nmk_python.version.PythonSupportedVersionsResolver
14
24
 
15
25
  tasks:
16
- # To refresh python version stamp file
17
- py.version:
18
- description: Refresh python version
19
- emoji: ":snake:.:label: "
20
- input: ${gitVersionStamp}
21
- output: ${pythonVersionStamp}
22
- params:
23
- version: ${pythonVersion}
24
- silent: true
25
- builder: nmk_python.version.PythonVersionRefresh
26
- deps:
27
- - git.version
28
- appendToDeps: setup
26
+ # To refresh python version stamp file
27
+ py.version:
28
+ description: Refresh python version
29
+ emoji: ":snake:.:label: "
30
+ input: ${gitVersionStamp}
31
+ output: ${pythonVersionStamp}
32
+ params:
33
+ version: ${pythonVersion}
34
+ silent: true
35
+ builder: nmk_python.version.PythonVersionRefresh
36
+ deps:
37
+ - git.version
38
+ appendToDeps: setup
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nmk-python
3
- Version: 1.10.3
3
+ Version: 1.11.0
4
4
  Summary: Python plugin for nmk build system
5
5
  Author: The dynod project
6
6
  Maintainer: The dynod project
@@ -22,6 +22,7 @@ Requires-Dist: Jinja2
22
22
  Requires-Dist: tomlkit
23
23
  Requires-Dist: setuptools
24
24
  Requires-Dist: wheel
25
+ Requires-Dist: setuptools-scm
25
26
  Requires-Dist: build
26
27
  Requires-Dist: ruff
27
28
  Requires-Dist: pytest-xdist
@@ -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=K-ZPBSN0YgWQqS4Nz2tRg-y2zTFvcutDiNR7Ii1NrMY,12979
4
- nmk_python/build.yml,sha256=kkaJV535tgcfDV65Pjxfh4HMexCS3muQ5oazFtqgYXI,5958
3
+ nmk_python/build.py,sha256=kcixJP5-YgKBKJ-gVtHpvyI3WvjmVHgwEgL9e3OJBNU,14860
4
+ nmk_python/build.yml,sha256=p_ziFqTxNqPn6hvLyHtutVJVVmlXqbkr7TbFo64_45w,6336
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,8 +11,8 @@ 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=fLpOWdujYwlJB7XhWaOGCTeg3gQaClk2YHoRkkW64dE,3109
15
- nmk_python/version.yml,sha256=WpZyQ2mChmvA_6eVb_Yp6ZaFIkX6oINxWBhKgb8h4GE,833
14
+ nmk_python/version.py,sha256=w15Zk7_TgqEsVSFN7Ql71-5gO5yOXoIYRdI_QlvMjYI,2738
15
+ nmk_python/version.yml,sha256=D_rUnEzjEtCmCgUhfaDPSsANaRkcDW7aZgPX6GZOUIk,1159
16
16
  nmk_python/_buildenv/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  nmk_python/_buildenv/template.py,sha256=avDeQuMSYHTiTwAgLbrpTPZ6bSaEqjCZDkcpzFxNt88,4568
18
18
  nmk_python/backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -21,7 +21,7 @@ nmk_python/backends/factory.py,sha256=NMYByORffwSSIjeNMLkOnwh6x1xhJQVhoV-0rSooq6
21
21
  nmk_python/backends/pip_build_backend.py,sha256=4MGYghBeMjZhUlKTwE0svSHArYwOAaK1I6_gmeNnwaI,1698
22
22
  nmk_python/backends/uv_build_backend.py,sha256=cIQwKVsYWHlVQCmHWjjoC-3aRmWiHK55VSGexQbn_vw,1963
23
23
  nmk_python/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
- nmk_python/templates/build.toml.jinja,sha256=6F1Kdb32JVBWEitxLC7AsUdhx2VTyQEyWhhSb7n3oBs,1770
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
26
26
  nmk_python/templates/python-settings.json.jinja,sha256=v-GlXJSGdtfaEZIinSC_aT54rlKArFe1RZ-BgPdbANM,666
27
27
  nmk_python/templates/python-test-debug-launch.json.jinja,sha256=J_xju2EpHNXvgvqBxlf99p7g-ZMh3xE-_2r7o_57gpU,364
@@ -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.10.3.dist-info/licenses/LICENSE,sha256=PROo9EW7wP6jmSr_90OluItAsIB411b_CAqEBioMKpI,1074
34
- nmk_python-1.10.3.dist-info/METADATA,sha256=4IagnIbEAXFlSZ2U0s1Qnmp9pMQDVwwQEkPcqQiM8mU,3175
35
- nmk_python-1.10.3.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
36
- nmk_python-1.10.3.dist-info/entry_points.txt,sha256=QLXIIXl6wODHDnVkh7KuiLv_XzfFtNfdWwpxyB675ak,88
37
- nmk_python-1.10.3.dist-info/top_level.txt,sha256=MCb5w_hoOZ0kk3Dajxrd9Pz6lZ3pyuS6TQCRA3vddTo,11
38
- nmk_python-1.10.3.dist-info/RECORD,,
33
+ nmk_python-1.11.0.dist-info/licenses/LICENSE,sha256=PROo9EW7wP6jmSr_90OluItAsIB411b_CAqEBioMKpI,1074
34
+ nmk_python-1.11.0.dist-info/METADATA,sha256=U8SM11IYPXQVPE-ajBZtYmcV2yllVRn62A_4YifjWhw,3205
35
+ nmk_python-1.11.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
36
+ nmk_python-1.11.0.dist-info/entry_points.txt,sha256=QLXIIXl6wODHDnVkh7KuiLv_XzfFtNfdWwpxyB675ak,88
37
+ nmk_python-1.11.0.dist-info/top_level.txt,sha256=MCb5w_hoOZ0kk3Dajxrd9Pz6lZ3pyuS6TQCRA3vddTo,11
38
+ nmk_python-1.11.0.dist-info/RECORD,,