Skip to content

Commit 8fc8c45

Browse files
[3.9] gh-113659: Skip hidden .pth files (GH-113660) (GH-114146)
(cherry picked from commit 74208ed) Co-authored-by: Łukasz Langa <[email protected]>
1 parent dd068ea commit 8fc8c45

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
@@ -16,6 +16,7 @@
1616
import os
1717
import re
1818
import shutil
19+
import stat
1920
import subprocess
2021
import sys
2122
import sysconfig
@@ -185,6 +186,44 @@ def test_addsitedir(self):
185186
finally:
186187
pth_file.cleanup()
187188

189+
def test_addsitedir_dotfile(self):
190+
pth_file = PthFile('.dotfile')
191+
pth_file.cleanup(prep=True)
192+
try:
193+
pth_file.create()
194+
site.addsitedir(pth_file.base_dir, set())
195+
self.assertNotIn(site.makepath(pth_file.good_dir_path)[0], sys.path)
196+
self.assertIn(pth_file.base_dir, sys.path)
197+
finally:
198+
pth_file.cleanup()
199+
200+
@unittest.skipUnless(hasattr(os, 'chflags'), 'test needs os.chflags()')
201+
def test_addsitedir_hidden_flags(self):
202+
pth_file = PthFile()
203+
pth_file.cleanup(prep=True)
204+
try:
205+
pth_file.create()
206+
st = os.stat(pth_file.file_path)
207+
os.chflags(pth_file.file_path, st.st_flags | stat.UF_HIDDEN)
208+
site.addsitedir(pth_file.base_dir, set())
209+
self.assertNotIn(site.makepath(pth_file.good_dir_path)[0], sys.path)
210+
self.assertIn(pth_file.base_dir, sys.path)
211+
finally:
212+
pth_file.cleanup()
213+
214+
@unittest.skipUnless(sys.platform == 'win32', 'test needs Windows')
215+
def test_addsitedir_hidden_file_attribute(self):
216+
pth_file = PthFile()
217+
pth_file.cleanup(prep=True)
218+
try:
219+
pth_file.create()
220+
subprocess.check_call(['attrib', '+H', pth_file.file_path])
221+
site.addsitedir(pth_file.base_dir, set())
222+
self.assertNotIn(site.makepath(pth_file.good_dir_path)[0], sys.path)
223+
self.assertIn(pth_file.base_dir, sys.path)
224+
finally:
225+
pth_file.cleanup()
226+
188227
# This tests _getuserbase, hence the double underline
189228
# to distinguish from a test for getuserbase
190229
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)