Commit 402ca3b9 by Arun Babu Neelicattu Committed by Randy Döring

factory: cleanup creation from package

This change ensures that generated toml file from packages contain all
relevant metadata and handles groups correct.
parent f645ab96
......@@ -116,14 +116,16 @@ You can specify a package in the following forms:
break
root_package.python_versions = ".".join( # type: ignore[union-attr]
assert root_package is not None
root_package.python_versions = ".".join(
str(v) for v in system_env.version_info[:3]
)
# We create a `pyproject.toml` file based on all the information
# we have about the current environment.
if not env_dir.joinpath("pyproject.toml").exists():
Factory.create_pyproject_from_package(
root_package, # type: ignore[arg-type]
root_package,
env_dir,
)
......
from __future__ import annotations
import contextlib
import logging
from typing import TYPE_CHECKING
......@@ -22,10 +23,17 @@ from poetry.plugins.plugin_manager import PluginManager
from poetry.poetry import Poetry
try:
from poetry.core.packages.dependency_group import MAIN_GROUP
except ImportError:
MAIN_GROUP = "default"
if TYPE_CHECKING:
from pathlib import Path
from cleo.io.io import IO
from poetry.core.packages.package import Package
from poetry.repositories.legacy_repository import LegacyRepository
......@@ -206,23 +214,73 @@ class Factory(BaseFactory):
)
@classmethod
def create_pyproject_from_package(cls, package: ProjectPackage, path: Path) -> None:
def create_pyproject_from_package(
cls, package: Package, path: Path | None = None
) -> TOMLDocument:
import tomlkit
from poetry.layouts.layout import POETRY_DEFAULT
pyproject: dict[str, Any] = tomlkit.document()
tool_table = tomlkit.table()
tool_table._is_super_table = True
pyproject["tool"] = tool_table
pyproject: dict[str, Any] = tomlkit.loads(POETRY_DEFAULT)
content = pyproject["tool"]["poetry"]
content: dict[str, Any] = tomlkit.table()
pyproject["tool"]["poetry"] = content
content["name"] = package.name
content["version"] = package.version.text
content["description"] = package.description
content["authors"] = package.authors
content["license"] = package.license.id if package.license else ""
if package.classifiers:
content["classifiers"] = package.classifiers
for key, attr in {
("documentation", "documentation_url"),
("repository", "repository_url"),
("homepage", "homepage"),
("maintainers", "maintainers"),
("keywords", "keywords"),
}:
value = getattr(package, attr, None)
if value:
content[key] = value
readmes = []
for readme in package.readmes:
readme_posix_path = readme.as_posix()
with contextlib.suppress(ValueError):
if package.root_dir:
readme_posix_path = readme.relative_to(package.root_dir).as_posix()
readmes.append(readme_posix_path)
if readmes:
content["readme"] = readmes
optional_dependencies = set()
extras_section = None
dependency_section = content["dependencies"]
if package.extras:
extras_section = tomlkit.table()
for extra in package.extras:
_dependencies = []
for dependency in package.extras[extra]:
_dependencies.append(dependency.name)
optional_dependencies.add(dependency.name)
extras_section[extra] = _dependencies
optional_dependencies = set(optional_dependencies)
dependency_section = content["dependencies"] = tomlkit.table()
dependency_section["python"] = package.python_versions
for dep in package.requires:
for dep in package.all_requires:
constraint: dict[str, Any] = tomlkit.inline_table()
if dep.is_vcs():
dep = cast(VCSDependency, dep)
......@@ -241,12 +299,39 @@ class Factory(BaseFactory):
if dep.extras:
constraint["extras"] = sorted(dep.extras)
if dep.name in optional_dependencies:
constraint["optional"] = True
if len(constraint) == 1 and "version" in constraint:
constraint = constraint["version"]
for group in dep.groups:
if group == MAIN_GROUP:
dependency_section[dep.name] = constraint
else:
if "group" not in content:
_table = tomlkit.table()
_table._is_super_table = True
content["group"] = _table
if group not in content["group"]:
_table = tomlkit.table()
_table._is_super_table = True
content["group"][group] = _table
assert isinstance(pyproject, TOMLDocument)
if "dependencies" not in content["group"][group]:
content["group"][group]["dependencies"] = tomlkit.table()
content["group"][group]["dependencies"][dep.name] = constraint
if extras_section:
content["extras"] = extras_section
pyproject.add(tomlkit.nl()) # type: ignore[attr-defined]
if path:
path.joinpath("pyproject.toml").write_text(
pyproject.as_string(), encoding="utf-8"
pyproject.as_string(), encoding="utf-8" # type: ignore[attr-defined]
)
return cast(TOMLDocument, pyproject)
......@@ -7,7 +7,7 @@ authors = [
]
license = "MIT"
readme = "README.rst"
readme = ["README.rst"]
homepage = "https://python-poetry.org"
repository = "https://github.com/python-poetry/poetry"
......@@ -31,5 +31,5 @@ fox = "fuz.foo:bar.baz"
[build-system]
requires = ["poetry-core>=1.0.2"]
requires = ["poetry-core>=1.1.0a7"]
build-backend = "poetry.core.masonry.api"
......@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING
import pytest
from deepdiff import DeepDiff
from entrypoints import EntryPoint
from poetry.core.semver.helpers import parse_constraint
from poetry.core.toml.file import TOMLFile
......@@ -41,10 +42,12 @@ def test_create_poetry():
assert package.description == "Some description."
assert package.authors == ["Sébastien Eustace <sebastien@eustace.io>"]
assert package.license.id == "MIT"
for readme in package.readmes:
assert (
package.readme.relative_to(fixtures_dir).as_posix()
== "sample_project/README.rst"
readme.relative_to(fixtures_dir).as_posix() == "sample_project/README.rst"
)
assert package.homepage == "https://python-poetry.org"
assert package.repository_url == "https://github.com/python-poetry/poetry"
assert package.keywords == ["packaging", "dependency", "poetry"]
......@@ -133,6 +136,34 @@ def test_create_poetry():
]
@pytest.mark.parametrize(
("project",),
[
("simple_project",),
("project_with_extras",),
],
)
def test_create_pyproject_from_package(project: str):
poetry = Factory().create_poetry(fixtures_dir / project)
package = poetry.package
pyproject = Factory.create_pyproject_from_package(package)
result = pyproject["tool"]["poetry"]
expected = poetry.pyproject.poetry_config
# packages do not support this at present
expected.pop("scripts", None)
# remove any empty sections
sections = list(expected.keys())
for section in sections:
if not expected[section]:
expected.pop(section)
assert not DeepDiff(expected, result)
def test_create_poetry_with_packages_and_includes():
poetry = Factory().create_poetry(fixtures_dir / "with-include")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment