File: test_package.py

package info (click to toggle)
python-pipdeptree 2.30.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 348 kB
  • sloc: python: 3,286; sh: 28; makefile: 5
file content (242 lines) | stat: -rw-r--r-- 8,488 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
from __future__ import annotations

from importlib.metadata import PackageNotFoundError
from typing import TYPE_CHECKING, Any
from unittest.mock import MagicMock, Mock

import pytest
from packaging.specifiers import SpecifierSet

from pipdeptree._models import DistPackage, ReqPackage
from pipdeptree._models.package import Package

if TYPE_CHECKING:
    from pytest_mock import MockerFixture


def sort_map_values(m: dict[str, Any]) -> dict[str, Any]:
    return {k: sorted(v) for k, v in m.items()}


def test_guess_version_setuptools(mocker: MockerFixture) -> None:
    mocker.patch("pipdeptree._models.package.version", side_effect=PackageNotFoundError)
    r = MagicMock()
    r.name = "setuptools"
    result = ReqPackage(r).installed_version
    assert result == "?"


def test_package_as_frozen_repr(mocker: MockerFixture) -> None:
    foo = Mock(metadata={"Name": "foo"}, version="1.2.3")
    dp = DistPackage(foo)
    expected = "test"
    mocker.patch("pipdeptree._models.package.dist_to_frozen_repr", Mock(return_value=expected))
    assert Package.as_frozen_repr(dp.unwrap()) == expected


def test_dist_package_requires() -> None:
    foo = Mock(
        metadata={"Name": "foo"},
        requires=["bar", "baz >=2.7.2"],
    )
    dp = DistPackage(foo)
    reqs = list(dp.requires())
    assert len(reqs) == 2


def test_dist_package_requires_with_environment_markers_that_eval_to_false() -> None:
    foo = Mock(
        metadata={"Name": "foo"},
        requires=['foo ; sys_platform == "NoexistOS"', "bar >=2.7.2 ; extra == 'testing'"],
    )
    dp = DistPackage(foo)
    reqs = list(dp.requires())
    assert len(reqs) == 0


def test_dist_package_render_as_root() -> None:
    foo = Mock(metadata={"Name": "foo"}, version="20.4.1")
    dp = DistPackage(foo)
    assert dp.render_as_root(frozen=False) == "foo==20.4.1"


def test_dist_package_render_as_branch() -> None:
    foo = Mock(metadata={"Name": "foo"}, version="20.4.1")
    bar = Mock(metadata={"Name": "bar"}, version="4.1.0")
    bar_req = MagicMock(version="4.1.0", specifier=[">=4.0"])
    bar_req.name = "bar"
    rp = ReqPackage(bar_req, dist=bar)
    dp = DistPackage(foo).as_parent_of(rp)
    assert dp.render_as_branch(frozen=False) == "foo==20.4.1 [requires: bar>=4.0]"


def test_dist_package_render_as_root_with_frozen(mocker: MockerFixture) -> None:
    foo = Mock(metadata={"Name": "foo"}, version="1.2.3")
    dp = DistPackage(foo)
    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:
    foo = Mock(metadata={"Name": "foo"}, version="20.4.1")
    dp = DistPackage(foo)
    assert dp.req is None

    bar = Mock(metadata={"Name": "bar"}, version="4.1.0")
    bar_req = MagicMock(version="4.1.0", specifier=[">=4.0"])
    bar_req.name = "bar"
    rp = ReqPackage(bar_req, dist=bar)
    dp1 = dp.as_parent_of(rp)
    assert dp1._obj == dp._obj  # noqa: SLF001
    assert dp1.req is rp

    dp2 = dp.as_parent_of(None)
    assert dp2 is dp


def test_dist_package_as_dict() -> None:
    foo = Mock(metadata={"Name": "foo"}, version="1.3.2b1")
    dp = DistPackage(foo)
    result = dp.as_dict()
    expected = {"key": "foo", "package_name": "foo", "installed_version": "1.3.2b1"}
    assert expected == result


@pytest.mark.parametrize(
    ("mocked_metadata", "expected_output"),
    [
        pytest.param(
            Mock(__getitem__=Mock(return_value=None), get_all=Mock(return_value=[])),
            Package.UNKNOWN_LICENSE_STR,
            id="no-license",
        ),
        pytest.param(
            Mock(
                __getitem__=Mock(return_value=None),
                get_all=Mock(
                    return_value=[
                        "License :: OSI Approved :: GNU General Public License v2 (GPLv2)",
                        "Operating System :: OS Independent",
                    ]
                ),
            ),
            "(GNU General Public License v2 (GPLv2))",
            id="one-license-with-one-non-license",
        ),
        pytest.param(
            Mock(
                __getitem__=Mock(return_value=None),
                get_all=Mock(
                    return_value=[
                        "License :: OSI Approved :: GNU General Public License v2 (GPLv2)",
                        "License :: OSI Approved :: Apache Software License",
                    ]
                ),
            ),
            "(GNU General Public License v2 (GPLv2), Apache Software License)",
            id="more-than-one-license",
        ),
        pytest.param(
            Mock(__getitem__=Mock(return_value="MIT"), get_all=Mock(return_value=[])),
            "(MIT)",
            id="license-expression",
        ),
        pytest.param(
            Mock(
                __getitem__=Mock(return_value="MIT"),
                get_all=Mock(
                    return_value=[
                        "License :: OSI Approved :: MIT License",
                    ]
                ),
            ),
            "(MIT)",
            id="license-expression-with-license-classifier",
        ),
    ],
)
def test_dist_package_licenses(mocked_metadata: Mock, expected_output: str, monkeypatch: pytest.MonkeyPatch) -> None:
    monkeypatch.setattr("pipdeptree._models.package.metadata", Mock(return_value=mocked_metadata))
    dist = DistPackage(Mock(metadata={"Name": "a"}))
    licenses_str = dist.licenses()

    assert licenses_str == expected_output


def test_dist_package_licenses_importlib_cant_find_package(monkeypatch: pytest.MonkeyPatch) -> None:
    monkeypatch.setattr("pipdeptree._models.package.metadata", Mock(side_effect=PackageNotFoundError()))
    dist = DistPackage(Mock(metadata={"Name": "a"}))
    licenses_str = dist.licenses()

    assert licenses_str == Package.UNKNOWN_LICENSE_STR


def test_dist_package_key_pep503_normalized() -> None:
    foobar = Mock(metadata={"Name": "foo.bar"}, version="20.4.1")
    dp = DistPackage(foobar)
    assert dp.key == "foo-bar"


def test_req_package_key_pep503_normalized() -> None:
    bar_req = MagicMock(specifier=[">=4.0"])
    bar_req.name = "bar.bar-bar-bar"
    rp = ReqPackage(bar_req)
    assert rp.key == "bar-bar-bar-bar"


def test_req_package_render_as_root() -> None:
    bar = Mock(metadata={"Name": "bar"}, version="4.1.0")
    bar_req = MagicMock(specifier=[">=4.0"])
    bar_req.name = "bar"
    rp = ReqPackage(bar_req, dist=bar)
    assert rp.render_as_root(frozen=False) == "bar==4.1.0"


def test_req_package_render_as_root_with_frozen(mocker: MockerFixture) -> None:
    bar = Mock(metadata={"Name": "bar"}, version="4.1.0")
    dp = DistPackage(bar)
    bar_req = MagicMock(specifier=[">=4.0"])
    bar_req.name = "bar"
    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:
    bar = Mock(metadata={"Name": "bar"}, version="4.1.0")
    bar_req = MagicMock(specifier=[">=4.0"])
    bar_req.name = "bar"
    rp = ReqPackage(bar_req, dist=bar)
    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:
    # ensure that we can handle development versions when detecting conflicts
    # see https://github.com/tox-dev/pipdeptree/issues/393
    bar = Mock(metadata={"Name": "bar"}, version="1.2.3.dev0")
    bar_req = MagicMock(specifier=SpecifierSet(">1.2.0"))
    bar_req.name = "bar"
    rp = ReqPackage(bar_req, dist=bar)
    assert not rp.is_conflicting()


def test_req_package_as_dict() -> None:
    bar = Mock(metadata={"Name": "bar"}, version="4.1.0")
    bar_req = MagicMock(specifier=[">=4.0"])
    bar_req.name = "bar"
    rp = ReqPackage(bar_req, dist=bar)
    result = rp.as_dict()
    expected = {"key": "bar", "package_name": "bar", "installed_version": "4.1.0", "required_version": ">=4.0"}
    assert expected == result


def test_req_package_as_dict_with_no_version_spec() -> None:
    bar = Mock(key="bar", version="4.1.0")
    bar_req = MagicMock(specifier=[])
    bar_req.name = "bar"
    rp = ReqPackage(bar_req, dist=bar)
    result = rp.as_dict()
    expected = {"key": "bar", "package_name": "bar", "installed_version": "4.1.0", "required_version": "Any"}
    assert expected == result