Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wip: poc pep 735 #823

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 39 additions & 11 deletions src/poetry/core/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,13 +134,18 @@ def configure_package(
) -> None:
project = pyproject.data.get("project", {})
tool_poetry = pyproject.poetry_config
dependency_groups = pyproject.data.get("dependency-groups", {})

package.root_dir = root

cls._configure_package_metadata(package, project, tool_poetry, root)
cls._configure_entry_points(package, project, tool_poetry)
cls._configure_package_dependencies(
package, project, tool_poetry, with_groups=with_groups
package,
project,
tool_poetry,
dependency_groups=dependency_groups,
with_groups=with_groups,
)
cls._configure_package_poetry_specifics(package, tool_poetry)

Expand Down Expand Up @@ -289,6 +294,7 @@ def _configure_package_dependencies(
package: ProjectPackage,
project: dict[str, Any],
tool_poetry: dict[str, Any],
dependency_groups: dict[str, list[str]],
with_groups: bool = True,
) -> None:
from poetry.core.packages.dependency import Dependency
Expand Down Expand Up @@ -339,16 +345,38 @@ def _configure_package_dependencies(
dependencies=tool_poetry["dependencies"],
)

if with_groups and "group" in tool_poetry:
for group_name, group_config in tool_poetry["group"].items():
group = DependencyGroup(
group_name, optional=group_config.get("optional", False)
)
cls._add_package_group_dependencies(
package=package,
group=group,
dependencies=group_config["dependencies"],
)
if with_groups:
if "group" in tool_poetry:
for group_name, group_config in tool_poetry["group"].items():
group = DependencyGroup(
group_name, optional=group_config.get("optional", False)
)
package.add_dependency_group(group)

if dependency_groups:
for group_name, dependencies in dependency_groups.items():
if package.has_dependency_group(group_name):
group = package.dependency_group(group_name)
else:
group = DependencyGroup(group_name)
package.add_dependency_group(group)

for constraint in dependencies:
dep = Dependency.create_from_pep_508(
constraint,
relative_to=package.root_dir,
groups=[group_name],
)
group.add_dependency(dep)

if "group" in tool_poetry:
for group_name, group_config in tool_poetry["group"].items():
if "dependencies" in group_config:
cls._add_package_group_dependencies(
package=package,
group=group_name,
dependencies=group_config["dependencies"],
)

if with_groups and "dev-dependencies" in tool_poetry:
cls._add_package_group_dependencies(
Expand Down
3 changes: 0 additions & 3 deletions src/poetry/core/json/schemas/poetry-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,6 @@
"^[a-zA-Z-_.0-9]+$": {
"type": "object",
"description": "This represents a single dependency group",
"required": [
"dependencies"
],
"properties": {
"optional": {
"type": "boolean",
Expand Down
24 changes: 18 additions & 6 deletions src/poetry/core/packages/dependency.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,10 @@ def with_constraint(self: T, constraint: str | VersionConstraint) -> T:

@classmethod
def create_from_pep_508(
cls, name: str, relative_to: Path | None = None
cls,
name: str,
relative_to: Path | None = None,
groups: Iterable[str] | None = None,
) -> Dependency:
"""
Resolve a PEP-508 requirement string to a `Dependency` instance. If a
Expand Down Expand Up @@ -413,17 +416,23 @@ def create_from_pep_508(
rev=url.rev,
directory=url.subdirectory,
extras=req.extras,
groups=groups,
)
elif link.scheme == "git":
dep = VCSDependency(
name, "git", link.url_without_fragment, extras=req.extras
name,
"git",
link.url_without_fragment,
extras=req.extras,
groups=groups,
)
elif link.scheme in ("http", "https"):
dep = URLDependency(
name,
link.url_without_fragment,
directory=link.subdirectory_fragment,
extras=req.extras,
groups=groups,
)
elif is_file_uri:
# handle RFC 8089 references
Expand All @@ -434,6 +443,7 @@ def create_from_pep_508(
base=relative_to,
subdirectory=link.subdirectory_fragment,
extras=req.extras,
groups=groups,
)
else:
with suppress(ValueError):
Expand All @@ -443,17 +453,18 @@ def create_from_pep_508(
path=Path(req.url),
base=relative_to,
extras=req.extras,
groups=groups,
)

if dep is None:
dep = Dependency(name, version or "*", extras=req.extras)
dep = Dependency(name, version or "*", extras=req.extras, groups=groups)

if version:
dep._constraint = parse_constraint(version)
else:
constraint: VersionConstraint | str
constraint = req.constraint if req.pretty_constraint else "*"
dep = Dependency(name, constraint, extras=req.extras)
dep = Dependency(name, constraint, extras=req.extras, groups=groups)

if req.marker:
dep.marker = req.marker
Expand Down Expand Up @@ -496,6 +507,7 @@ def _make_file_or_dir_dep(
base: Path | None = None,
subdirectory: str | None = None,
extras: Iterable[str] | None = None,
groups: Iterable[str] | None = None,
) -> FileDependency | DirectoryDependency | None:
"""
Helper function to create a file or directoru dependency with the given arguments.
Expand All @@ -520,10 +532,10 @@ def _make_file_or_dir_dep(

if is_file:
return FileDependency(
name, path, base=base, directory=subdirectory, extras=extras
name, path, base=base, directory=subdirectory, extras=extras, groups=groups
)

if subdirectory:
path = path / subdirectory

return DirectoryDependency(name, path, base=base, extras=extras)
return DirectoryDependency(name, path, base=base, extras=extras, groups=groups)
2 changes: 2 additions & 0 deletions tests/fixtures/sample_project_with_groups_new/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
My Package
==========
69 changes: 69 additions & 0 deletions tests/fixtures/sample_project_with_groups_new/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
[project]
name = "my-package"
version = "1.2.3"
description = "Some description."
readme = "README.rst"
requires-python = ">=3.6"
license = { text = "MIT" }
keywords = ["packaging", "dependency", "poetry"]
authors = [
{ name = "Sébastien Eustace", email = "[email protected]" }
]
maintainers = [
{ name = "Sébastien Eustace", email = "[email protected]" }
]

classifiers = [
"Topic :: Software Development :: Build Tools",
"Topic :: Software Development :: Libraries :: Python Modules"
]

# Requirements
dependencies = [
"cleo ~=0.6",
"pendulum @ git+https://github.com/sdispater/[email protected]",
"tomlkit @ git+https://github.com/sdispater/tomlkit.git@3bff550",
"pathlib2 ~=2.2 ; python_version == '2.7'",
# File dependency
"demo @ ../distributions/demo-0.1.0-py2.py3-none-any.whl",
# Dir dependency with setup.py
"my-package @ ../project_with_setup/",
# Dir dependency with pyproject.toml
"simple-project @ ../simple_project/",
# Dependency with markers
"functools32 ~=3.2.3 ; python_version ~= '2.7' and sys_platform == 'win32' or python_version in '3.4 3.5'",
# Dependency with python constraint
"dataclasses ~=0.7 ; python_full_version >= '3.6.1' and python_version < '3.7'"
]

[project.optional-dependencies]
db = [
"orator ~=0.9"
]
network = [
"requests[security] ~=2.18"
]

[project.urls]
homepage = "https://python-poetry.org"
repository = "https://github.com/python-poetry/poetry"
documentation = "https://python-poetry.org/docs"

[project.scripts]
my-script = "my_package:main"

[project.entry-points."blogtool.parsers"]
".rst" = "some_module::SomeClass"

[tool.poetry.dependencies]
tomlkit = { develop = true }

[dependency-groups]
test = ["pytest>7", "coverage"]
docs = ["mkdocs @ git+https://github.com/mkdocs/mkdocs.git"]

[tool.poetry.group.docs]
optional = true

[tool.poetry.group.docs.dependencies]
mkdocs = { develop = true }
25 changes: 25 additions & 0 deletions tests/test_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,31 @@ def test_create_poetry(project: str) -> None:
]


def test_create_poetry_with_groups() -> None:
poetry = Factory().create_poetry(fixtures_dir / "sample_project_with_groups_new")

assert "docs" in poetry.package._dependency_groups
assert "test" in poetry.package._dependency_groups
assert poetry.package._dependency_groups["docs"].is_optional()
assert not poetry.package._dependency_groups["test"].is_optional()

package = poetry.package
dependencies = {str(dep.name): dep for dep in package.all_requires}

assert dependencies["mkdocs"].name == "mkdocs"
assert isinstance(dependencies["mkdocs"], VCSDependency)
assert dependencies["mkdocs"].develop is True
assert dependencies["mkdocs"].source_type == "git"
assert dependencies["mkdocs"].source == "https://github.com/mkdocs/mkdocs.git"
assert dependencies["mkdocs"].groups == frozenset({"docs"})

assert dependencies["pytest"].name == "pytest"
assert dependencies["pytest"].groups == frozenset({"test"})

assert dependencies["coverage"].name == "coverage"
assert dependencies["coverage"].groups == frozenset({"test"})


def test_create_poetry_with_dependencies_with_subdirectory() -> None:
poetry = Factory().create_poetry(
fixtures_dir / "project_with_dependencies_with_subdirectory"
Expand Down