1
1
import collections .abc
2
2
import contextlib
3
3
import errno
4
+ import logging
4
5
import os
5
6
import re
6
7
import stat
10
11
import unittest
11
12
import warnings
12
13
13
- # From CPython 3.13.5
14
14
from test import support
15
15
16
16
23
23
24
24
# TESTFN_UNICODE is a non-ascii filename
25
25
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
28
28
# decomposed Unicode, encoded using UTF-8. See QA1173:
29
29
# http://developer.apple.com/mac/library/qa/qa2001/qa1173.html
30
30
import unicodedata
49
49
'encoding (%s). Unicode filename tests may not be effective'
50
50
% (TESTFN_UNENCODABLE , sys .getfilesystemencoding ()))
51
51
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" }:
54
54
try :
55
55
# ascii and utf-8 cannot encode the byte 0xff
56
56
b'\xff ' .decode (sys .getfilesystemencoding ())
@@ -199,10 +199,8 @@ def skip_unless_symlink(test):
199
199
return test if ok else unittest .skip (msg )(test )
200
200
201
201
202
- # From CPython 3.13.5
203
202
_can_hardlink = None
204
203
205
- # From CPython 3.13.5
206
204
def can_hardlink ():
207
205
global _can_hardlink
208
206
if _can_hardlink is None :
@@ -212,7 +210,6 @@ def can_hardlink():
212
210
return _can_hardlink
213
211
214
212
215
- # From CPython 3.13.5
216
213
def skip_unless_hardlink (test ):
217
214
ok = can_hardlink ()
218
215
msg = "requires hardlink support"
@@ -268,15 +265,15 @@ def can_chmod():
268
265
global _can_chmod
269
266
if _can_chmod is not None :
270
267
return _can_chmod
271
- if not hasattr (os , "chown " ):
268
+ if not hasattr (os , "chmod " ):
272
269
_can_chmod = False
273
270
return _can_chmod
274
271
try :
275
272
with open (TESTFN , "wb" ) as f :
276
273
try :
277
- os .chmod (TESTFN , 0o777 )
274
+ os .chmod (TESTFN , 0o555 )
278
275
mode1 = os .stat (TESTFN ).st_mode
279
- os .chmod (TESTFN , 0o666 )
276
+ os .chmod (TESTFN , 0o777 )
280
277
mode2 = os .stat (TESTFN ).st_mode
281
278
except OSError as e :
282
279
can = False
@@ -323,6 +320,10 @@ def can_dac_override():
323
320
else :
324
321
_can_dac_override = True
325
322
finally :
323
+ try :
324
+ os .chmod (TESTFN , 0o700 )
325
+ except OSError :
326
+ pass
326
327
unlink (TESTFN )
327
328
328
329
return _can_dac_override
@@ -378,8 +379,12 @@ def _waitfor(func, pathname, waitall=False):
378
379
# Increase the timeout and try again
379
380
time .sleep (timeout )
380
381
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
+ )
383
388
384
389
def _unlink (filename ):
385
390
_waitfor (os .unlink , filename )
@@ -494,9 +499,14 @@ def temp_dir(path=None, quiet=False):
494
499
except OSError as exc :
495
500
if not quiet :
496
501
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
+ )
500
510
if dir_created :
501
511
pid = os .getpid ()
502
512
try :
@@ -527,9 +537,15 @@ def change_cwd(path, quiet=False):
527
537
except OSError as exc :
528
538
if not quiet :
529
539
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
+ )
533
549
try :
534
550
yield os .getcwd ()
535
551
finally :
@@ -612,11 +628,18 @@ def __fspath__(self):
612
628
def fd_count ():
613
629
"""Count the number of open file descriptors.
614
630
"""
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 :
616
639
try :
617
- names = os .listdir ("/proc/self/fd" )
640
+ names = os .listdir (fd_path )
618
641
# 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.
620
643
return len (names ) - 1
621
644
except FileNotFoundError :
622
645
pass
@@ -686,9 +709,10 @@ def temp_umask(umask):
686
709
687
710
688
711
class EnvironmentVarGuard (collections .abc .MutableMapping ):
712
+ """Class to help protect the environment variable properly.
689
713
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
+ """
692
716
693
717
def __init__ (self ):
694
718
self ._environ = os .environ
@@ -722,7 +746,6 @@ def __len__(self):
722
746
def set (self , envvar , value ):
723
747
self [envvar ] = value
724
748
725
- # From CPython 3.13.5
726
749
def unset (self , envvar , / , * envvars ):
727
750
"""Unset one or more environment variables."""
728
751
for ev in (envvar , * envvars ):
@@ -746,13 +769,16 @@ def __exit__(self, *ignore_exc):
746
769
747
770
748
771
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
756
782
except (ImportError , AttributeError ):
757
783
def subst_drive (path ):
758
784
raise unittest .SkipTest ('ctypes or kernel32 is not available' )
0 commit comments