diff --git a/src/poetry/core/factory.py b/src/poetry/core/factory.py index 958574c6a..f53506e22 100644 --- a/src/poetry/core/factory.py +++ b/src/poetry/core/factory.py @@ -184,9 +184,10 @@ def _configure_package_metadata( package.requires_python = project.get("requires-python", "*") package.keywords = project.get("keywords") or tool_poetry.get("keywords", []) - package.classifiers = project.get("classifiers") or tool_poetry.get( - "classifiers", [] - ) + package.classifiers = ( + static_classifiers := project.get("classifiers") + ) or tool_poetry.get("classifiers", []) + package.dynamic_classifiers = not static_classifiers if urls := project.get("urls"): package.homepage = urls.get("homepage") or urls.get("Homepage") diff --git a/src/poetry/core/packages/project_package.py b/src/poetry/core/packages/project_package.py index 311c65dae..62e2d9199 100644 --- a/src/poetry/core/packages/project_package.py +++ b/src/poetry/core/packages/project_package.py @@ -45,6 +45,7 @@ def __init__( self.exclude: Sequence[Mapping[str, Any]] = [] self.custom_urls: Mapping[str, str] = {} self._requires_python: str = "*" + self.dynamic_classifiers = True if self._python_versions == "*": self._python_constraint = parse_constraint("~2.7 || >=3.4") @@ -111,6 +112,13 @@ def version(self) -> Version: def version(self, value: str | Version) -> None: self._set_version(value) + @property + def all_classifiers(self) -> list[str]: + if self.dynamic_classifiers: + return super().all_classifiers + + return list(self.classifiers) + @property def urls(self) -> dict[str, str]: urls = super().urls diff --git a/tests/test_factory.py b/tests/test_factory.py index fcbd0e65f..0aa8a7717 100644 --- a/tests/test_factory.py +++ b/tests/test_factory.py @@ -279,19 +279,22 @@ def test_create_poetry(new_format: str) -> None: "Topic :: Software Development :: Libraries :: Python Modules", ] - assert package.all_classifiers == [ - "License :: OSI Approved :: MIT License", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Topic :: Software Development :: Build Tools", - "Topic :: Software Development :: Libraries :: Python Modules", - ] + if new_format: + assert package.all_classifiers == package.classifiers + else: + assert package.all_classifiers == [ + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Software Development :: Build Tools", + "Topic :: Software Development :: Libraries :: Python Modules", + ] def test_create_poetry_with_dependencies_with_subdirectory() -> None: @@ -429,6 +432,63 @@ def test_create_poetry_python_version_not_compatible(tmp_path: Path) -> None: assert "not a subset" in str(e.value) +@pytest.mark.parametrize( + ("content", "expected"), + [ + ( # static + """\ +[project] +name = "foo" +version = "1" +requires-python = "3.10" +classifiers = ["License :: OSI Approved :: MIT License"] +""", + ["License :: OSI Approved :: MIT License"], + ), + ( # dynamic + """\ +[project] +name = "foo" +version = "1" +requires-python = "3.10" +dynamic = [ "classifiers" ] + +[tool.poetry] +classifiers = ["License :: OSI Approved :: MIT License"] +""", + [ + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + ], + ), + ( # legacy + """\ +[tool.poetry] +name = "foo" +version = "1" +classifiers = ["License :: OSI Approved :: MIT License"] + +[tool.poetry.dependencies] +python = "~3.10" +""", + [ + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + ], + ), + ], +) +def test_create_poetry_classifiers( + content: str, expected: list[str], tmp_path: Path +) -> None: + (tmp_path / "pyproject.toml").write_text(content) + poetry = Factory().create_poetry(tmp_path) + + assert poetry.package.all_classifiers == expected + + def test_validate() -> None: complete = fixtures_dir / "complete.toml" with complete.open("rb") as f: