Skip to content

Commit

Permalink
normalize source vcs urls
Browse files Browse the repository at this point in the history
This change ensures when referencing source url for package
specifications of source type "git" or for VCS dependencies, a
normalized version returned at all times.

Relates-to: python-poetry/poetry#8999
  • Loading branch information
abn committed Feb 24, 2024
1 parent 219c52e commit 78ddf35
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 5 deletions.
13 changes: 12 additions & 1 deletion src/poetry/core/packages/specification.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def __init__(
self._pretty_name = name
self._name = canonicalize_name(name)
self._source_type = source_type
self._source_url = source_url
self._source_url = self._normalize_source_url(source_type, source_url)
self._source_reference = source_reference
self._source_resolved_reference = source_resolved_reference
self._source_subdirectory = source_subdirectory
Expand All @@ -45,6 +45,17 @@ def __init__(

self._features = frozenset(canonicalize_name(feature) for feature in features)

@staticmethod
def _normalize_source_url(
source_type: str | None, source_url: str | None
) -> str | None:
if source_type and source_url and source_type == "git":
from poetry.core.vcs.git import ParsedUrl

return ParsedUrl.parse(source_url).url

return source_url

@property
def name(self) -> NormalizedName:
return self._name
Expand Down
5 changes: 3 additions & 2 deletions src/poetry/core/packages/vcs_dependency.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ def __init__(
# Attributes must be immutable for clone() to be safe!
# (For performance reasons, clone only creates a copy instead of a deep copy).
self._vcs = vcs
self._source = source

self._branch = branch
self._tag = tag
Expand All @@ -47,13 +46,15 @@ def __init__(
optional=optional,
allows_prereleases=True,
source_type=self._vcs.lower(),
source_url=self._source,
source_url=source,
source_reference=branch or tag or rev or "HEAD",
source_resolved_reference=resolved_rev,
source_subdirectory=directory,
extras=extras,
)

self._source = self.source_url

@property
def vcs(self) -> str:
return self._vcs
Expand Down
2 changes: 1 addition & 1 deletion src/poetry/core/vcs/git.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def parse(cls, url: str) -> ParsedUrl:
if m:
groups = m.groupdict()
return ParsedUrl(
groups.get("protocol"),
groups.get("protocol", "ssh"),
groups.get("resource"),
groups.get("pathname"),
groups.get("user"),
Expand Down
38 changes: 38 additions & 0 deletions tests/packages/test_specification.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,41 @@ def test_equal_specifications_have_same_hash(
assert spec1 == spec2
assert spec2 == spec1
assert hash(spec1) == hash(spec2)


@pytest.mark.parametrize(
"source_url,normalized_url",
[
("https://github.com/demo/demo.git", "https://github.com/demo/demo.git"),
("git@github.com:demo/demo.git", "ssh://git@github.com/demo/demo.git"),
],
)
def test_specification_normalize_source_url_method(
source_url: str, normalized_url: str
) -> None:
assert (
PackageSpecification._normalize_source_url("git", source_url) == normalized_url
)
assert (
PackageSpecification._normalize_source_url("notgit", source_url) == source_url
)


@pytest.mark.parametrize(
"source_url,normalized_url",
[
("https://github.com/demo/demo.git", "https://github.com/demo/demo.git"),
("git@github.com:demo/demo.git", "ssh://git@github.com/demo/demo.git"),
],
)
def test_specification_uses_normalize_source_url_for_git(
source_url: str, normalized_url: str
) -> None:
assert (
PackageSpecification(
name="demo",
source_type="git",
source_url=source_url,
).source_url
== normalized_url
)
18 changes: 18 additions & 0 deletions tests/packages/test_vcs_dependency.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,3 +229,21 @@ def test_vcs_dependencies_are_equal_if_resolved_references_match() -> None:
)

assert dependency1 == dependency2


@pytest.mark.parametrize(
"source_url,normalized_url",
[
("https://github.com/demo/demo.git", "https://github.com/demo/demo.git"),
("git@github.com:demo/demo.git", "ssh://git@github.com/demo/demo.git"),
],
)
def test_vcs_source_is_normalized(source_url: str, normalized_url: str) -> None:
dependency = VCSDependency(
name="demo",
vcs="git",
source=source_url,
branch="main",
)
assert dependency.source == normalized_url
assert dependency.source_url == normalized_url
2 changes: 1 addition & 1 deletion tests/vcs/test_vcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ def test_normalize_url(url: str, normalized: GitUrl) -> None:
),
(
"git@github.com:org/repo",
ParsedUrl(None, "github.com", ":org/repo", "git", None, "repo", None),
ParsedUrl("ssh", "github.com", ":org/repo", "git", None, "repo", None),
),
(
"git+https://github.com/sdispater/pendulum",
Expand Down

0 comments on commit 78ddf35

Please sign in to comment.