Repository: tox-dev/pipdeptree
Pull request #404 (2024-09-02 16:52:03)

[pre-commit.ci] pre-commit autoupdate
<!--pre-commit.ci start-->
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.6.2 → v0.6.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.6.2...v0.6.3)
<!--pre-commit.ci end-->


Patch:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 9e82b25..55c7df6 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -24,4 +24,4 @@ jobs:
       - name: Build package
         run: pyproject-build -s -w . -o dist
       - name: Publish to PyPI
-        uses: pypa/gh-action-pypi-publish@v1.9.0
+        uses: pypa/gh-action-pypi-publish@v1.10.1
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 2b56160..9f1fb0a 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -20,7 +20,7 @@ repos:
       - id: pyproject-fmt
         additional_dependencies: ["tox>=4.12.1"]
   - repo: https://github.com/astral-sh/ruff-pre-commit
-    rev: "v0.6.2"
+    rev: "v0.6.3"
     hooks:
       - id: ruff-format
       - id: ruff
diff --git a/src/pipdeptree/_adapter.py b/src/pipdeptree/_freeze.py
similarity index 85%
rename from src/pipdeptree/_adapter.py
rename to src/pipdeptree/_freeze.py
index 2593662..e6aea91 100644
--- a/src/pipdeptree/_adapter.py
+++ b/src/pipdeptree/_freeze.py
@@ -16,6 +16,16 @@ if TYPE_CHECKING:
     from importlib.metadata import Distribution
 
 
+def dist_to_frozen_repr(dist: Distribution) -> str:
+    """Return the frozen requirement repr of a `importlib.metadata.Distribution` object."""
+    from pip._internal.operations.freeze import FrozenRequirement  # noqa: PLC0415, PLC2701
+
+    adapter = PipBaseDistributionAdapter(dist)
+    fr = FrozenRequirement.from_dist(adapter)  # type: ignore[arg-type]
+
+    return str(fr).strip()
+
+
 class PipBaseDistributionAdapter:
     """
     An adapter class for pip's `pip._internal.metadata.BaseDistribution` abstract class.
@@ -74,3 +84,6 @@ class PipBaseDistributionAdapter:
             with Path(egg_link_path).open("r", encoding=locale.getpreferredencoding(False)) as f:  # noqa: FBT003
                 result = f.readline().rstrip()
         return result
+
+
+__all__ = ["dist_to_frozen_repr"]
diff --git a/src/pipdeptree/_models/package.py b/src/pipdeptree/_models/package.py
index 9d40a44..c62dd27 100644
--- a/src/pipdeptree/_models/package.py
+++ b/src/pipdeptree/_models/package.py
@@ -9,11 +9,11 @@ from typing import TYPE_CHECKING, Iterator
 from packaging.requirements import InvalidRequirement, Requirement
 from packaging.utils import canonicalize_name
 
+from pipdeptree._freeze import dist_to_frozen_repr
+
 if TYPE_CHECKING:
     from importlib.metadata import Distribution
 
-from pipdeptree._adapter import PipBaseDistributionAdapter
-
 
 class InvalidRequirementError(ValueError):
     """
@@ -75,12 +75,7 @@ class Package(ABC):
 
     @staticmethod
     def as_frozen_repr(dist: Distribution) -> str:
-        from pip._internal.operations.freeze import FrozenRequirement  # noqa: PLC0415, PLC2701 # pragma: no cover
-
-        adapter = PipBaseDistributionAdapter(dist)
-        fr = FrozenRequirement.from_dist(adapter)  # type: ignore[arg-type]
-
-        return str(fr).strip()
+        return dist_to_frozen_repr(dist)
 
     def __repr__(self) -> str:
         return f'<{self.__class__.__name__}("{self.key}")>'


Test patch:
diff --git a/tests/_models/test_package.py b/tests/_models/test_package.py
index 6ad7721..43f1f4a 100644
--- a/tests/_models/test_package.py
+++ b/tests/_models/test_package.py
@@ -1,9 +1,6 @@
 from __future__ import annotations
 
-import locale
-import sys
 from importlib.metadata import PackageNotFoundError
-from pathlib import Path
 from typing import TYPE_CHECKING, Any
 from unittest.mock import MagicMock, Mock
 
@@ -29,18 +26,11 @@ def test_guess_version_setuptools(mocker: MockerFixture) -> None:
     assert result == "?"
 
 
-def test_package_as_frozen_repr(tmp_path: Path, mocker: MockerFixture) -> None:
-    file_path = tmp_path / "foo.egg-link"
-    with Path(file_path).open("w", encoding=locale.getpreferredencoding(False)) as f:
-        f.write("/A/B/foo")
-    mock_path = sys.path.copy()
-    mock_path.append(str(tmp_path))
-    mocker.patch("pipdeptree._discovery.sys.path", mock_path)
-    json_text = '{"dir_info": {"editable": true}}'
-    foo = Mock(metadata={"Name": "foo"}, version="20.4.1")
-    foo.read_text = Mock(return_value=json_text)
+def test_package_as_frozen_repr(mocker: MockerFixture) -> None:
+    foo = Mock(metadata={"Name": "foo"}, version="1.2.3")
     dp = DistPackage(foo)
-    expected = "# Editable install with no version control (foo==20.4.1)\n-e /A/B/foo"
+    expected = "test"
+    mocker.patch("pipdeptree._models.package.dist_to_frozen_repr", Mock(return_value=expected))
     assert Package.as_frozen_repr(dp.unwrap()) == expected
 
 
@@ -67,8 +57,7 @@ def test_dist_package_requires_with_environment_markers_that_eval_to_false() ->
 def test_dist_package_render_as_root() -> None:
     foo = Mock(metadata={"Name": "foo"}, version="20.4.1")
     dp = DistPackage(foo)
-    is_frozen = False
-    assert dp.render_as_root(frozen=is_frozen) == "foo==20.4.1"
+    assert dp.render_as_root(frozen=False) == "foo==20.4.1"
 
 
 def test_dist_package_render_as_branch() -> None:
@@ -78,18 +67,15 @@ def test_dist_package_render_as_branch() -> None:
     bar_req.name = "bar"
     rp = ReqPackage(bar_req, dist=bar)
     dp = DistPackage(foo).as_parent_of(rp)
-    is_frozen = False
-    assert dp.render_as_branch(frozen=is_frozen) == "foo==20.4.1 [requires: bar>=4.0]"
+    assert dp.render_as_branch(frozen=False) == "foo==20.4.1 [requires: bar>=4.0]"
 
 
-def test_dist_package_render_as_root_with_frozen() -> None:
-    json_text = '{"dir_info": {"editable": true}, "url": "file:///A/B/foo"}'
-    foo = Mock(metadata={"Name": "foo"}, version="20.4.1")
-    foo.read_text = Mock(return_value=json_text)
+def test_dist_package_render_as_root_with_frozen(mocker: MockerFixture) -> None:
+    foo = Mock(metadata={"Name": "foo"}, version="1.2.3")
     dp = DistPackage(foo)
-    is_frozen = True
-    expect = "# Editable install with no version control (foo==20.4.1)\n-e /A/B/foo"
-    assert dp.render_as_root(frozen=is_frozen) == expect
+    expected = "test"
+    mocker.patch("pipdeptree._models.package.dist_to_frozen_repr", Mock(return_value=expected))
+    assert dp.render_as_root(frozen=True) == expected
 
 
 def test_dist_package_as_parent_of() -> None:
@@ -181,21 +167,18 @@ def test_req_package_render_as_root() -> None:
     bar_req = MagicMock(specifier=[">=4.0"])
     bar_req.name = "bar"
     rp = ReqPackage(bar_req, dist=bar)
-    is_frozen = False
-    assert rp.render_as_root(frozen=is_frozen) == "bar==4.1.0"
+    assert rp.render_as_root(frozen=False) == "bar==4.1.0"
 
 
-def test_req_package_render_as_root_with_frozen() -> None:
-    json_text = '{"dir_info": {"editable": true}, "url": "file:///A/B/bar"}'
+def test_req_package_render_as_root_with_frozen(mocker: MockerFixture) -> None:
     bar = Mock(metadata={"Name": "bar"}, version="4.1.0")
-    bar.read_text = Mock(return_value=json_text)
-    d = DistPackage(bar)
+    dp = DistPackage(bar)
     bar_req = MagicMock(specifier=[">=4.0"])
     bar_req.name = "bar"
-    rp = ReqPackage(bar_req, dist=d)
-    is_frozen = True
-    expect = "# Editable install with no version control (bar==4.1.0)\n-e /A/B/bar"
-    assert rp.render_as_root(frozen=is_frozen) == expect
+    rp = ReqPackage(bar_req, dp)
+    expected = "test"
+    mocker.patch("pipdeptree._models.package.dist_to_frozen_repr", Mock(return_value=expected))
+    assert rp.render_as_root(frozen=True) == expected
 
 
 def test_req_package_render_as_branch() -> None:
@@ -203,8 +186,7 @@ def test_req_package_render_as_branch() -> None:
     bar_req = MagicMock(specifier=[">=4.0"])
     bar_req.name = "bar"
     rp = ReqPackage(bar_req, dist=bar)
-    is_frozen = False
-    assert rp.render_as_branch(frozen=is_frozen) == "bar [required: >=4.0, installed: 4.1.0]"
+    assert rp.render_as_branch(frozen=False) == "bar [required: >=4.0, installed: 4.1.0]"
 
 
 def test_req_package_is_conflicting_handle_dev_versions() -> None:
diff --git a/tests/test_freeze.py b/tests/test_freeze.py
new file mode 100644
index 0000000..6d6a76e
--- /dev/null
+++ b/tests/test_freeze.py
@@ -0,0 +1,12 @@
+from __future__ import annotations
+
+from unittest.mock import Mock
+
+from pipdeptree._freeze import dist_to_frozen_repr
+
+
+def test_dist_to_frozen_repr() -> None:
+    foo = Mock(metadata={"Name": "foo"}, version="20.4.1")
+    foo.read_text = Mock(return_value=None)
+    expected = "foo==20.4.1"
+    assert dist_to_frozen_repr(foo) == expected