Skip to content

Commit facbd38

Browse files
committed
feat(pip/_internal): Skip current directory when performing freeze
This skips any *.egg_info present in the current directory when performing pip freeze. This fixes pypa#2926
1 parent 9e884a4 commit facbd38

File tree

3 files changed

+67
-25
lines changed

3 files changed

+67
-25
lines changed

src/pip/_internal/utils/misc.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111
import io
1212
import logging
1313
import os
14-
import posixpath
1514
import shutil
1615
import stat
1716
import sys
1817
from collections import deque
1918

19+
import posixpath
2020
from pip._vendor import pkg_resources
2121
# NOTE: retrying is not annotated in typeshed as on 2017-07-17, which is
2222
# why we ignore the type on this import.
@@ -397,6 +397,14 @@ def dist_is_editable(dist):
397397
return False
398398

399399

400+
def dist_in_curr_dir(dist):
401+
'''
402+
Return True if given Distribution is installed in the current directory.
403+
'''
404+
norm_path = normalize_path(dist_location(dist))
405+
return norm_path.startswith(normalize_path(os.getcwd()))
406+
407+
400408
def get_installed_distributions(
401409
local_only=True, # type: bool
402410
skip=stdlib_pkgs, # type: Container[str]
@@ -456,12 +464,15 @@ def editables_only_test(d):
456464
def user_test(d):
457465
return True
458466

467+
curr_dir_test = dist_in_curr_dir
468+
459469
return [d for d in working_set
460470
if local_test(d) and
461471
d.key not in skip and
462472
editable_test(d) and
463473
editables_only_test(d) and
464-
user_test(d)
474+
user_test(d) and
475+
not curr_dir_test(d)
465476
]
466477

467478

tests/functional/test_freeze.py

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -79,34 +79,36 @@ def test_freeze_with_pip(script):
7979
assert 'pip==' in result.stdout
8080

8181

82+
def _fake_install(pkgname, dest):
83+
egg_info_path = os.path.join(
84+
dest, '{}-1.0-py{}.{}.egg-info'.format(
85+
pkgname.replace('-', '_'),
86+
sys.version_info[0],
87+
sys.version_info[1]
88+
)
89+
)
90+
with open(egg_info_path, 'w') as egg_info_file:
91+
egg_info_file.write(textwrap.dedent("""\
92+
Metadata-Version: 1.0
93+
Name: {}
94+
Version: 1.0
95+
""".format(pkgname)
96+
))
97+
return egg_info_path
98+
99+
82100
def test_freeze_with_invalid_names(script):
83101
"""
84102
Test that invalid names produce warnings and are passed over gracefully.
85103
"""
86104

87-
def fake_install(pkgname, dest):
88-
egg_info_path = os.path.join(
89-
dest, '{}-1.0-py{}.{}.egg-info'.format(
90-
pkgname.replace('-', '_'),
91-
sys.version_info[0],
92-
sys.version_info[1]
93-
)
94-
)
95-
with open(egg_info_path, 'w') as egg_info_file:
96-
egg_info_file.write(textwrap.dedent("""\
97-
Metadata-Version: 1.0
98-
Name: {}
99-
Version: 1.0
100-
""".format(pkgname)
101-
))
102-
103105
valid_pkgnames = ('middle-dash', 'middle_underscore', 'middle.dot')
104106
invalid_pkgnames = (
105107
'-leadingdash', '_leadingunderscore', '.leadingdot',
106108
'trailingdash-', 'trailingunderscore_', 'trailingdot.'
107109
)
108110
for pkgname in valid_pkgnames + invalid_pkgnames:
109-
fake_install(pkgname, script.site_packages_path)
111+
_fake_install(pkgname, script.site_packages_path)
110112
result = script.pip('freeze', expect_stderr=True)
111113
for pkgname in valid_pkgnames:
112114
_check_output(
@@ -129,6 +131,18 @@ def fake_install(pkgname, dest):
129131
_check_output(result.stderr, expected)
130132

131133

134+
def test_freeze_skip_curr_dir(script):
135+
"""
136+
Test that an .egginfo is skipped when present in current directory
137+
"""
138+
139+
curr_dir = os.getcwd()
140+
egg_info_path = _fake_install("foo-package", curr_dir)
141+
result = script.pip("freeze")
142+
os.remove(egg_info_path)
143+
assert "foo-package==" not in result.stdout
144+
145+
132146
@pytest.mark.git
133147
def test_freeze_editable_not_vcs(script, tmpdir):
134148
"""

tests/unit/test_utils.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ def test_noegglink_in_sitepkgs_venv_global(self):
188188
assert egg_link_path(self.mock_dist) is None
189189

190190

191+
@patch('pip._internal.utils.misc.dist_in_curr_dir')
191192
@patch('pip._internal.utils.misc.dist_in_usersite')
192193
@patch('pip._internal.utils.misc.dist_is_local')
193194
@patch('pip._internal.utils.misc.dist_is_editable')
@@ -199,6 +200,7 @@ class Tests_get_installed_distributions:
199200
Mock(test_name="editable"),
200201
Mock(test_name="normal"),
201202
Mock(test_name="user"),
203+
Mock(test_name="curr_dir")
202204
]
203205

204206
workingset_stdlib = [
@@ -221,45 +223,56 @@ def dist_is_local(self, dist):
221223
def dist_in_usersite(self, dist):
222224
return dist.test_name == "user"
223225

226+
def dist_in_curr_dir(self, dist):
227+
return dist.test_name == "curr_dir"
228+
224229
@patch('pip._vendor.pkg_resources.working_set', workingset)
225230
def test_editables_only(self, mock_dist_is_editable,
226231
mock_dist_is_local,
227-
mock_dist_in_usersite):
232+
mock_dist_in_usersite,
233+
mock_dist_in_curr_dir):
228234
mock_dist_is_editable.side_effect = self.dist_is_editable
229235
mock_dist_is_local.side_effect = self.dist_is_local
230236
mock_dist_in_usersite.side_effect = self.dist_in_usersite
237+
mock_dist_in_curr_dir.side_effect = self.dist_in_curr_dir
231238
dists = get_installed_distributions(editables_only=True)
232239
assert len(dists) == 1, dists
233240
assert dists[0].test_name == "editable"
234241

235242
@patch('pip._vendor.pkg_resources.working_set', workingset)
236243
def test_exclude_editables(self, mock_dist_is_editable,
237244
mock_dist_is_local,
238-
mock_dist_in_usersite):
245+
mock_dist_in_usersite,
246+
mock_dist_in_curr_dir):
239247
mock_dist_is_editable.side_effect = self.dist_is_editable
240248
mock_dist_is_local.side_effect = self.dist_is_local
241249
mock_dist_in_usersite.side_effect = self.dist_in_usersite
250+
mock_dist_in_curr_dir.side_effect = self.dist_in_curr_dir
242251
dists = get_installed_distributions(include_editables=False)
243252
assert len(dists) == 1
244253
assert dists[0].test_name == "normal"
245254

246255
@patch('pip._vendor.pkg_resources.working_set', workingset)
247256
def test_include_globals(self, mock_dist_is_editable,
248257
mock_dist_is_local,
249-
mock_dist_in_usersite):
258+
mock_dist_in_usersite,
259+
mock_dist_in_curr_dir):
250260
mock_dist_is_editable.side_effect = self.dist_is_editable
251261
mock_dist_is_local.side_effect = self.dist_is_local
252262
mock_dist_in_usersite.side_effect = self.dist_in_usersite
263+
mock_dist_in_curr_dir.side_effect = self.dist_in_curr_dir
253264
dists = get_installed_distributions(local_only=False)
254265
assert len(dists) == 4
255266

256267
@patch('pip._vendor.pkg_resources.working_set', workingset)
257268
def test_user_only(self, mock_dist_is_editable,
258269
mock_dist_is_local,
259-
mock_dist_in_usersite):
270+
mock_dist_in_usersite,
271+
mock_dist_in_curr_dir):
260272
mock_dist_is_editable.side_effect = self.dist_is_editable
261273
mock_dist_is_local.side_effect = self.dist_is_local
262274
mock_dist_in_usersite.side_effect = self.dist_in_usersite
275+
mock_dist_in_curr_dir.side_effect = self.dist_in_curr_dir
263276
dists = get_installed_distributions(local_only=False,
264277
user_only=True)
265278
assert len(dists) == 1
@@ -268,20 +281,24 @@ def test_user_only(self, mock_dist_is_editable,
268281
@patch('pip._vendor.pkg_resources.working_set', workingset_stdlib)
269282
def test_gte_py27_excludes(self, mock_dist_is_editable,
270283
mock_dist_is_local,
271-
mock_dist_in_usersite):
284+
mock_dist_in_usersite,
285+
mock_dist_in_curr_dir):
272286
mock_dist_is_editable.side_effect = self.dist_is_editable
273287
mock_dist_is_local.side_effect = self.dist_is_local
274288
mock_dist_in_usersite.side_effect = self.dist_in_usersite
289+
mock_dist_in_curr_dir.side_effect = self.dist_in_curr_dir
275290
dists = get_installed_distributions()
276291
assert len(dists) == 0
277292

278293
@patch('pip._vendor.pkg_resources.working_set', workingset_freeze)
279294
def test_freeze_excludes(self, mock_dist_is_editable,
280295
mock_dist_is_local,
281-
mock_dist_in_usersite):
296+
mock_dist_in_usersite,
297+
mock_dist_in_curr_dir):
282298
mock_dist_is_editable.side_effect = self.dist_is_editable
283299
mock_dist_is_local.side_effect = self.dist_is_local
284300
mock_dist_in_usersite.side_effect = self.dist_in_usersite
301+
mock_dist_in_curr_dir.side_effect = self.dist_in_curr_dir
285302
dists = get_installed_distributions(
286303
skip=('setuptools', 'pip', 'distribute'))
287304
assert len(dists) == 0

0 commit comments

Comments
 (0)