1
1
import logging
2
2
3
3
import pytest
4
- from mock import patch
4
+ from pip . _vendor import pkg_resources
5
5
6
- from pip ._internal .exceptions import UnsupportedPythonVersion
6
+ from pip ._internal .exceptions import (
7
+ NoneMetadataError , UnsupportedPythonVersion ,
8
+ )
7
9
from pip ._internal .legacy_resolve import _check_dist_requires_python
10
+ from pip ._internal .utils .packaging import get_requires_python
8
11
9
12
10
- class FakeDist (object ):
13
+ # We need to inherit from DistInfoDistribution for the `isinstance()`
14
+ # check inside `packaging.get_metadata()` to work.
15
+ class FakeDist (pkg_resources .DistInfoDistribution ):
11
16
12
- def __init__ (self , project_name ):
13
- self .project_name = project_name
17
+ def __init__ (self , metadata , metadata_name = None ):
18
+ """
19
+ :param metadata: The value that dist.get_metadata() should return
20
+ for the `metadata_name` metadata.
21
+ :param metadata_name: The name of the metadata to store
22
+ (can be "METADATA" or "PKG-INFO"). Defaults to "METADATA".
23
+ """
24
+ if metadata_name is None :
25
+ metadata_name = 'METADATA'
14
26
27
+ self .project_name = 'my-project'
28
+ self .metadata_name = metadata_name
29
+ self .metadata = metadata
15
30
16
- @pytest .fixture
17
- def dist ():
18
- return FakeDist ('my-project' )
31
+ def __str__ (self ):
32
+ return '<distribution {!r}>' .format (self .project_name )
33
+
34
+ def has_metadata (self , name ):
35
+ return (name == self .metadata_name )
36
+
37
+ def get_metadata (self , name ):
38
+ assert name == self .metadata_name
39
+ return self .metadata
40
+
41
+
42
+ def make_fake_dist (requires_python = None , metadata_name = None ):
43
+ metadata = 'Name: test\n '
44
+ if requires_python is not None :
45
+ metadata += 'Requires-Python:{}' .format (requires_python )
46
+
47
+ return FakeDist (metadata , metadata_name = metadata_name )
19
48
20
49
21
- @patch ('pip._internal.legacy_resolve.get_requires_python' )
22
50
class TestCheckDistRequiresPython (object ):
23
51
24
52
"""
25
53
Test _check_dist_requires_python().
26
54
"""
27
55
28
- def test_compatible (self , mock_get_requires , caplog , dist ):
56
+ def test_compatible (self , caplog ):
57
+ """
58
+ Test a Python version compatible with the dist's Requires-Python.
59
+ """
29
60
caplog .set_level (logging .DEBUG )
30
- mock_get_requires .return_value = '== 3.6.5'
31
- _check_dist_requires_python (
32
- dist ,
33
- version_info = (3 , 6 , 5 ),
34
- ignore_requires_python = False ,
35
- )
36
- assert not len (caplog .records )
61
+ dist = make_fake_dist ('== 3.6.5' )
37
62
38
- def test_invalid_specifier (self , mock_get_requires , caplog , dist ):
39
- caplog .set_level (logging .DEBUG )
40
- mock_get_requires .return_value = 'invalid'
41
63
_check_dist_requires_python (
42
64
dist ,
43
65
version_info = (3 , 6 , 5 ),
44
66
ignore_requires_python = False ,
45
67
)
46
- assert len (caplog .records ) == 1
47
- record = caplog .records [0 ]
48
- assert record .levelname == 'WARNING'
49
- assert record .message == (
50
- "Package 'my-project' has an invalid Requires-Python: "
51
- "Invalid specifier: 'invalid'"
52
- )
68
+ assert not len (caplog .records )
53
69
54
- def test_incompatible (self , mock_get_requires , dist ):
55
- mock_get_requires .return_value = '== 3.6.4'
70
+ def test_incompatible (self ):
71
+ """
72
+ Test a Python version incompatible with the dist's Requires-Python.
73
+ """
74
+ dist = make_fake_dist ('== 3.6.4' )
56
75
with pytest .raises (UnsupportedPythonVersion ) as exc :
57
76
_check_dist_requires_python (
58
77
dist ,
@@ -64,11 +83,13 @@ def test_incompatible(self, mock_get_requires, dist):
64
83
"3.6.5 not in '== 3.6.4'"
65
84
)
66
85
67
- def test_incompatible_with_ignore_requires (
68
- self , mock_get_requires , caplog , dist ,
69
- ):
86
+ def test_incompatible_with_ignore_requires (self , caplog ):
87
+ """
88
+ Test a Python version incompatible with the dist's Requires-Python
89
+ while passing ignore_requires_python=True.
90
+ """
70
91
caplog .set_level (logging .DEBUG )
71
- mock_get_requires . return_value = '== 3.6.4'
92
+ dist = make_fake_dist ( '== 3.6.4' )
72
93
_check_dist_requires_python (
73
94
dist ,
74
95
version_info = (3 , 6 , 5 ),
@@ -81,3 +102,67 @@ def test_incompatible_with_ignore_requires(
81
102
"Ignoring failed Requires-Python check for package 'my-project': "
82
103
"3.6.5 not in '== 3.6.4'"
83
104
)
105
+
106
+ def test_none_requires_python (self , caplog ):
107
+ """
108
+ Test a dist with Requires-Python None.
109
+ """
110
+ caplog .set_level (logging .DEBUG )
111
+ dist = make_fake_dist ()
112
+ # Make sure our test setup is correct.
113
+ assert get_requires_python (dist ) is None
114
+ assert len (caplog .records ) == 0
115
+
116
+ # Then there is no exception and no log message.
117
+ _check_dist_requires_python (
118
+ dist ,
119
+ version_info = (3 , 6 , 5 ),
120
+ ignore_requires_python = False ,
121
+ )
122
+ assert len (caplog .records ) == 0
123
+
124
+ def test_invalid_requires_python (self , caplog ):
125
+ """
126
+ Test a dist with an invalid Requires-Python.
127
+ """
128
+ caplog .set_level (logging .DEBUG )
129
+ dist = make_fake_dist ('invalid' )
130
+ _check_dist_requires_python (
131
+ dist ,
132
+ version_info = (3 , 6 , 5 ),
133
+ ignore_requires_python = False ,
134
+ )
135
+ assert len (caplog .records ) == 1
136
+ record = caplog .records [0 ]
137
+ assert record .levelname == 'WARNING'
138
+ assert record .message == (
139
+ "Package 'my-project' has an invalid Requires-Python: "
140
+ "Invalid specifier: 'invalid'"
141
+ )
142
+
143
+ @pytest .mark .parametrize ('metadata_name' , [
144
+ 'METADATA' ,
145
+ 'PKG-INFO' ,
146
+ ])
147
+ def test_empty_metadata_error (self , caplog , metadata_name ):
148
+ """
149
+ Test dist.has_metadata() returning True and dist.get_metadata()
150
+ returning None.
151
+ """
152
+ dist = make_fake_dist (metadata_name = metadata_name )
153
+ dist .metadata = None
154
+
155
+ # Make sure our test setup is correct.
156
+ assert dist .has_metadata (metadata_name )
157
+ assert dist .get_metadata (metadata_name ) is None
158
+
159
+ with pytest .raises (NoneMetadataError ) as exc :
160
+ _check_dist_requires_python (
161
+ dist ,
162
+ version_info = (3 , 6 , 5 ),
163
+ ignore_requires_python = False ,
164
+ )
165
+ assert str (exc .value ) == (
166
+ "None {} metadata found for distribution: "
167
+ "<distribution 'my-project'>" .format (metadata_name )
168
+ )
0 commit comments