Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit581b894

Browse files
committed
Ignore PermissionError when checking cwd during import
On macOS `getcwd(3)` can return EACCES if a path component isn't readable,resulting in PermissionError. `PathFinder.find_spec()` now catches these andignores them - the same treatment as a missing/deleted cwd.Introduces 2 new `test.support.os_helper` context managers- `save_mode(path, ...)` - restores the mode of a path on exit- `save_cwd(...)` - restores the current directory on exitUnlike `change_cwd(path)` (which always performs a `chdir(path)`),`save_cwd()` allows the code inside the `with` block to control this. The newcontext manager just restores the original working directory afterward.This is allows finer control of exception handling and robust environmentrestoration across platforms in `FinderTests.test_permission_error_cwd()`.
1 parent2762c6c commit581b894

File tree

5 files changed

+83
-6
lines changed

5 files changed

+83
-6
lines changed

‎Doc/reference/import.rst‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -871,10 +871,10 @@ module.
871871

872872
The current working directory -- denoted by an empty string -- is handled
873873
slightly differently from other entries on:data:`sys.path`. First, if the
874-
current working directory is found to not exist, no value is stored in
875-
:data:`sys.path_importer_cache`. Second, the value for the current working
876-
directory is looked up fresh for each module lookup. Third, the path used for
877-
:data:`sys.path_importer_cache` and returned by
874+
current working directorycannot be determined oris found to not exist, no
875+
value is stored in:data:`sys.path_importer_cache`. Second, the value for the
876+
current workingdirectory is looked up fresh for each module lookup. Third,
877+
the path used for:data:`sys.path_importer_cache` and returned by
878878
:meth:`importlib.machinery.PathFinder.find_spec` will be the actual current
879879
working directory and not the empty string.
880880

‎Lib/importlib/_bootstrap_external.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1506,7 +1506,7 @@ def _path_importer_cache(cls, path):
15061506
ifpath=='':
15071507
try:
15081508
path=_os.getcwd()
1509-
exceptFileNotFoundError:
1509+
except(FileNotFoundError,PermissionError):
15101510
# Don't cache the failure as the cwd can easily change to
15111511
# a valid directory later on.
15121512
returnNone

‎Lib/test/support/os_helper.py‎

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,33 @@ def skip_unless_working_chmod(test):
294294
returntestifokelseunittest.skip(msg)(test)
295295

296296

297+
@contextlib.contextmanager
298+
defsave_mode(path,*,quiet=False):
299+
"""Context manager that restores the mode (permissions) of path on exit.
300+
301+
Arguments:
302+
303+
path: Path of the file to restore mode of.
304+
305+
quiet: if False (the default), the context manager raises an exception
306+
on error. Otherwise, it issues only a warning and keeps the current
307+
working directory the same.
308+
309+
"""
310+
saved_mode=os.stat(path)
311+
try:
312+
yield
313+
finally:
314+
try:
315+
os.chmod(path,saved_mode.st_mode)
316+
exceptOSErrorasexc:
317+
ifnotquiet:
318+
raise
319+
warnings.warn(f'tests may fail, unable to restore the mode of '
320+
f'{path!r} to{saved_mode.st_mode}:{exc}',
321+
RuntimeWarning,stacklevel=3)
322+
323+
297324
# Check whether the current effective user has the capability to override
298325
# DAC (discretionary access control). Typically user root is able to
299326
# bypass file read, write, and execute permission checks. The capability
@@ -508,9 +535,36 @@ def temp_dir(path=None, quiet=False):
508535
rmtree(path)
509536

510537

538+
@contextlib.contextmanager
539+
defsave_cwd(*,quiet=False):
540+
"""Return a context manager that restores the current working directory on
541+
exit.
542+
543+
Arguments:
544+
545+
quiet: if False (the default), the context manager raises an exception
546+
on error. Otherwise, it issues only a warning and keeps the current
547+
working directory the same.
548+
549+
"""
550+
saved_dir=os.getcwd()
551+
try:
552+
yield
553+
finally:
554+
try:
555+
os.chdir(saved_dir)
556+
exceptOSErrorasexc:
557+
ifnotquiet:
558+
raise
559+
warnings.warn(f'tests may fail, unable to restore the current '
560+
f'working directory to{saved_dir!r}:{exc}',
561+
RuntimeWarning,stacklevel=3)
562+
563+
511564
@contextlib.contextmanager
512565
defchange_cwd(path,quiet=False):
513-
"""Return a context manager that changes the current working directory.
566+
"""Return a context manager that changes the current working directory on
567+
entry, and restores it on exit.
514568
515569
Arguments:
516570

‎Lib/test/test_importlib/import_/test_path.py‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
fromtest.supportimportos_helper
12
fromtest.test_importlibimportutil
23

34
importlib=util.import_importlib('importlib')
@@ -153,6 +154,25 @@ def test_deleted_cwd(self):
153154
# Do not want FileNotFoundError raised.
154155
self.assertIsNone(self.machinery.PathFinder.find_spec('whatever'))
155156

157+
@os_helper.skip_unless_working_chmod
158+
deftest_permission_error_cwd(self):
159+
# gh-115911
160+
with (
161+
os_helper.temp_dir()asnew_dir,
162+
os_helper.save_mode(new_dir),
163+
os_helper.save_cwd(),
164+
util.import_state(path=['']),
165+
):
166+
os.chdir(new_dir)
167+
try:
168+
os.chmod(new_dir,0o000)
169+
exceptOSError:
170+
self.skipTest("platform does not allow "
171+
"changing mode of the cwd")
172+
173+
# Do not want PermissionError raised.
174+
self.assertIsNone(self.machinery.PathFinder.find_spec('whatever'))
175+
156176
deftest_invalidate_caches_finders(self):
157177
# Finders with an invalidate_caches() method have it called.
158178
classFakeFinder:
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
If the current working directory cannot be determined due to permissions,
2+
then import will no longer raise:exc:`PermissionError`. Patch by Alex
3+
Willmer.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp