Skip to content

Commit

Permalink
info: enhance local path poetry project support
Browse files Browse the repository at this point in the history
This change ensures that package inspection will handle rich core
metadata available for poetry managed projects. This will allow, nested
local path dependencies to use "develop" mode packages.

Resolves: #3098
  • Loading branch information
abn authored and finswimmer committed Oct 6, 2020
1 parent 9010821 commit 8acbd03
Show file tree
Hide file tree
Showing 10 changed files with 147 additions and 39 deletions.
9 changes: 9 additions & 0 deletions poetry/inspection/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,15 @@ def to_package(
package.python_versions = self.requires_python or "*"
package.files = self.files

if root_dir or (self._source_type in {"directory"} and self._source_url):
# this is a local poetry project, this means we can extract "richer" requirement information
# eg: development requirements etc.
poetry_package = self._get_poetry_package(path=root_dir or self._source_url)
if poetry_package:
package.extras = poetry_package.extras
package.requires = poetry_package.requires
return package

for req in self.requires_dist or []:
try:
# Attempt to parse the PEP-508 requirement string
Expand Down
9 changes: 7 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,14 @@ def http():


@pytest.fixture
def fixture_dir():
def fixture_base():
return Path(__file__).parent / "fixtures"


@pytest.fixture
def fixture_dir(fixture_base):
def _fixture_dir(name):
return Path(__file__).parent / "fixtures" / name
return fixture_base / name

return _fixture_dir

Expand Down
11 changes: 11 additions & 0 deletions tests/fixtures/project_with_nested_local/bar/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[tool.poetry]
name = "bar"
version = "1.2.3"
description = "Some description."
authors = ["Poetry Maintainer <tests@python-poetry.org>"]
license = "MIT"

# Requirements
[tool.poetry.dependencies]
python = "~2.7 || ^3.4"
quix = { path = "../quix", develop = true }
11 changes: 11 additions & 0 deletions tests/fixtures/project_with_nested_local/foo/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[tool.poetry]
name = "foo"
version = "1.2.3"
description = "Some description."
authors = ["Poetry Maintainer <tests@python-poetry.org>"]
license = "MIT"

# Requirements
[tool.poetry.dependencies]
python = "~2.7 || ^3.4"
bar = { path = "../bar", develop = true }
12 changes: 12 additions & 0 deletions tests/fixtures/project_with_nested_local/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[tool.poetry]
name = "project-with-nested-local"
version = "1.2.3"
description = "Some description."
authors = ["Poetry Maintainer <tests@python-poetry.org>"]
license = "MIT"

# Requirements
[tool.poetry.dependencies]
python = "~2.7 || ^3.4"
foo = { path = "./foo", develop = true }
bar = { path = "./bar", develop = true }
10 changes: 10 additions & 0 deletions tests/fixtures/project_with_nested_local/quix/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[tool.poetry]
name = "quix"
version = "1.2.3"
description = "Some description."
authors = ["Poetry Maintainer <tests@python-poetry.org>"]
license = "MIT"

# Requirements
[tool.poetry.dependencies]
python = "~2.7 || ^3.4"
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ python-versions = "*"
version = "1.2.3"

[package.dependencies]
pendulum = {version = ">=1.4.4", optional = true, markers = "extra == \"extras_a\""}
pendulum = {version = ">=1.4.4", optional = true}

[package.extras]
extras_a = ["pendulum (>=1.4.4)"]
Expand Down
35 changes: 16 additions & 19 deletions tests/installation/test_installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@
from tests.repositories.test_pypi_repository import MockRepository


fixtures_dir = Path("tests/fixtures")


class Installer(BaseInstaller):
def _get_installer(self):
return NoopInstaller()
Expand Down Expand Up @@ -779,8 +776,8 @@ def test_installer_with_pypi_repository(package, locker, installed, config):
assert locker.written_data == expected


def test_run_installs_with_local_file(installer, locker, repo, package):
file_path = fixtures_dir / "distributions/demo-0.1.0-py2.py3-none-any.whl"
def test_run_installs_with_local_file(installer, locker, repo, package, fixture_dir):
file_path = fixture_dir("distributions/demo-0.1.0-py2.py3-none-any.whl")
package.add_dependency(Factory.create_dependency("demo", {"file": str(file_path)}))

repo.add_package(get_package("pendulum", "1.4.4"))
Expand All @@ -793,9 +790,11 @@ def test_run_installs_with_local_file(installer, locker, repo, package):
assert 2 == installer.executor.installations_count


def test_run_installs_wheel_with_no_requires_dist(installer, locker, repo, package):
file_path = (
fixtures_dir / "wheel_with_no_requires_dist/demo-0.1.0-py2.py3-none-any.whl"
def test_run_installs_wheel_with_no_requires_dist(
installer, locker, repo, package, fixture_dir
):
file_path = fixture_dir(
"wheel_with_no_requires_dist/demo-0.1.0-py2.py3-none-any.whl"
)
package.add_dependency(Factory.create_dependency("demo", {"file": str(file_path)}))

Expand All @@ -809,31 +808,29 @@ def test_run_installs_wheel_with_no_requires_dist(installer, locker, repo, packa


def test_run_installs_with_local_poetry_directory_and_extras(
installer, locker, repo, package, tmpdir
installer, locker, repo, package, tmpdir, fixture_dir
):
file_path = fixtures_dir / "project_with_extras"
file_path = fixture_dir("project_with_extras")
package.add_dependency(
Factory.create_dependency(
"project-with-extras", {"path": str(file_path), "extras": ["extras_a"]}
)
)
print(package.requires[0].develop)

repo.add_package(get_package("pendulum", "1.4.4"))

installer.run()

expected = fixture("with-directory-dependency-poetry")

assert locker.written_data == expected

assert 2 == installer.executor.installations_count


def test_run_installs_with_local_poetry_directory_transitive(
installer, locker, repo, package, tmpdir
installer, locker, repo, package, tmpdir, fixture_dir
):
root_dir = fixtures_dir.joinpath("directory")
root_dir = fixture_dir("directory")
package.root_dir = root_dir
locker.set_lock_path(root_dir)
directory = root_dir.joinpath("project_with_transitive_directory_dependencies")
Expand All @@ -858,12 +855,12 @@ def test_run_installs_with_local_poetry_directory_transitive(


def test_run_installs_with_local_poetry_file_transitive(
installer, locker, repo, package, tmpdir
installer, locker, repo, package, tmpdir, fixture_dir
):
root_dir = fixtures_dir.joinpath("directory")
root_dir = fixture_dir("directory")
package.root_dir = root_dir
locker.set_lock_path(root_dir)
directory = fixtures_dir.joinpath("directory").joinpath(
directory = fixture_dir("directory").joinpath(
"project_with_transitive_file_dependencies"
)
package.add_dependency(
Expand All @@ -887,9 +884,9 @@ def test_run_installs_with_local_poetry_file_transitive(


def test_run_installs_with_local_setuptools_directory(
installer, locker, repo, package, tmpdir
installer, locker, repo, package, tmpdir, fixture_dir
):
file_path = fixtures_dir / "project_with_setup/"
file_path = fixture_dir("project_with_setup/")
package.add_dependency(
Factory.create_dependency("project-with-setup", {"path": str(file_path)})
)
Expand Down
33 changes: 16 additions & 17 deletions tests/installation/test_installer_old.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@
from tests.repositories.test_pypi_repository import MockRepository


fixtures_dir = Path("tests/fixtures")


class Installer(BaseInstaller):
def _get_installer(self):
return NoopInstaller()
Expand Down Expand Up @@ -749,8 +746,8 @@ def test_installer_with_pypi_repository(package, locker, installed, config):
assert locker.written_data == expected


def test_run_installs_with_local_file(installer, locker, repo, package):
file_path = fixtures_dir / "distributions/demo-0.1.0-py2.py3-none-any.whl"
def test_run_installs_with_local_file(installer, locker, repo, package, fixture_dir):
file_path = fixture_dir("distributions/demo-0.1.0-py2.py3-none-any.whl")
package.add_dependency(Factory.create_dependency("demo", {"file": str(file_path)}))

repo.add_package(get_package("pendulum", "1.4.4"))
Expand All @@ -764,9 +761,11 @@ def test_run_installs_with_local_file(installer, locker, repo, package):
assert len(installer.installer.installs) == 2


def test_run_installs_wheel_with_no_requires_dist(installer, locker, repo, package):
file_path = (
fixtures_dir / "wheel_with_no_requires_dist/demo-0.1.0-py2.py3-none-any.whl"
def test_run_installs_wheel_with_no_requires_dist(
installer, locker, repo, package, fixture_dir
):
file_path = fixture_dir(
"wheel_with_no_requires_dist/demo-0.1.0-py2.py3-none-any.whl"
)
package.add_dependency(Factory.create_dependency("demo", {"file": str(file_path)}))

Expand All @@ -780,9 +779,9 @@ def test_run_installs_wheel_with_no_requires_dist(installer, locker, repo, packa


def test_run_installs_with_local_poetry_directory_and_extras(
installer, locker, repo, package, tmpdir
installer, locker, repo, package, tmpdir, fixture_dir
):
file_path = fixtures_dir / "project_with_extras"
file_path = fixture_dir("project_with_extras")
package.add_dependency(
Factory.create_dependency(
"project-with-extras", {"path": str(file_path), "extras": ["extras_a"]}
Expand All @@ -801,9 +800,9 @@ def test_run_installs_with_local_poetry_directory_and_extras(


def test_run_installs_with_local_poetry_directory_transitive(
installer, locker, repo, package, tmpdir
installer, locker, repo, package, tmpdir, fixture_dir
):
root_dir = fixtures_dir.joinpath("directory")
root_dir = fixture_dir("directory")
package.root_dir = root_dir
locker.set_lock_path(root_dir)
directory = root_dir.joinpath("project_with_transitive_directory_dependencies")
Expand All @@ -828,16 +827,16 @@ def test_run_installs_with_local_poetry_directory_transitive(


def test_run_installs_with_local_poetry_file_transitive(
installer, locker, repo, package, tmpdir
installer, locker, repo, package, tmpdir, fixture_dir
):
root_dir = fixtures_dir.joinpath("directory")
root_dir = fixture_dir("directory")
package.root_dir = root_dir
locker.set_lock_path(root_dir)
directory = root_dir.joinpath("project_with_transitive_file_dependencies")
package.add_dependency(
Factory.create_dependency(
"project-with-transitive-file-dependencies",
{"path": str(directory.relative_to(fixtures_dir.joinpath("directory")))},
{"path": str(directory.relative_to(fixture_dir("directory")))},
root_dir=root_dir,
)
)
Expand All @@ -855,9 +854,9 @@ def test_run_installs_with_local_poetry_file_transitive(


def test_run_installs_with_local_setuptools_directory(
installer, locker, repo, package, tmpdir
installer, locker, repo, package, tmpdir, fixture_dir
):
file_path = fixtures_dir / "project_with_setup/"
file_path = fixture_dir("project_with_setup/")
package.add_dependency(
Factory.create_dependency("project-with-setup", {"path": str(file_path)})
)
Expand Down
54 changes: 54 additions & 0 deletions tests/puzzle/test_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -1672,6 +1672,60 @@ def test_solver_can_resolve_directory_dependencies(solver, repo, package):
assert op.package.source_url == path


def test_solver_can_resolve_directory_dependencies_nested_editable(
solver, repo, pool, installed, locked, io
):
base = Path(__file__).parent.parent / "fixtures" / "project_with_nested_local"
poetry = Factory().create_poetry(cwd=base)
package = poetry.package

solver = Solver(
package, pool, installed, locked, io, provider=Provider(package, pool, io)
)

ops = solver.solve()

check_solver_result(
ops,
[
{
"job": "install",
"package": Package(
"quix",
"1.2.3",
source_type="directory",
source_url=(base / "quix").as_posix(),
),
"skipped": False,
},
{
"job": "install",
"package": Package(
"bar",
"1.2.3",
source_type="directory",
source_url=(base / "bar").as_posix(),
),
"skipped": False,
},
{
"job": "install",
"package": Package(
"foo",
"1.2.3",
source_type="directory",
source_url=(base / "foo").as_posix(),
),
"skipped": False,
},
],
)

for op in ops:
assert op.package.source_type == "directory"
assert op.package.develop is True


def test_solver_can_resolve_directory_dependencies_with_extras(solver, repo, package):
pendulum = get_package("pendulum", "2.0.3")
cleo = get_package("cleo", "1.0.0")
Expand Down

0 comments on commit 8acbd03

Please sign in to comment.