From 268d2939681091305ac95f3619026da29563573e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Palancher?= Date: Thu, 2 Jul 2026 11:14:31 +0200 Subject: [PATCH 1/3] fix(build): authors optional in setup converter Make authors optional in setup converter. Omit author and author_email when not specified. --- CHANGELOG.md | 7 ++++++- src/build/rfl/build/scripts/setup | 9 +++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a88eec..25c4e13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,10 +10,15 @@ and this project adheres to ### Added -- build:: +- build: - Support setuptools.packages.find.where directive in setup converter. - Support setuptools.data-files directives in setup converter. +### Changed + +- build: Make `authors` optional in setup converter (omit `author` and + `author_email` when not specified). + ## [1.8.0] - 2026-05-22 ### Added diff --git a/src/build/rfl/build/scripts/setup b/src/build/rfl/build/scripts/setup index 57181bc..7dfaf39 100644 --- a/src/build/rfl/build/scripts/setup +++ b/src/build/rfl/build/scripts/setup @@ -166,11 +166,16 @@ elif "file" in pyproject["project"]["license"]: if "urls" in pyproject["project"]: kwargs["url"] = pyproject["project"]["urls"]["Homepage"] +authors = pyproject["project"].get("authors") or [] +if authors: + if "name" in authors[0]: + kwargs["author"] = authors[0]["name"] + if "email" in authors[0]: + kwargs["author_email"] = authors[0]["email"] + setup( name=pyproject["project"]["name"], version=pyproject["project"]["version"], - author=pyproject["project"]["authors"][0]["name"], - author_email=pyproject["project"]["authors"][0]["email"], platforms=["GNU/Linux"], **kwargs, ) From e0ccd67283eb0e8bb549d0249a90f91623b52490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Palancher?= Date: Thu, 2 Jul 2026 11:15:11 +0200 Subject: [PATCH 2/3] tests(build): cover opt author in setup converter --- src/build/rfl/tests/test_setup.py | 72 +++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 4 deletions(-) diff --git a/src/build/rfl/tests/test_setup.py b/src/build/rfl/tests/test_setup.py index 8d1f1d9..471ff2d 100644 --- a/src/build/rfl/tests/test_setup.py +++ b/src/build/rfl/tests/test_setup.py @@ -29,18 +29,27 @@ def _run_setup_script(): exec(compile(code, str(path), "exec"), {"__name__": "__main__"}) -def _minimal_pyproject(extra="", license_line='license = "LGPL-3.0-or-later"'): +def _minimal_pyproject( + extra="", + license_line='license = "LGPL-3.0-or-later"', + authors_block=textwrap.dedent( + """\ + authors = [ + {name = "Test Author", email = "test@example.com"}, + ] + """ + ), +): content = textwrap.dedent( f"""\ [project] name = "test-pkg" version = "1.0.0" {license_line} - authors = [ - {{name = "Test Author", email = "test@example.com"}}, - ] """ ) + if authors_block: + content += textwrap.dedent(authors_block) if extra: content += textwrap.dedent(extra) return content @@ -93,6 +102,61 @@ def test_minimal_project_metadata(self, mock_setup, mock_exit): platforms=["GNU/Linux"], ) + @patch("sys.exit") + @patch("setuptools.setup") + def test_no_authors(self, mock_setup, mock_exit): + with _project_dir(_minimal_pyproject(authors_block="")): + _run_setup_script() + + mock_exit.assert_not_called() + mock_setup.assert_called_once_with( + name="test-pkg", + version="1.0.0", + platforms=["GNU/Linux"], + ) + + @patch("sys.exit") + @patch("setuptools.setup") + def test_author_name_only(self, mock_setup, mock_exit): + authors_block = textwrap.dedent( + """\ + authors = [ + {name = "Test Author"}, + ] + """ + ) + with _project_dir(_minimal_pyproject(authors_block=authors_block)): + _run_setup_script() + + mock_exit.assert_not_called() + mock_setup.assert_called_once_with( + name="test-pkg", + version="1.0.0", + author="Test Author", + platforms=["GNU/Linux"], + ) + + @patch("sys.exit") + @patch("setuptools.setup") + def test_author_email_only(self, mock_setup, mock_exit): + authors_block = textwrap.dedent( + """\ + authors = [ + {email = "test@example.com"}, + ] + """ + ) + with _project_dir(_minimal_pyproject(authors_block=authors_block)): + _run_setup_script() + + mock_exit.assert_not_called() + mock_setup.assert_called_once_with( + name="test-pkg", + version="1.0.0", + author_email="test@example.com", + platforms=["GNU/Linux"], + ) + @patch("sys.exit") @patch("setuptools.setup") def test_console_scripts_entry_points(self, mock_setup, mock_exit): From 7d214a3434a0672053bb840108ffc15973dbc09c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Palancher?= Date: Thu, 2 Jul 2026 11:15:38 +0200 Subject: [PATCH 3/3] docs(build): mention optional author --- src/build/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/build/README.md b/src/build/README.md index 0743694..b5afe3f 100644 --- a/src/build/README.md +++ b/src/build/README.md @@ -38,7 +38,7 @@ arguments: | Source | `setup()` argument | |--------|-------------------| | `[project]` `name`, `version` | `name`, `version` | -| `[project]` `authors[0]` | `author`, `author_email` | +| `[project]` `authors[0]` (optional) | `author`, `author_email` (each only when present) | | `[project]` `scripts` | `entry_points["console_scripts"]` | | `[project]` `dependencies` | `install_requires` | | `[project]` `optional-dependencies` | `extras_require` | @@ -116,7 +116,9 @@ The converter is intentionally minimal. It does **not** map many common - `[tool.setuptools]` `package-dir` as an explicit pyproject key (only inferred from `where`) -Only the first `[project]` author entry is used. +When `[project].authors` is present, only the first entry is used; `name` and +`email` are each passed to `setup()` only when specified. When `authors` is absent +or empty, no author metadata is passed. The script must be executed from the directory that contains `pyproject.toml`. It requires `tomllib` (Python 3.11+) or the `tomli` package on older Python versions.