-
Notifications
You must be signed in to change notification settings - Fork 251
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
Allow non-existant path dependencies #507
Changes from all commits
095d452
d891024
d8b868a
87b5a4f
a8368e7
0755814
953c91b
efbba4b
b6922e3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,12 +5,15 @@ | |
|
||
from pathlib import Path | ||
from typing import Iterable | ||
from warnings import warn | ||
|
||
from poetry.core.packages.dependency import Dependency | ||
from poetry.core.packages.utils.utils import path_to_url | ||
|
||
|
||
class FileDependency(Dependency): | ||
_full_path: Path | None | ||
|
||
def __init__( | ||
self, | ||
name: str, | ||
|
@@ -22,19 +25,8 @@ def __init__( | |
) -> None: | ||
self._path = path | ||
self._base = base or Path.cwd() | ||
self._full_path = path | ||
|
||
if not self._path.is_absolute(): | ||
try: | ||
self._full_path = self._base.joinpath(self._path).resolve() | ||
except FileNotFoundError: | ||
raise ValueError(f"Directory {self._path} does not exist") | ||
|
||
if not self._full_path.exists(): | ||
raise ValueError(f"File {self._path} does not exist") | ||
|
||
if self._full_path.is_dir(): | ||
raise ValueError(f"{self._path} is a directory, expected a file") | ||
self._full_path = None | ||
full_path = self._get_full_path(False, name) | ||
|
||
super().__init__( | ||
name, | ||
|
@@ -43,10 +35,40 @@ def __init__( | |
optional=optional, | ||
allows_prereleases=True, | ||
source_type="file", | ||
source_url=self._full_path.as_posix(), | ||
source_url=full_path.as_posix(), | ||
extras=extras, | ||
) | ||
|
||
def _get_full_path(self, raise_if_invalid: bool, name: str) -> Path: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adding |
||
if self._full_path is not None: | ||
return self._full_path | ||
Comment on lines
+43
to
+44
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This little bit of caching means that if we already checked in |
||
full_path = self._path | ||
if not self._path.is_absolute(): | ||
try: | ||
full_path = self._base.joinpath(self._path).resolve() | ||
except FileNotFoundError: | ||
msg = f"Source file {self._path} for {name} does not exist" | ||
if raise_if_invalid: | ||
raise ValueError(msg) | ||
warn(msg, category=UserWarning) | ||
return full_path | ||
|
||
if not full_path.exists(): | ||
msg = f"Source file {self._path} for {name} does not exist" | ||
if raise_if_invalid: | ||
raise ValueError(msg) | ||
warn(msg, category=UserWarning) | ||
return full_path | ||
|
||
if full_path.is_dir(): | ||
raise ValueError( | ||
f"Expected source for {name} to be a" | ||
f" file but {self._path} is a directory" | ||
) | ||
|
||
self._full_path = full_path | ||
return full_path | ||
|
||
@property | ||
def base(self) -> Path: | ||
return self._base | ||
|
@@ -57,14 +79,14 @@ def path(self) -> Path: | |
|
||
@property | ||
def full_path(self) -> Path: | ||
return self._full_path | ||
return self._get_full_path(True, self.name) | ||
|
||
def is_file(self) -> bool: | ||
return True | ||
|
||
def hash(self, hash_name: str = "sha256") -> str: | ||
h = hashlib.new(hash_name) | ||
with self._full_path.open("rb") as fp: | ||
with self.full_path.open("rb") as fp: | ||
for content in iter(lambda: fp.read(io.DEFAULT_BUFFER_SIZE), b""): | ||
h.update(content) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# missing build section |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,7 +22,7 @@ | |
|
||
def test_file_dependency_wrong_path() -> None: | ||
with pytest.raises(ValueError): | ||
FileDependency("demo", DIST_PATH / "demo-0.2.0.tar.gz") | ||
FileDependency("demo", DIST_PATH / "demo-0.2.0.tar.gz").full_path | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think these tests should be testing each individual failure mode, but this was good enough for years so I suppose it will do |
||
|
||
|
||
def test_file_dependency_dir() -> None: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -298,18 +298,6 @@ def test_create_poetry_omits_dev_dependencies_iff_with_dev_is_false() -> None: | |
assert any("dev" in r.groups for r in poetry.package.all_requires) | ||
|
||
|
||
def test_create_poetry_fails_with_invalid_dev_dependencies_iff_with_dev_is_true() -> ( | ||
None | ||
): | ||
with pytest.raises(ValueError) as err: | ||
Factory().create_poetry(fixtures_dir / "project_with_invalid_dev_deps") | ||
assert "does not exist" in str(err.value) | ||
|
||
Factory().create_poetry( | ||
fixtures_dir / "project_with_invalid_dev_deps", with_groups=False | ||
) | ||
|
||
|
||
Comment on lines
-301
to
-312
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removing this test since we actually want to be able to create a Poetry object with invalid path deps, we just want it to fail for certain operations (install, show, etc.). |
||
def test_create_poetry_with_groups_and_legacy_dev() -> None: | ||
poetry = Factory().create_poetry( | ||
fixtures_dir / "project_with_groups_and_legacy_dev" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here. If I don't care for existence, I won't care if it's not a Python package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to push back on this a bit. There's a real use case for creating a
DirectoryDependency
pointing to a path that does not exist: you deleted or renamed the dependency and are updating the lock file. I can't think of any use case where you'd want to point at an existing but invalid dependency, so in those cases I think failing fast is the best option.