From cdf31ab8225b94f2578e9463c0f697e5379deb57 Mon Sep 17 00:00:00 2001 From: changw98ic <59154235+changw98ic@users.noreply.github.com> Date: Sun, 19 Apr 2026 14:44:11 +0800 Subject: [PATCH 1/6] Support multiple --author flags in poetry init/new --- src/poetry/console/commands/init.py | 43 +++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/src/poetry/console/commands/init.py b/src/poetry/console/commands/init.py index 48ea6e206ed..15341ae9459 100644 --- a/src/poetry/console/commands/init.py +++ b/src/poetry/console/commands/init.py @@ -39,7 +39,13 @@ class InitCommand(Command): options: ClassVar[list[Option]] = [ option("name", None, "Name of the package.", flag=False), option("description", None, "Description of the package.", flag=False), - option("author", None, "Author name of the package.", flag=False), + option( + "author", + None, + "Author name of the package.", + flag=False, + multiple=True, + ), option("python", None, "Compatible Python versions.", flag=False), option( "dependency", @@ -150,19 +156,38 @@ def _init_pyproject( author = self.option("author") if not author and vcs_config.get("user.name"): - author = vcs_config["user.name"] + author = [vcs_config["user.name"]] author_email = vcs_config.get("user.email") if author_email: - author += f" <{author_email}>" + author[0] += f" <{author_email}>" + elif not author: + author = [] + + if is_interactive and not author: + default_author = "" + if vcs_config.get("user.name"): + default_author = vcs_config["user.name"] + author_email = vcs_config.get("user.email") + if author_email: + default_author += f" <{author_email}>" - if is_interactive: question = self.create_question( - f"Author [{author}, n to skip]: ", default=author + f"Author [{default_author}, n to skip]: ", + default=default_author, + ) + question.set_validator( + lambda v: self._validate_author(v, default_author) ) - question.set_validator(lambda v: self._validate_author(v, author)) - author = self.ask(question) + first_author = self.ask(question) + if first_author: + author.append(first_author) - authors = [author] if author else [] + # Validate all authors + authors = [] + for a in author: + validated = self._validate_author(a, a) + if validated: + authors.append(validated) license_name = self.option("license") if not license_name and is_interactive: @@ -237,7 +262,7 @@ def _init_pyproject( name, version, description=description, - author=authors[0] if authors else None, + authors=authors, readme_format=readme_format, license=license_name, python=python, From da84f00b757216a2f0449c19e7666f63e930a2c8 Mon Sep 17 00:00:00 2001 From: changw98ic <59154235+changw98ic@users.noreply.github.com> Date: Sun, 19 Apr 2026 14:44:12 +0800 Subject: [PATCH 2/6] Support multiple --author flags in poetry init/new --- src/poetry/layouts/layout.py | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/poetry/layouts/layout.py b/src/poetry/layouts/layout.py index 768b3737191..e490f242a98 100644 --- a/src/poetry/layouts/layout.py +++ b/src/poetry/layouts/layout.py @@ -66,6 +66,7 @@ def __init__( description: str = "", readme_format: str = "md", author: str | None = None, + authors: list[str] | None = None, license: str | None = None, python: str | None = None, dependencies: Mapping[str, str | Mapping[str, Any]] | None = None, @@ -86,10 +87,12 @@ def __init__( self._dependencies = dependencies or {} self._dev_dependencies = dev_dependencies or {} - if not author: - author = "Your Name " - - self._author = author + if authors: + self._authors = authors + elif author: + self._authors = [author] + else: + self._authors = ["Your Name "] @property def basedir(self) -> Path: @@ -147,15 +150,16 @@ def generate_project_content( project_content["name"] = self._project project_content["version"] = self._version project_content["description"] = self._description - m = AUTHOR_REGEX.match(self._author) - if m is None: - # This should not happen because author has been validated before. - raise ValueError(f"Invalid author: {self._author}") - else: - author = {"name": m.group("name")} - if email := m.group("email"): - author["email"] = email - project_content["authors"].append(author) + for author_str in self._authors: + m = AUTHOR_REGEX.match(author_str) + if m is None: + # This should not happen because author has been validated before. + raise ValueError(f"Invalid author: {author_str}") + else: + author = {"name": m.group("name")} + if email := m.group("email"): + author["email"] = email + project_content["authors"].append(author) if self._license: project_content["license"] = self._license From 41c6c98c591075a4188d81a3979d8836597eaaf2 Mon Sep 17 00:00:00 2001 From: changw98ic <59154235+changw98ic@users.noreply.github.com> Date: Sun, 19 Apr 2026 15:12:08 +0800 Subject: [PATCH 3/6] Add tests for multiple --author support --- tests/console/commands/test_init.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/console/commands/test_init.py b/tests/console/commands/test_init.py index d4904ecd4af..668315ed5bb 100644 --- a/tests/console/commands/test_init.py +++ b/tests/console/commands/test_init.py @@ -1215,3 +1215,29 @@ def test_init_does_not_add_readme_key_when_readme_missing( # Assert pyproject = (tmp_path / "pyproject.toml").read_text(encoding="utf-8") assert "readme =" not in pyproject + + +def test_multiple_authors_via_cli(tester: CommandTester, source_dir: Path) -> None: + """Test that multiple --author flags are supported in non-interactive mode.""" + tester.execute( + "--name my-package " + "--author 'Alice ' " + "--author 'Bob '", + interactive=False, + ) + + pyproject = (source_dir / "pyproject.toml").read_text(encoding="utf-8") + assert '{name = "Alice",email = "alice@example.com"}' in pyproject + assert '{name = "Bob",email = "bob@example.com"}' in pyproject + + +def test_single_author_via_cli_unchanged(tester: CommandTester, source_dir: Path) -> None: + """Test that single --author behavior is unchanged.""" + tester.execute( + "--name my-package " + "--author 'Alice '", + interactive=False, + ) + + pyproject = (source_dir / "pyproject.toml").read_text(encoding="utf-8") + assert '{name = "Alice",email = "alice@example.com"}' in pyproject From 1dd728634ef29a6162279031cda9af55d7e3af20 Mon Sep 17 00:00:00 2001 From: changw98ic <59154235+changw98ic@users.noreply.github.com> Date: Sun, 19 Apr 2026 15:43:53 +0800 Subject: [PATCH 4/6] Fix: preserve interactive author prompt behavior --- src/poetry/console/commands/init.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/poetry/console/commands/init.py b/src/poetry/console/commands/init.py index 15341ae9459..7135c087297 100644 --- a/src/poetry/console/commands/init.py +++ b/src/poetry/console/commands/init.py @@ -163,14 +163,9 @@ def _init_pyproject( elif not author: author = [] - if is_interactive and not author: - default_author = "" - if vcs_config.get("user.name"): - default_author = vcs_config["user.name"] - author_email = vcs_config.get("user.email") - if author_email: - default_author += f" <{author_email}>" - + if is_interactive: + # Build the default author string for the prompt + default_author = author[0] if author else "" question = self.create_question( f"Author [{default_author}, n to skip]: ", default=default_author, @@ -180,9 +175,11 @@ def _init_pyproject( ) first_author = self.ask(question) if first_author: - author.append(first_author) + author = [first_author] + else: + author = [] - # Validate all authors + # Validate all authors from CLI authors = [] for a in author: validated = self._validate_author(a, a) From 47dc4d9ceff9d7405b96915c36a6913b1a012e3a Mon Sep 17 00:00:00 2001 From: changw98ic <59154235+changw98ic@users.noreply.github.com> Date: Sun, 19 Apr 2026 16:28:07 +0800 Subject: [PATCH 5/6] Add interactive multi-author prompt + TODO on author param deprecation --- src/poetry/console/commands/init.py | 67 +++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/src/poetry/console/commands/init.py b/src/poetry/console/commands/init.py index 7135c087297..5410ca557ef 100644 --- a/src/poetry/console/commands/init.py +++ b/src/poetry/console/commands/init.py @@ -155,6 +155,7 @@ def _init_pyproject( description = self.ask(self.create_question("Description []: ", default="")) author = self.option("author") + author_from_cli = bool(author) if not author and vcs_config.get("user.name"): author = [vcs_config["user.name"]] author_email = vcs_config.get("user.email") @@ -164,20 +165,60 @@ def _init_pyproject( author = [] if is_interactive: - # Build the default author string for the prompt - default_author = author[0] if author else "" - question = self.create_question( - f"Author [{default_author}, n to skip]: ", - default=default_author, - ) - question.set_validator( - lambda v: self._validate_author(v, default_author) - ) - first_author = self.ask(question) - if first_author: - author = [first_author] + # When --author was provided via CLI, use it as default but still prompt + # so the user can confirm or override. Do not ask for additional authors + # since the user already expressed their intent via the CLI flag. + if author_from_cli: + default_author = author[0] if author else "" + question = self.create_question( + f"Author [{default_author}, n to skip]: ", + default=default_author, + ) + question.set_validator( + lambda v: self._validate_author(v, default_author) + ) + first_author = self.ask(question) + if first_author: + author = [first_author] + else: + author = [] else: - author = [] + # No --author from CLI: interactive flow allows multiple authors + default_author = author[0] if author else "" + question = self.create_question( + f"Author [{default_author}, n to skip]: ", + default=default_author, + ) + question.set_validator( + lambda v: self._validate_author(v, default_author) + ) + first_author = self.ask(question) + if first_author: + author = [first_author] + else: + author = [] + + # Allow additional authors interactively + while first_author: + question = self.create_question( + "Add another author? [n to skip]: ", + default="n", + ) + another = self.ask(question) + if not another or another.lower() == "n": + break + question = self.create_question( + "Author [, n to skip]: ", + default="", + ) + question.set_validator( + lambda v: self._validate_author(v, "") + ) + additional = self.ask(question) + if additional: + author.append(additional) + else: + break # Validate all authors from CLI authors = [] From 83ed55da02308ee77b56710ba5bfc9fbc74c4f58 Mon Sep 17 00:00:00 2001 From: changw98ic <59154235+changw98ic@users.noreply.github.com> Date: Sun, 19 Apr 2026 16:28:10 +0800 Subject: [PATCH 6/6] Add interactive multi-author prompt + TODO on author param deprecation --- src/poetry/layouts/layout.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/poetry/layouts/layout.py b/src/poetry/layouts/layout.py index e490f242a98..bf4e4d1be4a 100644 --- a/src/poetry/layouts/layout.py +++ b/src/poetry/layouts/layout.py @@ -66,6 +66,7 @@ def __init__( description: str = "", readme_format: str = "md", author: str | None = None, + # TODO: Deprecate `author` in a future major version; use `authors` only. authors: list[str] | None = None, license: str | None = None, python: str | None = None,