Skip to content

Commit 01845a1

Browse files
[3.8] gh-113659: Skip hidden .pth files (GH-113660) (GH-114147)
Skip .pth files with names starting with a dot or hidden file attribute. (cherry picked from commit 74208ed)
1 parent a911516 commit 01845a1

File tree

3 files changed

+50
-1
lines changed

3 files changed

+50
-1
lines changed

Lib/site.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
import builtins
7575
import _sitebuiltins
7676
import io
77+
import stat
7778

7879
# Prefixes for site-packages; add additional prefixes like /usr/local here
7980
PREFIXES = [sys.prefix, sys.exec_prefix]
@@ -156,6 +157,13 @@ def addpackage(sitedir, name, known_paths):
156157
else:
157158
reset = False
158159
fullname = os.path.join(sitedir, name)
160+
try:
161+
st = os.lstat(fullname)
162+
except OSError:
163+
return
164+
if ((getattr(st, 'st_flags', 0) & stat.UF_HIDDEN) or
165+
(getattr(st, 'st_file_attributes', 0) & stat.FILE_ATTRIBUTE_HIDDEN)):
166+
return
159167
try:
160168
f = io.TextIOWrapper(io.open_code(fullname))
161169
except OSError:
@@ -203,7 +211,8 @@ def addsitedir(sitedir, known_paths=None):
203211
names = os.listdir(sitedir)
204212
except OSError:
205213
return
206-
names = [name for name in names if name.endswith(".pth")]
214+
names = [name for name in names
215+
if name.endswith(".pth") and not name.startswith(".")]
207216
for name in sorted(names):
208217
addpackage(sitedir, name, known_paths)
209218
if reset:

Lib/test/test_site.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import urllib.request
1919
import urllib.error
2020
import shutil
21+
import stat
2122
import subprocess
2223
import sysconfig
2324
import tempfile
@@ -182,6 +183,44 @@ def test_addsitedir(self):
182183
finally:
183184
pth_file.cleanup()
184185

186+
def test_addsitedir_dotfile(self):
187+
pth_file = PthFile('.dotfile')
188+
pth_file.cleanup(prep=True)
189+
try:
190+
pth_file.create()
191+
site.addsitedir(pth_file.base_dir, set())
192+
self.assertNotIn(site.makepath(pth_file.good_dir_path)[0], sys.path)
193+
self.assertIn(pth_file.base_dir, sys.path)
194+
finally:
195+
pth_file.cleanup()
196+
197+
@unittest.skipUnless(hasattr(os, 'chflags'), 'test needs os.chflags()')
198+
def test_addsitedir_hidden_flags(self):
199+
pth_file = PthFile()
200+
pth_file.cleanup(prep=True)
201+
try:
202+
pth_file.create()
203+
st = os.stat(pth_file.file_path)
204+
os.chflags(pth_file.file_path, st.st_flags | stat.UF_HIDDEN)
205+
site.addsitedir(pth_file.base_dir, set())
206+
self.assertNotIn(site.makepath(pth_file.good_dir_path)[0], sys.path)
207+
self.assertIn(pth_file.base_dir, sys.path)
208+
finally:
209+
pth_file.cleanup()
210+
211+
@unittest.skipUnless(sys.platform == 'win32', 'test needs Windows')
212+
def test_addsitedir_hidden_file_attribute(self):
213+
pth_file = PthFile()
214+
pth_file.cleanup(prep=True)
215+
try:
216+
pth_file.create()
217+
subprocess.check_call(['attrib', '+H', pth_file.file_path])
218+
site.addsitedir(pth_file.base_dir, set())
219+
self.assertNotIn(site.makepath(pth_file.good_dir_path)[0], sys.path)
220+
self.assertIn(pth_file.base_dir, sys.path)
221+
finally:
222+
pth_file.cleanup()
223+
185224
# This tests _getuserbase, hence the double underline
186225
# to distinguish from a test for getuserbase
187226
def test__getuserbase(self):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Skip ``.pth`` files with names starting with a dot or hidden file attribute.

0 commit comments

Comments
 (0)