1- # noxfile.py
2- # See https://nox.thea.codes/en/stable/config.html
1+ """Noxfile for the {{cookiecutter.project_name}} project."""
32
4- from pathlib import Path # Use pathlib for path manipulation
5- from typing import Any # Import Any for type hints
6- from typing import List # Import List for type hints
7- from typing import Optional # Import Optional for type hints
3+ from pathlib import Path
4+ from typing import List
85
96import nox
10- from nox .sessions import Session # Import Session type for hinting
7+ from nox .command import CommandFailed
8+ from nox .sessions import Session
119
1210nox .options .default_venv_backend = "uv"
13- nox .options .sessions = ["default" ]
1411
1512# Logic that helps avoid metaprogramming in cookiecutter-robust-python
16- MIN_PYTHON_VERSION_SLUG : int = int ({{ cookiecutter .min_python_version }} * 100 )
17- MAX_PYTHON_VERSION_SLUG : int = int ({{ cookiecutter .max_python_version }} * 100 )
13+ MIN_PYTHON_VERSION_SLUG : int = int ("{{ cookiecutter.min_python_version}}" . lstrip ( "3." ) )
14+ MAX_PYTHON_VERSION_SLUG : int = int ("{{ cookiecutter.max_python_version}}" . lstrip ( "3." ) )
1815
19- # Python versions to test against. As of April 2025 , generally 3.9-3.13 are actively supported.
16+ # Python versions to test against. As of April {{cookiecutter.copyright_year}} , generally {{cookiecutter.min_python_version}}-{{cookiecutter.max_python_version}} are actively supported.
2017# See: https://devguide.python.org/versions/ and https://endoflife.date/python
2118PYTHON_VERSIONS : List [str ] = [
22- str ( VERSION_SLUG / 100 ) for VERSION_SLUG in range (MIN_PYTHON_VERSION_SLUG , MAX_PYTHON_VERSION_SLUG + 1 )
19+ f"3. { VERSION_SLUG } " for VERSION_SLUG in range (MIN_PYTHON_VERSION_SLUG , MAX_PYTHON_VERSION_SLUG + 1 )
2320]
2421DEFAULT_PYTHON_VERSION : str = PYTHON_VERSIONS [- 1 ]
2522
2623REPO_ROOT : Path = Path (__file__ ).parent
2724CRATES_FOLDER : Path = REPO_ROOT / "rust"
28- PACKAGE_NAME : str = "{{ cookiecutter.package_name }}"
25+ PACKAGE_NAME : str = "{{cookiecutter.package_name}}"
2926
3027
3128# --- GRANULAR TASK AUTOMATION SESSIONS ---
@@ -54,7 +51,7 @@ def lint_python(session: Session) -> None:
5451
5552
5653@nox .session (python = PYTHON_VERSIONS )
57- def typecheck_python (session : Session ) -> None :
54+ def typecheck (session : Session ) -> None :
5855 """Run static type checking (Pyright) on Python code."""
5956 session .log ("Installing type checking dependencies..." )
6057 session .run ("uv" , "sync" , "--locked" , "--clean" , "--groups" , "dev" , "typecheck" , external = True )
@@ -63,7 +60,7 @@ def typecheck_python(session: Session) -> None:
6360 session .run ("uv" , "run" , "pyright" , external = True )
6461
6562
66- @nox .session (python = DEFAULT_PYTHON_VERSION )
63+ @nox .session (python = DEFAULT_PYTHON_VERSION , name = "security-python" )
6764def security_python (session : Session ) -> None :
6865 """Run code security checks (Bandit) on Python code."""
6966 session .log ("Installing security dependencies..." )
@@ -76,8 +73,8 @@ def security_python(session: Session) -> None:
7673 session .run ("uv" , "run" , "pip-audit" , "--python" , str (Path (session .python )), external = True )
7774
7875
79- @nox .session (python = PYTHON_VERSIONS )
80- def test_python (session : Session ) -> None :
76+ @nox .session (python = PYTHON_VERSIONS , name = "tests-python" )
77+ def tests_python (session : Session ) -> None :
8178 """Run the Python test suite (pytest with coverage)."""
8279 session .log ("Installing test dependencies..." )
8380 session .run ("uv" , "sync" , "--locked" , "--clean" , "--groups" , "dev" , "test" , external = True )
@@ -97,16 +94,16 @@ def test_python(session: Session) -> None:
9794 )
9895
9996
100- @nox .session (venv = None )
101- def test_rust (session : Session ) -> None :
97+ @nox .session (python = None , name = "tests-rust" )
98+ def tests_rust (session : Session ) -> None :
10299 """Test the project's rust crates."""
103100 crates : list [Path ] = [cargo_toml .parent for cargo_toml in CRATES_FOLDER .glob ("*/Cargo.toml" )]
104101 crate_kwargs : list [str ] = [f"-p { crate .name } " for crate in crates ]
105102 session .run ("cargo" , "test" , "--all-features" , "--no-run" , * crate_kwargs , external = True )
106103 session .run ("cargo" , "test" , "--all-features" , * crate_kwargs , external = True )
107104
108105
109- @nox .session (python = DEFAULT_PYTHON_VERSION )
106+ @nox .session (python = DEFAULT_PYTHON_VERSION , name = "docs-build" )
110107def docs_build (session : Session ) -> None :
111108 """Build the project documentation (Sphinx)."""
112109 session .log ("Installing documentation dependencies..." )
@@ -157,7 +154,7 @@ def build_rust(session: Session) -> None:
157154
158155{% endif % }
159156
160- @nox .session (python = DEFAULT_PYTHON_VERSION )
157+ @nox .session (python = DEFAULT_PYTHON_VERSION , name = "build-python" )
161158def build_python (session : Session ) -> None :
162159 """Build sdist and wheel packages (uv build)."""
163160 session .log ("Installing build dependencies..." )
@@ -171,7 +168,7 @@ def build_python(session: Session) -> None:
171168 session .run ("uv" , "run" , "ls" , "-l" , "dist/" , external = True )
172169
173170
174- @nox .session (python = DEFAULT_PYTHON_VERSION )
171+ @nox .session (python = DEFAULT_PYTHON_VERSION , name = "build-container" )
175172def build_container (session : Session ) -> None :
176173 """Build the Docker container image.
177174
@@ -190,7 +187,6 @@ def build_container(session: Session) -> None:
190187 except nox .command .CommandFailed :
191188 session .log ("Neither Docker nor Podman command found. Please install a container runtime." )
192189 session .skip ("Container runtime not available." )
193- return
194190
195191 current_dir = Path ("." )
196192 session .log (f"Ensuring core dependencies are synced in { current_dir .resolve ()} for build context..." )
@@ -203,7 +199,7 @@ def build_container(session: Session) -> None:
203199 session .log (f"Container image { project_image_name } :latest built locally." )
204200
205201
206- @nox .session (python = DEFAULT_PYTHON_VERSION )
202+ @nox .session (python = DEFAULT_PYTHON_VERSION , name = "publish-python" )
207203def publish_python (session : Session ) -> None :
208204 """Publish sdist and wheel packages to PyPI via uv publish.
209205
@@ -217,7 +213,7 @@ def publish_python(session: Session) -> None:
217213 session .run ("uv" , "publish" , "dist/*" , external = True )
218214
219215
220- @nox .session (python = None )
216+ @nox .session (python = None , name = "publish-rust" )
221217def publish_rust (session : Session ) -> None :
222218 """Publish built crates to crates.io."""
223219 session .log ("Publishing crates to crates.io" )
@@ -239,7 +235,6 @@ def release(session: Session) -> None:
239235 except nox .command .CommandFailed :
240236 session .log ("Git command not found. Commitizen requires Git." )
241237 session .skip ("Git not available." )
242- return
243238
244239 session .log ("Checking Commitizen availability via uvx." )
245240 session .run ("uvx" , "cz" , "--version" , success_codes = [0 ], external = True )
@@ -281,7 +276,6 @@ def tox(session: Session) -> None:
281276 if not tox_ini_path .exists ():
282277 session .log ("tox.ini file not found at %s. Tox requires this file." , str (tox_ini_path ))
283278 session .skip ("tox.ini not present." )
284- return
285279
286280 session .log ("Checking Tox availability via uvx." )
287281 session .run ("uvx" , "tox" , "--version" , success_codes = [0 ], external = True )
@@ -326,7 +320,7 @@ def check(session: Session) -> None:
326320 session .notify ("security_deps" )
327321
328322
329- @nox .session (python = PYTHON_VERSIONS )
323+ @nox .session (python = PYTHON_VERSIONS , name = "full-check" )
330324def full_check (session : Session ) -> None :
331325 """Run all core quality checks and tests."""
332326 session .log (f"Queueing all check and test sessions for py{ session .python } if applicable." )
@@ -359,7 +353,6 @@ def coverage(session: Session) -> None:
359353 else :
360354 session .error (f"Failed to combine coverage data: { e } " )
361355 session .skip ("Could not combine coverage data." )
362- return
363356
364357 session .log ("Generating HTML coverage report." )
365358 coverage_html_dir = Path ("coverage-html" )
@@ -369,4 +362,3 @@ def coverage(session: Session) -> None:
369362 session .run ("uv" , "run" , "coverage" , "report" , external = True )
370363
371364 session .log (f"Coverage reports generated in ./{ str (coverage_html_dir )} and terminal." )
372-
0 commit comments