From aa5b5599321310f3ecb73eb9e838764758aab96d Mon Sep 17 00:00:00 2001 From: Simon Rainerson Date: Wed, 30 Oct 2024 13:49:45 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=20=F0=9F=90=8D=20Change=20python=20de?= =?UTF-8?q?fault=20to=20pyproject.toml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The days of setuptools are numbered! Switch default component to use pyproject.toml, it is currently the least deprecated way of building python packages. Also sneak in some nifty features like adding a `run` command for clients and services. And add a corresponding entry point to their package. Also made the generated code pass `ruff`, it uses the `--unsafe-fixes` to add period at the end of docstrings if missing. Since it only runs on the templated code we know that it won't do anything else. --- CHANGELOG.md | 7 +++++++ .../component-template/@mainPackage@/main.py | 4 ++-- python/component-template/pyproject.toml | 18 +++++++++++++++++ python/component-template/setup.py | 13 ------------ python/component-template/tests/test_main.py | 5 +++-- python/main.py.in | 3 +++ python/package.nix | 20 ++++++++++++++++--- 7 files changed, 50 insertions(+), 20 deletions(-) create mode 100644 python/component-template/pyproject.toml delete mode 100644 python/component-template/setup.py create mode 100644 python/main.py.in diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b8a2fc..134a8cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added +- Python now generates a `run` command and cli entry point for clients and services. + +### Changed +- Python now uses `pyproject` instead of `setuptools` by default. Template for targetSetup + has been updated accordingly. It also conforms to `ruff`s checks and formatting by default. + ### Fixed - Python's config merger now handles mypy overrides targeting multiple packages. diff --git a/python/component-template/@mainPackage@/main.py b/python/component-template/@mainPackage@/main.py index e16297c..265ed8b 100644 --- a/python/component-template/@mainPackage@/main.py +++ b/python/component-template/@mainPackage@/main.py @@ -1,6 +1,6 @@ -""" @desc@ """ +"""@desc@""" def main() -> None: - """ main function of @mainPackage@ """ + """Main function of @mainPackage@.""" raise NotImplementedError diff --git a/python/component-template/pyproject.toml b/python/component-template/pyproject.toml new file mode 100644 index 0000000..b66c1a5 --- /dev/null +++ b/python/component-template/pyproject.toml @@ -0,0 +1,18 @@ +[build-system] +requires = ["setuptools"] + +[project] +name = "@pname@" +version = "@version@" +description = "@desc@" +authors = [{name = "@author@", email = "@email@"}] + +[setuptools.packages.find] +exclude = ["tests*"] + +[urls] +Homepage = "@url@" + +[project.scripts] +@entryPoint@ + diff --git a/python/component-template/setup.py b/python/component-template/setup.py deleted file mode 100644 index 6b06b41..0000000 --- a/python/component-template/setup.py +++ /dev/null @@ -1,13 +0,0 @@ -""" Package setup for the component @pname@ """ -from setuptools import find_packages, setup - -setup( - name="@pname@", - version="@version@", - url="@url@", - author="@author@", - author_email="@email@", - description="@desc@", - packages=find_packages(exclude=["tests"]), - entry_points=@entryPoint@, -) diff --git a/python/component-template/tests/test_main.py b/python/component-template/tests/test_main.py index eaf4487..a8e4964 100644 --- a/python/component-template/tests/test_main.py +++ b/python/component-template/tests/test_main.py @@ -1,6 +1,7 @@ -""" Tests for @mainPackage@ in @pname@ """ +"""Tests for @mainPackage@ in @pname@.""" import @mainPackage@.main + def test_main() -> None: - """ Tests for the main function """ + """Tests for the main function.""" @mainPackage@.main.main() diff --git a/python/main.py.in b/python/main.py.in new file mode 100644 index 0000000..76c13b7 --- /dev/null +++ b/python/main.py.in @@ -0,0 +1,3 @@ + +if __name__ == "__main__": + main() diff --git a/python/package.nix b/python/package.nix index 8de66f6..7c08a23 100644 --- a/python/package.nix +++ b/python/package.nix @@ -71,7 +71,7 @@ let inherit version; pname = name; mainPackage = lib.toLower (builtins.replaceStrings [ "-" " " ] [ "_" "_" ] name); - entryPoint = if setuptoolsLibrary then "{}" else "{\\\"console_scripts\\\": [\\\"${name}=${mainPackage}.main:main\\\"]}"; + entryPoint = if setuptoolsLibrary then "" else "${name}=\\\"${mainPackage}.main:main\\\""; } // args.targetSetup.variables or { }; variableQueries = { desc = "✍️ Write a short description for your component:"; @@ -79,13 +79,18 @@ let email = "📧 Enter author email:"; url = "🏄 Enter author website url:"; } // args.targetSetup.variableQueries or { }; - initCommands = "black ."; + initCommands = '' + ${if ! setuptoolsLibrary then "cat ${./main.py.in} >>$mainPackage/main.py" else ""} + ruff format . + ruff check --fix --unsafe-fixes . + ''; }); pythonPackageArgs = attrs // { inherit version preBuild doStandardTests pythonVersion propagatedBuildInputs; src = if lib.isStorePath src then src else filteredSrc; pname = name; + format = attrs.format or "pyproject"; # Don't install dependencies with pip, let nix handle that preInstall = '' @@ -170,7 +175,16 @@ let Show the config Nedryland has generated for a linter, one of: black, coverage, flake8, isort, mypy, pylint, pytest''; }; - } // attrs.shellCommands or { }); + } // ( + lib.optionalAttrs + (! setuptoolsLibrary) + { + run = { + script = ''python -m ${name}.main "$@"''; + description = "Run the main module."; + }; + }) + // attrs.shellCommands or { }); }; in pythonPkgs.buildPythonPackage pythonPackageArgs