Skip to content

Commit 4863cac

Browse files
Add test.support.os_helper @ 3.13.5
1 parent f402dee commit 4863cac

File tree

1 file changed

+58
-32
lines changed

1 file changed

+58
-32
lines changed

Lib/test/support/os_helper.py

Lines changed: 58 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import collections.abc
22
import contextlib
33
import errno
4+
import logging
45
import os
56
import re
67
import stat
@@ -10,7 +11,6 @@
1011
import unittest
1112
import warnings
1213

13-
# From CPython 3.13.5
1414
from test import support
1515

1616

@@ -23,8 +23,8 @@
2323

2424
# TESTFN_UNICODE is a non-ascii filename
2525
TESTFN_UNICODE = TESTFN_ASCII + "-\xe0\xf2\u0258\u0141\u011f"
26-
if sys.platform == 'darwin':
27-
# In Mac OS X's VFS API file names are, by definition, canonically
26+
if support.is_apple:
27+
# On Apple's VFS API file names are, by definition, canonically
2828
# decomposed Unicode, encoded using UTF-8. See QA1173:
2929
# http://developer.apple.com/mac/library/qa/qa2001/qa1173.html
3030
import unicodedata
@@ -49,8 +49,8 @@
4949
'encoding (%s). Unicode filename tests may not be effective'
5050
% (TESTFN_UNENCODABLE, sys.getfilesystemencoding()))
5151
TESTFN_UNENCODABLE = None
52-
# macOS and Emscripten deny unencodable filenames (invalid utf-8)
53-
elif sys.platform not in {'darwin', 'emscripten', 'wasi'}:
52+
# Apple and Emscripten deny unencodable filenames (invalid utf-8)
53+
elif not support.is_apple and sys.platform not in {"emscripten", "wasi"}:
5454
try:
5555
# ascii and utf-8 cannot encode the byte 0xff
5656
b'\xff'.decode(sys.getfilesystemencoding())
@@ -199,10 +199,8 @@ def skip_unless_symlink(test):
199199
return test if ok else unittest.skip(msg)(test)
200200

201201

202-
# From CPython 3.13.5
203202
_can_hardlink = None
204203

205-
# From CPython 3.13.5
206204
def can_hardlink():
207205
global _can_hardlink
208206
if _can_hardlink is None:
@@ -212,7 +210,6 @@ def can_hardlink():
212210
return _can_hardlink
213211

214212

215-
# From CPython 3.13.5
216213
def skip_unless_hardlink(test):
217214
ok = can_hardlink()
218215
msg = "requires hardlink support"
@@ -268,15 +265,15 @@ def can_chmod():
268265
global _can_chmod
269266
if _can_chmod is not None:
270267
return _can_chmod
271-
if not hasattr(os, "chown"):
268+
if not hasattr(os, "chmod"):
272269
_can_chmod = False
273270
return _can_chmod
274271
try:
275272
with open(TESTFN, "wb") as f:
276273
try:
277-
os.chmod(TESTFN, 0o777)
274+
os.chmod(TESTFN, 0o555)
278275
mode1 = os.stat(TESTFN).st_mode
279-
os.chmod(TESTFN, 0o666)
276+
os.chmod(TESTFN, 0o777)
280277
mode2 = os.stat(TESTFN).st_mode
281278
except OSError as e:
282279
can = False
@@ -323,6 +320,10 @@ def can_dac_override():
323320
else:
324321
_can_dac_override = True
325322
finally:
323+
try:
324+
os.chmod(TESTFN, 0o700)
325+
except OSError:
326+
pass
326327
unlink(TESTFN)
327328

328329
return _can_dac_override
@@ -378,8 +379,12 @@ def _waitfor(func, pathname, waitall=False):
378379
# Increase the timeout and try again
379380
time.sleep(timeout)
380381
timeout *= 2
381-
warnings.warn('tests may fail, delete still pending for ' + pathname,
382-
RuntimeWarning, stacklevel=4)
382+
logging.getLogger(__name__).warning(
383+
'tests may fail, delete still pending for %s',
384+
pathname,
385+
stack_info=True,
386+
stacklevel=4,
387+
)
383388

384389
def _unlink(filename):
385390
_waitfor(os.unlink, filename)
@@ -494,9 +499,14 @@ def temp_dir(path=None, quiet=False):
494499
except OSError as exc:
495500
if not quiet:
496501
raise
497-
warnings.warn(f'tests may fail, unable to create '
498-
f'temporary directory {path!r}: {exc}',
499-
RuntimeWarning, stacklevel=3)
502+
logging.getLogger(__name__).warning(
503+
"tests may fail, unable to create temporary directory %r: %s",
504+
path,
505+
exc,
506+
exc_info=exc,
507+
stack_info=True,
508+
stacklevel=3,
509+
)
500510
if dir_created:
501511
pid = os.getpid()
502512
try:
@@ -527,9 +537,15 @@ def change_cwd(path, quiet=False):
527537
except OSError as exc:
528538
if not quiet:
529539
raise
530-
warnings.warn(f'tests may fail, unable to change the current working '
531-
f'directory to {path!r}: {exc}',
532-
RuntimeWarning, stacklevel=3)
540+
logging.getLogger(__name__).warning(
541+
'tests may fail, unable to change the current working directory '
542+
'to %r: %s',
543+
path,
544+
exc,
545+
exc_info=exc,
546+
stack_info=True,
547+
stacklevel=3,
548+
)
533549
try:
534550
yield os.getcwd()
535551
finally:
@@ -612,11 +628,18 @@ def __fspath__(self):
612628
def fd_count():
613629
"""Count the number of open file descriptors.
614630
"""
615-
if sys.platform.startswith(('linux', 'freebsd', 'emscripten')):
631+
if sys.platform.startswith(('linux', 'android', 'freebsd', 'emscripten')):
632+
fd_path = "/proc/self/fd"
633+
elif support.is_apple:
634+
fd_path = "/dev/fd"
635+
else:
636+
fd_path = None
637+
638+
if fd_path is not None:
616639
try:
617-
names = os.listdir("/proc/self/fd")
640+
names = os.listdir(fd_path)
618641
# Subtract one because listdir() internally opens a file
619-
# descriptor to list the content of the /proc/self/fd/ directory.
642+
# descriptor to list the content of the directory.
620643
return len(names) - 1
621644
except FileNotFoundError:
622645
pass
@@ -686,9 +709,10 @@ def temp_umask(umask):
686709

687710

688711
class EnvironmentVarGuard(collections.abc.MutableMapping):
712+
"""Class to help protect the environment variable properly.
689713
690-
"""Class to help protect the environment variable properly. Can be used as
691-
a context manager."""
714+
Can be used as a context manager.
715+
"""
692716

693717
def __init__(self):
694718
self._environ = os.environ
@@ -722,7 +746,6 @@ def __len__(self):
722746
def set(self, envvar, value):
723747
self[envvar] = value
724748

725-
# From CPython 3.13.5
726749
def unset(self, envvar, /, *envvars):
727750
"""Unset one or more environment variables."""
728751
for ev in (envvar, *envvars):
@@ -746,13 +769,16 @@ def __exit__(self, *ignore_exc):
746769

747770

748771
try:
749-
import ctypes
750-
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
751-
752-
ERROR_FILE_NOT_FOUND = 2
753-
DDD_REMOVE_DEFINITION = 2
754-
DDD_EXACT_MATCH_ON_REMOVE = 4
755-
DDD_NO_BROADCAST_SYSTEM = 8
772+
if support.MS_WINDOWS:
773+
import ctypes
774+
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
775+
776+
ERROR_FILE_NOT_FOUND = 2
777+
DDD_REMOVE_DEFINITION = 2
778+
DDD_EXACT_MATCH_ON_REMOVE = 4
779+
DDD_NO_BROADCAST_SYSTEM = 8
780+
else:
781+
raise AttributeError
756782
except (ImportError, AttributeError):
757783
def subst_drive(path):
758784
raise unittest.SkipTest('ctypes or kernel32 is not available')

0 commit comments

Comments
 (0)