Skip to content

Commit 1cef58f

Browse files
committed
os: update Lib
1 parent 8ac22a7 commit 1cef58f

File tree

1 file changed

+74
-63
lines changed

1 file changed

+74
-63
lines changed

Lib/os.py

Lines changed: 74 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,15 @@
2828

2929
from _collections_abc import _check_methods
3030

31+
GenericAlias = type(list[int])
32+
3133
_names = sys.builtin_module_names
3234

3335
# Note: more names are added to __all__ later.
3436
__all__ = ["altsep", "curdir", "pardir", "sep", "pathsep", "linesep",
3537
"defpath", "name", "path", "devnull", "SEEK_SET", "SEEK_CUR",
3638
"SEEK_END", "fsencode", "fsdecode", "get_exec_path", "fdopen",
37-
"popen", "extsep"]
39+
"extsep"]
3840

3941
def _exists(name):
4042
return name in globals()
@@ -336,7 +338,10 @@ def walk(top, topdown=True, onerror=None, followlinks=False):
336338
dirs.remove('CVS') # don't visit CVS directories
337339
338340
"""
339-
top = fspath(top)
341+
sys.audit("os.walk", top, topdown, onerror, followlinks)
342+
return _walk(fspath(top), topdown, onerror, followlinks)
343+
344+
def _walk(top, topdown, onerror, followlinks):
340345
dirs = []
341346
nondirs = []
342347
walk_dirs = []
@@ -410,11 +415,11 @@ def walk(top, topdown=True, onerror=None, followlinks=False):
410415
# the caller can replace the directory entry during the "yield"
411416
# above.
412417
if followlinks or not islink(new_path):
413-
yield from walk(new_path, topdown, onerror, followlinks)
418+
yield from _walk(new_path, topdown, onerror, followlinks)
414419
else:
415420
# Recurse into sub-directories
416421
for new_path in walk_dirs:
417-
yield from walk(new_path, topdown, onerror, followlinks)
422+
yield from _walk(new_path, topdown, onerror, followlinks)
418423
# Yield after recursion if going bottom up
419424
yield top, dirs, nondirs
420425

@@ -455,8 +460,8 @@ def fwalk(top=".", topdown=True, onerror=None, *, follow_symlinks=False, dir_fd=
455460
if 'CVS' in dirs:
456461
dirs.remove('CVS') # don't visit CVS directories
457462
"""
458-
if not isinstance(top, int) or not hasattr(top, '__index__'):
459-
top = fspath(top)
463+
sys.audit("os.fwalk", top, topdown, onerror, follow_symlinks, dir_fd)
464+
top = fspath(top)
460465
# Note: To guard against symlink races, we use the standard
461466
# lstat()/open()/fstat() trick.
462467
if not follow_symlinks:
@@ -654,17 +659,15 @@ def get_exec_path(env=None):
654659
return path_list.split(pathsep)
655660

656661

657-
# Change environ to automatically call putenv(), unsetenv if they exist.
658-
from _collections_abc import MutableMapping
662+
# Change environ to automatically call putenv() and unsetenv()
663+
from _collections_abc import MutableMapping, Mapping
659664

660665
class _Environ(MutableMapping):
661-
def __init__(self, data, encodekey, decodekey, encodevalue, decodevalue, putenv, unsetenv):
666+
def __init__(self, data, encodekey, decodekey, encodevalue, decodevalue):
662667
self.encodekey = encodekey
663668
self.decodekey = decodekey
664669
self.encodevalue = encodevalue
665670
self.decodevalue = decodevalue
666-
self.putenv = putenv
667-
self.unsetenv = unsetenv
668671
self._data = data
669672

670673
def __getitem__(self, key):
@@ -678,12 +681,12 @@ def __getitem__(self, key):
678681
def __setitem__(self, key, value):
679682
key = self.encodekey(key)
680683
value = self.encodevalue(value)
681-
self.putenv(key, value)
684+
putenv(key, value)
682685
self._data[key] = value
683686

684687
def __delitem__(self, key):
685688
encodedkey = self.encodekey(key)
686-
self.unsetenv(encodedkey)
689+
unsetenv(encodedkey)
687690
try:
688691
del self._data[encodedkey]
689692
except KeyError:
@@ -700,9 +703,11 @@ def __len__(self):
700703
return len(self._data)
701704

702705
def __repr__(self):
703-
return 'environ({{{}}})'.format(', '.join(
704-
('{!r}: {!r}'.format(self.decodekey(key), self.decodevalue(value))
705-
for key, value in self._data.items())))
706+
formatted_items = ", ".join(
707+
f"{self.decodekey(key)!r}: {self.decodevalue(value)!r}"
708+
for key, value in self._data.items()
709+
)
710+
return f"environ({{{formatted_items}}})"
706711

707712
def copy(self):
708713
return dict(self)
@@ -712,21 +717,23 @@ def setdefault(self, key, value):
712717
self[key] = value
713718
return self[key]
714719

715-
try:
716-
_putenv = putenv
717-
except NameError:
718-
_putenv = lambda key, value: None
719-
else:
720-
if "putenv" not in __all__:
721-
__all__.append("putenv")
720+
def __ior__(self, other):
721+
self.update(other)
722+
return self
722723

723-
try:
724-
_unsetenv = unsetenv
725-
except NameError:
726-
_unsetenv = lambda key: _putenv(key, "")
727-
else:
728-
if "unsetenv" not in __all__:
729-
__all__.append("unsetenv")
724+
def __or__(self, other):
725+
if not isinstance(other, Mapping):
726+
return NotImplemented
727+
new = dict(self)
728+
new.update(other)
729+
return new
730+
731+
def __ror__(self, other):
732+
if not isinstance(other, Mapping):
733+
return NotImplemented
734+
new = dict(other)
735+
new.update(self)
736+
return new
730737

731738
def _createenviron():
732739
if name == 'nt':
@@ -755,8 +762,7 @@ def decode(value):
755762
data = environ
756763
return _Environ(data,
757764
encodekey, decode,
758-
encode, decode,
759-
_putenv, _unsetenv)
765+
encode, decode)
760766

761767
# unicode environ
762768
environ = _createenviron()
@@ -781,8 +787,7 @@ def _check_bytes(value):
781787
# bytes environ
782788
environb = _Environ(environ._data,
783789
_check_bytes, bytes,
784-
_check_bytes, bytes,
785-
_putenv, _unsetenv)
790+
_check_bytes, bytes)
786791
del _check_bytes
787792

788793
def getenvb(key, default=None):
@@ -862,12 +867,8 @@ def _spawnvef(mode, file, args, env, func):
862867
wpid, sts = waitpid(pid, 0)
863868
if WIFSTOPPED(sts):
864869
continue
865-
elif WIFSIGNALED(sts):
866-
return -WTERMSIG(sts)
867-
elif WIFEXITED(sts):
868-
return WEXITSTATUS(sts)
869-
else:
870-
raise OSError("Not stopped, signaled or exited???")
870+
871+
return waitstatus_to_exitcode(sts)
871872

872873
def spawnv(mode, file, args):
873874
"""spawnv(mode, file, args) -> integer
@@ -969,28 +970,30 @@ def spawnlpe(mode, file, *args):
969970

970971
__all__.extend(["spawnlp", "spawnlpe"])
971972

972-
973+
# VxWorks has no user space shell provided. As a result, running
974+
# command in a shell can't be supported.
975+
if sys.platform != 'vxworks':
973976
# Supply os.popen()
974-
def popen(cmd, mode="r", buffering=-1):
975-
if not isinstance(cmd, str):
976-
raise TypeError("invalid cmd type (%s, expected string)" % type(cmd))
977-
if mode not in ("r", "w"):
978-
raise ValueError("invalid mode %r" % mode)
979-
if buffering == 0 or buffering is None:
980-
raise ValueError("popen() does not support unbuffered streams")
981-
import subprocess, io
982-
if mode == "r":
983-
proc = subprocess.Popen(cmd,
984-
shell=True,
985-
stdout=subprocess.PIPE,
986-
bufsize=buffering)
987-
return _wrap_close(io.TextIOWrapper(proc.stdout), proc)
988-
else:
989-
proc = subprocess.Popen(cmd,
990-
shell=True,
991-
stdin=subprocess.PIPE,
992-
bufsize=buffering)
993-
return _wrap_close(io.TextIOWrapper(proc.stdin), proc)
977+
def popen(cmd, mode="r", buffering=-1):
978+
if not isinstance(cmd, str):
979+
raise TypeError("invalid cmd type (%s, expected string)" % type(cmd))
980+
if mode not in ("r", "w"):
981+
raise ValueError("invalid mode %r" % mode)
982+
if buffering == 0 or buffering is None:
983+
raise ValueError("popen() does not support unbuffered streams")
984+
import subprocess, io
985+
if mode == "r":
986+
proc = subprocess.Popen(cmd,
987+
shell=True, text=True,
988+
stdout=subprocess.PIPE,
989+
bufsize=buffering)
990+
return _wrap_close(proc.stdout, proc)
991+
else:
992+
proc = subprocess.Popen(cmd,
993+
shell=True, text=True,
994+
stdin=subprocess.PIPE,
995+
bufsize=buffering)
996+
return _wrap_close(proc.stdin, proc)
994997

995998
# Helper for popen() -- a proxy for a file whose close waits for the process
996999
class _wrap_close:
@@ -1015,12 +1018,18 @@ def __getattr__(self, name):
10151018
def __iter__(self):
10161019
return iter(self._stream)
10171020

1021+
__all__.append("popen")
1022+
10181023
# Supply os.fdopen()
1019-
def fdopen(fd, *args, **kwargs):
1024+
def fdopen(fd, mode="r", buffering=-1, encoding=None, *args, **kwargs):
10201025
if not isinstance(fd, int):
10211026
raise TypeError("invalid fd type (%s, expected integer)" % type(fd))
10221027
import io
1023-
return io.open(fd, *args, **kwargs)
1028+
if "b" not in mode:
1029+
# TODO: RUSTPYTHON (module 'io' has no attribute 'text_encoding')
1030+
# encoding = io.text_encoding(encoding)
1031+
pass
1032+
return io.open(fd, mode, buffering, encoding, *args, **kwargs)
10241033

10251034

10261035
# For testing purposes, make sure the function is available when the C
@@ -1076,6 +1085,8 @@ def __subclasshook__(cls, subclass):
10761085
return _check_methods(subclass, '__fspath__')
10771086
return NotImplemented
10781087

1088+
__class_getitem__ = classmethod(GenericAlias)
1089+
10791090

10801091
if name == 'nt':
10811092
class _AddedDllDirectory:

0 commit comments

Comments
 (0)