1r"""OS routines for NT or Posix depending on what system we're on. 2 3This exports: 4 - all functions from posix or nt, e.g. unlink, stat, etc. 5 - os.path is either posixpath or ntpath 6 - os.name is either 'posix' or 'nt' 7 - os.curdir is a string representing the current directory (always '.') 8 - os.pardir is a string representing the parent directory (always '..') 9 - os.sep is the (or a most common) pathname separator ('/' or '\\') 10 - os.extsep is the extension separator (always '.') 11 - os.altsep is the alternate pathname separator (None or '/') 12 - os.pathsep is the component separator used in $PATH etc 13 - os.linesep is the line separator in text files ('\r' or '\n' or '\r\n') 14 - os.defpath is the default search path for executables 15 - os.devnull is the file path of the null device ('/dev/null', etc.) 16 17Programs that import and use 'os' stand a better chance of being 18portable between different platforms. Of course, they must then 19only use functions that are defined by all platforms (e.g., unlink 20and opendir), and leave all pathname manipulation to os.path 21(e.g., split and join). 22""" 23 24#' 25import abc 26import sys 27import stat as st 28 29from _collections_abc import _check_methods 30 31GenericAlias = type(list[int]) 32 33_names = sys.builtin_module_names 34 35# Note: more names are added to __all__ later. 36__all__ = ["altsep", "curdir", "pardir", "sep", "pathsep", "linesep", 37 "defpath", "name", "path", "devnull", "SEEK_SET", "SEEK_CUR", 38 "SEEK_END", "fsencode", "fsdecode", "get_exec_path", "fdopen", 39 "extsep"] 40 41def _exists(name): 42 return name in globals() 43 44def _get_exports_list(module): 45 try: 46 return list(module.__all__) 47 except AttributeError: 48 return [n for n in dir(module) if n[0] != '_'] 49 50# Any new dependencies of the os module and/or changes in path separator 51# requires updating importlib as well. 52if 'posix' in _names: 53 name = 'posix' 54 linesep = '\n' 55 from posix import * 56 try: 57 from posix import _exit 58 __all__.append('_exit') 59 except ImportError: 60 pass 61 import posixpath as path 62 63 try: 64 from posix import _have_functions 65 except ImportError: 66 pass 67 68 import posix 69 __all__.extend(_get_exports_list(posix)) 70 del posix 71 72elif 'nt' in _names: 73 name = 'nt' 74 linesep = '\r\n' 75 from nt import * 76 try: 77 from nt import _exit 78 __all__.append('_exit') 79 except ImportError: 80 pass 81 import ntpath as path 82 83 import nt 84 __all__.extend(_get_exports_list(nt)) 85 del nt 86 87 try: 88 from nt import _have_functions 89 except ImportError: 90 pass 91 92else: 93 raise ImportError('no os specific module found') 94 95sys.modules['os.path'] = path 96from os.path import (curdir, pardir, sep, pathsep, defpath, extsep, altsep, 97 devnull) 98 99del _names 100 101 102if _exists("_have_functions"): 103 _globals = globals() 104 def _add(str, fn): 105 if (fn in _globals) and (str in _have_functions): 106 _set.add(_globals[fn]) 107 108 _set = set() 109 _add("HAVE_FACCESSAT", "access") 110 _add("HAVE_FCHMODAT", "chmod") 111 _add("HAVE_FCHOWNAT", "chown") 112 _add("HAVE_FSTATAT", "stat") 113 _add("HAVE_FUTIMESAT", "utime") 114 _add("HAVE_LINKAT", "link") 115 _add("HAVE_MKDIRAT", "mkdir") 116 _add("HAVE_MKFIFOAT", "mkfifo") 117 _add("HAVE_MKNODAT", "mknod") 118 _add("HAVE_OPENAT", "open") 119 _add("HAVE_READLINKAT", "readlink") 120 _add("HAVE_RENAMEAT", "rename") 121 _add("HAVE_SYMLINKAT", "symlink") 122 _add("HAVE_UNLINKAT", "unlink") 123 _add("HAVE_UNLINKAT", "rmdir") 124 _add("HAVE_UTIMENSAT", "utime") 125 supports_dir_fd = _set 126 127 _set = set() 128 _add("HAVE_FACCESSAT", "access") 129 supports_effective_ids = _set 130 131 _set = set() 132 _add("HAVE_FCHDIR", "chdir") 133 _add("HAVE_FCHMOD", "chmod") 134 _add("MS_WINDOWS", "chmod") 135 _add("HAVE_FCHOWN", "chown") 136 _add("HAVE_FDOPENDIR", "listdir") 137 _add("HAVE_FDOPENDIR", "scandir") 138 _add("HAVE_FEXECVE", "execve") 139 _set.add(stat) # fstat always works 140 _add("HAVE_FTRUNCATE", "truncate") 141 _add("HAVE_FUTIMENS", "utime") 142 _add("HAVE_FUTIMES", "utime") 143 _add("HAVE_FPATHCONF", "pathconf") 144 if _exists("statvfs") and _exists("fstatvfs"): # mac os x10.3 145 _add("HAVE_FSTATVFS", "statvfs") 146 supports_fd = _set 147 148 _set = set() 149 _add("HAVE_FACCESSAT", "access") 150 # Some platforms don't support lchmod(). Often the function exists 151 # anyway, as a stub that always returns ENOSUP or perhaps EOPNOTSUPP. 152 # (No, I don't know why that's a good design.) ./configure will detect 153 # this and reject it--so HAVE_LCHMOD still won't be defined on such 154 # platforms. This is Very Helpful. 155 # 156 # However, sometimes platforms without a working lchmod() *do* have 157 # fchmodat(). (Examples: Linux kernel 3.2 with glibc 2.15, 158 # OpenIndiana 3.x.) And fchmodat() has a flag that theoretically makes 159 # it behave like lchmod(). So in theory it would be a suitable 160 # replacement for lchmod(). But when lchmod() doesn't work, fchmodat()'s 161 # flag doesn't work *either*. Sadly ./configure isn't sophisticated 162 # enough to detect this condition--it only determines whether or not 163 # fchmodat() minimally works. 164 # 165 # Therefore we simply ignore fchmodat() when deciding whether or not 166 # os.chmod supports follow_symlinks. Just checking lchmod() is 167 # sufficient. After all--if you have a working fchmodat(), your 168 # lchmod() almost certainly works too. 169 # 170 # _add("HAVE_FCHMODAT", "chmod") 171 _add("HAVE_FCHOWNAT", "chown") 172 _add("HAVE_FSTATAT", "stat") 173 _add("HAVE_LCHFLAGS", "chflags") 174 _add("HAVE_LCHMOD", "chmod") 175 _add("MS_WINDOWS", "chmod") 176 if _exists("lchown"): # mac os x10.3 177 _add("HAVE_LCHOWN", "chown") 178 _add("HAVE_LINKAT", "link") 179 _add("HAVE_LUTIMES", "utime") 180 _add("HAVE_LSTAT", "stat") 181 _add("HAVE_FSTATAT", "stat") 182 _add("HAVE_UTIMENSAT", "utime") 183 _add("MS_WINDOWS", "stat") 184 supports_follow_symlinks = _set 185 186 del _set 187 del _have_functions 188 del _globals 189 del _add 190 191 192# Python uses fixed values for the SEEK_ constants; they are mapped 193# to native constants if necessary in posixmodule.c 194# Other possible SEEK values are directly imported from posixmodule.c 195SEEK_SET = 0 196SEEK_CUR = 1 197SEEK_END = 2 198 199# Super directory utilities. 200# (Inspired by Eric Raymond; the doc strings are mostly his) 201 202def makedirs(name, mode=0o777, exist_ok=False): 203 """makedirs(name [, mode=0o777][, exist_ok=False]) 204 205 Super-mkdir; create a leaf directory and all intermediate ones. Works like 206 mkdir, except that any intermediate path segment (not just the rightmost) 207 will be created if it does not exist. If the target directory already 208 exists, raise an OSError if exist_ok is False. Otherwise no exception is 209 raised. This is recursive. 210 211 """ 212 head, tail = path.split(name) 213 if not tail: 214 head, tail = path.split(head) 215 if head and tail and not path.exists(head): 216 try: 217 makedirs(head, exist_ok=exist_ok) 218 except FileExistsError: 219 # Defeats race condition when another thread created the path 220 pass 221 cdir = curdir 222 if isinstance(tail, bytes): 223 cdir = bytes(curdir, 'ASCII') 224 if tail == cdir: # xxx/newdir/. exists if xxx/newdir exists 225 return 226 try: 227 mkdir(name, mode) 228 except OSError: 229 # Cannot rely on checking for EEXIST, since the operating system 230 # could give priority to other errors like EACCES or EROFS 231 if not exist_ok or not path.isdir(name): 232 raise 233 234def removedirs(name): 235 """removedirs(name) 236 237 Super-rmdir; remove a leaf directory and all empty intermediate 238 ones. Works like rmdir except that, if the leaf directory is 239 successfully removed, directories corresponding to rightmost path 240 segments will be pruned away until either the whole path is 241 consumed or an error occurs. Errors during this latter phase are 242 ignored -- they generally mean that a directory was not empty. 243 244 """ 245 rmdir(name) 246 head, tail = path.split(name) 247 if not tail: 248 head, tail = path.split(head) 249 while head and tail: 250 try: 251 rmdir(head) 252 except OSError: 253 break 254 head, tail = path.split(head) 255 256def renames(old, new): 257 """renames(old, new) 258 259 Super-rename; create directories as necessary and delete any left 260 empty. Works like rename, except creation of any intermediate 261 directories needed to make the new pathname good is attempted 262 first. After the rename, directories corresponding to rightmost 263 path segments of the old name will be pruned until either the 264 whole path is consumed or a nonempty directory is found. 265 266 Note: this function can fail with the new directory structure made 267 if you lack permissions needed to unlink the leaf directory or 268 file. 269 270 """ 271 head, tail = path.split(new) 272 if head and tail and not path.exists(head): 273 makedirs(head) 274 rename(old, new) 275 head, tail = path.split(old) 276 if head and tail: 277 try: 278 removedirs(head) 279 except OSError: 280 pass 281 282__all__.extend(["makedirs", "removedirs", "renames"]) 283 284# Private sentinel that makes walk() classify all symlinks and junctions as 285# regular files. 286_walk_symlinks_as_files = object() 287 288def walk(top, topdown=True, onerror=None, followlinks=False): 289 """Directory tree generator. 290 291 For each directory in the directory tree rooted at top (including top 292 itself, but excluding '.' and '..'), yields a 3-tuple 293 294 dirpath, dirnames, filenames 295 296 dirpath is a string, the path to the directory. dirnames is a list of 297 the names of the subdirectories in dirpath (including symlinks to directories, 298 and excluding '.' and '..'). 299 filenames is a list of the names of the non-directory files in dirpath. 300 Note that the names in the lists are just names, with no path components. 301 To get a full path (which begins with top) to a file or directory in 302 dirpath, do os.path.join(dirpath, name). 303 304 If optional arg 'topdown' is true or not specified, the triple for a 305 directory is generated before the triples for any of its subdirectories 306 (directories are generated top down). If topdown is false, the triple 307 for a directory is generated after the triples for all of its 308 subdirectories (directories are generated bottom up). 309 310 When topdown is true, the caller can modify the dirnames list in-place 311 (e.g., via del or slice assignment), and walk will only recurse into the 312 subdirectories whose names remain in dirnames; this can be used to prune the 313 search, or to impose a specific order of visiting. Modifying dirnames when 314 topdown is false has no effect on the behavior of os.walk(), since the 315 directories in dirnames have already been generated by the time dirnames 316 itself is generated. No matter the value of topdown, the list of 317 subdirectories is retrieved before the tuples for the directory and its 318 subdirectories are generated. 319 320 By default errors from the os.scandir() call are ignored. If 321 optional arg 'onerror' is specified, it should be a function; it 322 will be called with one argument, an OSError instance. It can 323 report the error to continue with the walk, or raise the exception 324 to abort the walk. Note that the filename is available as the 325 filename attribute of the exception object. 326 327 By default, os.walk does not follow symbolic links to subdirectories on 328 systems that support them. In order to get this functionality, set the 329 optional argument 'followlinks' to true. 330 331 Caution: if you pass a relative pathname for top, don't change the 332 current working directory between resumptions of walk. walk never 333 changes the current directory, and assumes that the client doesn't 334 either. 335 336 Example: 337 338 import os 339 from os.path import join, getsize 340 for root, dirs, files in os.walk('python/Lib/email'): 341 print(root, "consumes ") 342 print(sum(getsize(join(root, name)) for name in files), end=" ") 343 print("bytes in", len(files), "non-directory files") 344 if 'CVS' in dirs: 345 dirs.remove('CVS') # don't visit CVS directories 346 347 """ 348 sys.audit("os.walk", top, topdown, onerror, followlinks) 349 350 stack = [fspath(top)] 351 islink, join = path.islink, path.join 352 while stack: 353 top = stack.pop() 354 if isinstance(top, tuple): 355 yield top 356 continue 357 358 dirs = [] 359 nondirs = [] 360 walk_dirs = [] 361 362 # We may not have read permission for top, in which case we can't 363 # get a list of the files the directory contains. 364 # We suppress the exception here, rather than blow up for a 365 # minor reason when (say) a thousand readable directories are still 366 # left to visit. 367 try: 368 scandir_it = scandir(top) 369 except OSError as error: 370 if onerror is not None: 371 onerror(error) 372 continue 373 374 cont = False 375 with scandir_it: 376 while True: 377 try: 378 try: 379 entry = next(scandir_it) 380 except StopIteration: 381 break 382 except OSError as error: 383 if onerror is not None: 384 onerror(error) 385 cont = True 386 break 387 388 try: 389 if followlinks is _walk_symlinks_as_files: 390 is_dir = entry.is_dir(follow_symlinks=False) and not entry.is_junction() 391 else: 392 is_dir = entry.is_dir() 393 except OSError: 394 # If is_dir() raises an OSError, consider the entry not to 395 # be a directory, same behaviour as os.path.isdir(). 396 is_dir = False 397 398 if is_dir: 399 dirs.append(entry.name) 400 else: 401 nondirs.append(entry.name) 402 403 if not topdown and is_dir: 404 # Bottom-up: traverse into sub-directory, but exclude 405 # symlinks to directories if followlinks is False 406 if followlinks: 407 walk_into = True 408 else: 409 try: 410 is_symlink = entry.is_symlink() 411 except OSError: 412 # If is_symlink() raises an OSError, consider the 413 # entry not to be a symbolic link, same behaviour 414 # as os.path.islink(). 415 is_symlink = False 416 walk_into = not is_symlink 417 418 if walk_into: 419 walk_dirs.append(entry.path) 420 if cont: 421 continue 422 423 if topdown: 424 # Yield before sub-directory traversal if going top down 425 yield top, dirs, nondirs 426 # Traverse into sub-directories 427 for dirname in reversed(dirs): 428 new_path = join(top, dirname) 429 # bpo-23605: os.path.islink() is used instead of caching 430 # entry.is_symlink() result during the loop on os.scandir() because 431 # the caller can replace the directory entry during the "yield" 432 # above. 433 if followlinks or not islink(new_path): 434 stack.append(new_path) 435 else: 436 # Yield after sub-directory traversal if going bottom up 437 stack.append((top, dirs, nondirs)) 438 # Traverse into sub-directories 439 for new_path in reversed(walk_dirs): 440 stack.append(new_path) 441 442__all__.append("walk") 443 444if {open, stat} <= supports_dir_fd and {scandir, stat} <= supports_fd: 445 446 def fwalk(top=".", topdown=True, onerror=None, *, follow_symlinks=False, dir_fd=None): 447 """Directory tree generator. 448 449 This behaves exactly like walk(), except that it yields a 4-tuple 450 451 dirpath, dirnames, filenames, dirfd 452 453 `dirpath`, `dirnames` and `filenames` are identical to walk() output, 454 and `dirfd` is a file descriptor referring to the directory `dirpath`. 455 456 The advantage of fwalk() over walk() is that it's safe against symlink 457 races (when follow_symlinks is False). 458 459 If dir_fd is not None, it should be a file descriptor open to a directory, 460 and top should be relative; top will then be relative to that directory. 461 (dir_fd is always supported for fwalk.) 462 463 Caution: 464 Since fwalk() yields file descriptors, those are only valid until the 465 next iteration step, so you should dup() them if you want to keep them 466 for a longer period. 467 468 Example: 469 470 import os 471 for root, dirs, files, rootfd in os.fwalk('python/Lib/email'): 472 print(root, "consumes", end="") 473 print(sum(os.stat(name, dir_fd=rootfd).st_size for name in files), 474 end="") 475 print("bytes in", len(files), "non-directory files") 476 if 'CVS' in dirs: 477 dirs.remove('CVS') # don't visit CVS directories 478 """ 479 sys.audit("os.fwalk", top, topdown, onerror, follow_symlinks, dir_fd) 480 top = fspath(top) 481 stack = [(_fwalk_walk, (True, dir_fd, top, top, None))] 482 isbytes = isinstance(top, bytes) 483 try: 484 while stack: 485 yield from _fwalk(stack, isbytes, topdown, onerror, follow_symlinks) 486 finally: 487 # Close any file descriptors still on the stack. 488 while stack: 489 action, value = stack.pop() 490 if action == _fwalk_close: 491 close(value) 492 493 # Each item in the _fwalk() stack is a pair (action, args). 494 _fwalk_walk = 0 # args: (isroot, dirfd, toppath, topname, entry) 495 _fwalk_yield = 1 # args: (toppath, dirnames, filenames, topfd) 496 _fwalk_close = 2 # args: dirfd 497 498 def _fwalk(stack, isbytes, topdown, onerror, follow_symlinks): 499 # Note: This uses O(depth of the directory tree) file descriptors: if 500 # necessary, it can be adapted to only require O(1) FDs, see issue 501 # #13734. 502 503 action, value = stack.pop() 504 if action == _fwalk_close: 505 close(value) 506 return 507 elif action == _fwalk_yield: 508 yield value 509 return 510 assert action == _fwalk_walk 511 isroot, dirfd, toppath, topname, entry = value 512 try: 513 if not follow_symlinks: 514 # Note: To guard against symlink races, we use the standard 515 # lstat()/open()/fstat() trick. 516 if entry is None: 517 orig_st = stat(topname, follow_symlinks=False, dir_fd=dirfd) 518 else: 519 orig_st = entry.stat(follow_symlinks=False) 520 topfd = open(topname, O_RDONLY | O_NONBLOCK, dir_fd=dirfd) 521 except OSError as err: 522 if isroot: 523 raise 524 if onerror is not None: 525 onerror(err) 526 return 527 stack.append((_fwalk_close, topfd)) 528 if not follow_symlinks: 529 if isroot and not st.S_ISDIR(orig_st.st_mode): 530 return 531 if not path.samestat(orig_st, stat(topfd)): 532 return 533 534 scandir_it = scandir(topfd) 535 dirs = [] 536 nondirs = [] 537 entries = None if topdown or follow_symlinks else [] 538 for entry in scandir_it: 539 name = entry.name 540 if isbytes: 541 name = fsencode(name) 542 try: 543 if entry.is_dir(): 544 dirs.append(name) 545 if entries is not None: 546 entries.append(entry) 547 else: 548 nondirs.append(name) 549 except OSError: 550 try: 551 # Add dangling symlinks, ignore disappeared files 552 if entry.is_symlink(): 553 nondirs.append(name) 554 except OSError: 555 pass 556 557 if topdown: 558 yield toppath, dirs, nondirs, topfd 559 else: 560 stack.append((_fwalk_yield, (toppath, dirs, nondirs, topfd))) 561 562 toppath = path.join(toppath, toppath[:0]) # Add trailing slash. 563 if entries is None: 564 stack.extend( 565 (_fwalk_walk, (False, topfd, toppath + name, name, None)) 566 for name in dirs[::-1]) 567 else: 568 stack.extend( 569 (_fwalk_walk, (False, topfd, toppath + name, name, entry)) 570 for name, entry in zip(dirs[::-1], entries[::-1])) 571 572 __all__.append("fwalk") 573 574def execl(file, *args): 575 """execl(file, *args) 576 577 Execute the executable file with argument list args, replacing the 578 current process. """ 579 execv(file, args) 580 581def execle(file, *args): 582 """execle(file, *args, env) 583 584 Execute the executable file with argument list args and 585 environment env, replacing the current process. """ 586 env = args[-1] 587 execve(file, args[:-1], env) 588 589def execlp(file, *args): 590 """execlp(file, *args) 591 592 Execute the executable file (which is searched for along $PATH) 593 with argument list args, replacing the current process. """ 594 execvp(file, args) 595 596def execlpe(file, *args): 597 """execlpe(file, *args, env) 598 599 Execute the executable file (which is searched for along $PATH) 600 with argument list args and environment env, replacing the current 601 process. """ 602 env = args[-1] 603 execvpe(file, args[:-1], env) 604 605def execvp(file, args): 606 """execvp(file, args) 607 608 Execute the executable file (which is searched for along $PATH) 609 with argument list args, replacing the current process. 610 args may be a list or tuple of strings. """ 611 _execvpe(file, args) 612 613def execvpe(file, args, env): 614 """execvpe(file, args, env) 615 616 Execute the executable file (which is searched for along $PATH) 617 with argument list args and environment env, replacing the 618 current process. 619 args may be a list or tuple of strings. """ 620 _execvpe(file, args, env) 621 622__all__.extend(["execl","execle","execlp","execlpe","execvp","execvpe"]) 623 624def _execvpe(file, args, env=None): 625 if env is not None: 626 exec_func = execve 627 argrest = (args, env) 628 else: 629 exec_func = execv 630 argrest = (args,) 631 env = environ 632 633 if path.dirname(file): 634 exec_func(file, *argrest) 635 return 636 saved_exc = None 637 path_list = get_exec_path(env) 638 if name != 'nt': 639 file = fsencode(file) 640 path_list = map(fsencode, path_list) 641 for dir in path_list: 642 fullname = path.join(dir, file) 643 try: 644 exec_func(fullname, *argrest) 645 except (FileNotFoundError, NotADirectoryError) as e: 646 last_exc = e 647 except OSError as e: 648 last_exc = e 649 if saved_exc is None: 650 saved_exc = e 651 if saved_exc is not None: 652 raise saved_exc 653 raise last_exc 654 655 656def get_exec_path(env=None): 657 """Returns the sequence of directories that will be searched for the 658 named executable (similar to a shell) when launching a process. 659 660 *env* must be an environment variable dict or None. If *env* is None, 661 os.environ will be used. 662 """ 663 # Use a local import instead of a global import to limit the number of 664 # modules loaded at startup: the os module is always loaded at startup by 665 # Python. It may also avoid a bootstrap issue. 666 import warnings 667 668 if env is None: 669 env = environ 670 671 # {b'PATH': ...}.get('PATH') and {'PATH': ...}.get(b'PATH') emit a 672 # BytesWarning when using python -b or python -bb: ignore the warning 673 with warnings.catch_warnings(): 674 warnings.simplefilter("ignore", BytesWarning) 675 676 try: 677 path_list = env.get('PATH') 678 except TypeError: 679 path_list = None 680 681 if supports_bytes_environ: 682 try: 683 path_listb = env[b'PATH'] 684 except (KeyError, TypeError): 685 pass 686 else: 687 if path_list is not None: 688 raise ValueError( 689 "env cannot contain 'PATH' and b'PATH' keys") 690 path_list = path_listb 691 692 if path_list is not None and isinstance(path_list, bytes): 693 path_list = fsdecode(path_list) 694 695 if path_list is None: 696 path_list = defpath 697 return path_list.split(pathsep) 698 699 700# Change environ to automatically call putenv() and unsetenv() 701from _collections_abc import MutableMapping, Mapping 702 703class _Environ(MutableMapping): 704 def __init__(self, data, encodekey, decodekey, encodevalue, decodevalue): 705 self.encodekey = encodekey 706 self.decodekey = decodekey 707 self.encodevalue = encodevalue 708 self.decodevalue = decodevalue 709 self._data = data 710 711 def __getitem__(self, key): 712 try: 713 value = self._data[self.encodekey(key)] 714 except KeyError: 715 # raise KeyError with the original key value 716 raise KeyError(key) from None 717 return self.decodevalue(value) 718 719 def __setitem__(self, key, value): 720 key = self.encodekey(key) 721 value = self.encodevalue(value) 722 putenv(key, value) 723 self._data[key] = value 724 725 def __delitem__(self, key): 726 encodedkey = self.encodekey(key) 727 unsetenv(encodedkey) 728 try: 729 del self._data[encodedkey] 730 except KeyError: 731 # raise KeyError with the original key value 732 raise KeyError(key) from None 733 734 def __iter__(self): 735 # list() from dict object is an atomic operation 736 keys = list(self._data) 737 for key in keys: 738 yield self.decodekey(key) 739 740 def __len__(self): 741 return len(self._data) 742 743 def __repr__(self): 744 formatted_items = ", ".join( 745 f"{self.decodekey(key)!r}: {self.decodevalue(value)!r}" 746 for key, value in self._data.items() 747 ) 748 return f"environ({{{formatted_items}}})" 749 750 def copy(self): 751 return dict(self) 752 753 def setdefault(self, key, value): 754 if key not in self: 755 self[key] = value 756 return self[key] 757 758 def __ior__(self, other): 759 self.update(other) 760 return self 761 762 def __or__(self, other): 763 if not isinstance(other, Mapping): 764 return NotImplemented 765 new = dict(self) 766 new.update(other) 767 return new 768 769 def __ror__(self, other): 770 if not isinstance(other, Mapping): 771 return NotImplemented 772 new = dict(other) 773 new.update(self) 774 return new 775 776def _createenviron(): 777 if name == 'nt': 778 # Where Env Var Names Must Be UPPERCASE 779 def check_str(value): 780 if not isinstance(value, str): 781 raise TypeError("str expected, not %s" % type(value).__name__) 782 return value 783 encode = check_str 784 decode = str 785 def encodekey(key): 786 return encode(key).upper() 787 data = {} 788 for key, value in environ.items(): 789 data[encodekey(key)] = value 790 else: 791 # Where Env Var Names Can Be Mixed Case 792 encoding = sys.getfilesystemencoding() 793 def encode(value): 794 if not isinstance(value, str): 795 raise TypeError("str expected, not %s" % type(value).__name__) 796 return value.encode(encoding, 'surrogateescape') 797 def decode(value): 798 return value.decode(encoding, 'surrogateescape') 799 encodekey = encode 800 data = environ 801 return _Environ(data, 802 encodekey, decode, 803 encode, decode) 804 805# unicode environ 806environ = _createenviron() 807del _createenviron 808 809 810def getenv(key, default=None): 811 """Get an environment variable, return None if it doesn't exist. 812 The optional second argument can specify an alternate default. 813 key, default and the result are str.""" 814 return environ.get(key, default) 815 816supports_bytes_environ = (name != 'nt') 817__all__.extend(("getenv", "supports_bytes_environ")) 818 819if supports_bytes_environ: 820 def _check_bytes(value): 821 if not isinstance(value, bytes): 822 raise TypeError("bytes expected, not %s" % type(value).__name__) 823 return value 824 825 # bytes environ 826 environb = _Environ(environ._data, 827 _check_bytes, bytes, 828 _check_bytes, bytes) 829 del _check_bytes 830 831 def getenvb(key, default=None): 832 """Get an environment variable, return None if it doesn't exist. 833 The optional second argument can specify an alternate default. 834 key, default and the result are bytes.""" 835 return environb.get(key, default) 836 837 __all__.extend(("environb", "getenvb")) 838 839def _fscodec(): 840 encoding = sys.getfilesystemencoding() 841 errors = sys.getfilesystemencodeerrors() 842 843 def fsencode(filename): 844 """Encode filename (an os.PathLike, bytes, or str) to the filesystem 845 encoding with 'surrogateescape' error handler, return bytes unchanged. 846 On Windows, use 'strict' error handler if the file system encoding is 847 'mbcs' (which is the default encoding). 848 """ 849 filename = fspath(filename) # Does type-checking of `filename`. 850 if isinstance(filename, str): 851 return filename.encode(encoding, errors) 852 else: 853 return filename 854 855 def fsdecode(filename): 856 """Decode filename (an os.PathLike, bytes, or str) from the filesystem 857 encoding with 'surrogateescape' error handler, return str unchanged. On 858 Windows, use 'strict' error handler if the file system encoding is 859 'mbcs' (which is the default encoding). 860 """ 861 filename = fspath(filename) # Does type-checking of `filename`. 862 if isinstance(filename, bytes): 863 return filename.decode(encoding, errors) 864 else: 865 return filename 866 867 return fsencode, fsdecode 868 869fsencode, fsdecode = _fscodec() 870del _fscodec 871 872# Supply spawn*() (probably only for Unix) 873if _exists("fork") and not _exists("spawnv") and _exists("execv"): 874 875 P_WAIT = 0 876 P_NOWAIT = P_NOWAITO = 1 877 878 __all__.extend(["P_WAIT", "P_NOWAIT", "P_NOWAITO"]) 879 880 # XXX Should we support P_DETACH? I suppose it could fork()**2 881 # and close the std I/O streams. Also, P_OVERLAY is the same 882 # as execv*()? 883 884 def _spawnvef(mode, file, args, env, func): 885 # Internal helper; func is the exec*() function to use 886 if not isinstance(args, (tuple, list)): 887 raise TypeError('argv must be a tuple or a list') 888 if not args or not args[0]: 889 raise ValueError('argv first element cannot be empty') 890 pid = fork() 891 if not pid: 892 # Child 893 try: 894 if env is None: 895 func(file, args) 896 else: 897 func(file, args, env) 898 except: 899 _exit(127) 900 else: 901 # Parent 902 if mode == P_NOWAIT: 903 return pid # Caller is responsible for waiting! 904 while 1: 905 wpid, sts = waitpid(pid, 0) 906 if WIFSTOPPED(sts): 907 continue 908 909 return waitstatus_to_exitcode(sts) 910 911 def spawnv(mode, file, args): 912 """spawnv(mode, file, args) -> integer 913 914Execute file with arguments from args in a subprocess. 915If mode == P_NOWAIT return the pid of the process. 916If mode == P_WAIT return the process's exit code if it exits normally; 917otherwise return -SIG, where SIG is the signal that killed it. """ 918 return _spawnvef(mode, file, args, None, execv) 919 920 def spawnve(mode, file, args, env): 921 """spawnve(mode, file, args, env) -> integer 922 923Execute file with arguments from args in a subprocess with the 924specified environment. 925If mode == P_NOWAIT return the pid of the process. 926If mode == P_WAIT return the process's exit code if it exits normally; 927otherwise return -SIG, where SIG is the signal that killed it. """ 928 return _spawnvef(mode, file, args, env, execve) 929 930 # Note: spawnvp[e] isn't currently supported on Windows 931 932 def spawnvp(mode, file, args): 933 """spawnvp(mode, file, args) -> integer 934 935Execute file (which is looked for along $PATH) with arguments from 936args in a subprocess. 937If mode == P_NOWAIT return the pid of the process. 938If mode == P_WAIT return the process's exit code if it exits normally; 939otherwise return -SIG, where SIG is the signal that killed it. """ 940 return _spawnvef(mode, file, args, None, execvp) 941 942 def spawnvpe(mode, file, args, env): 943 """spawnvpe(mode, file, args, env) -> integer 944 945Execute file (which is looked for along $PATH) with arguments from 946args in a subprocess with the supplied environment. 947If mode == P_NOWAIT return the pid of the process. 948If mode == P_WAIT return the process's exit code if it exits normally; 949otherwise return -SIG, where SIG is the signal that killed it. """ 950 return _spawnvef(mode, file, args, env, execvpe) 951 952 953 __all__.extend(["spawnv", "spawnve", "spawnvp", "spawnvpe"]) 954 955 956if _exists("spawnv"): 957 # These aren't supplied by the basic Windows code 958 # but can be easily implemented in Python 959 960 def spawnl(mode, file, *args): 961 """spawnl(mode, file, *args) -> integer 962 963Execute file with arguments from args in a subprocess. 964If mode == P_NOWAIT return the pid of the process. 965If mode == P_WAIT return the process's exit code if it exits normally; 966otherwise return -SIG, where SIG is the signal that killed it. """ 967 return spawnv(mode, file, args) 968 969 def spawnle(mode, file, *args): 970 """spawnle(mode, file, *args, env) -> integer 971 972Execute file with arguments from args in a subprocess with the 973supplied environment. 974If mode == P_NOWAIT return the pid of the process. 975If mode == P_WAIT return the process's exit code if it exits normally; 976otherwise return -SIG, where SIG is the signal that killed it. """ 977 env = args[-1] 978 return spawnve(mode, file, args[:-1], env) 979 980 981 __all__.extend(["spawnl", "spawnle"]) 982 983 984if _exists("spawnvp"): 985 # At the moment, Windows doesn't implement spawnvp[e], 986 # so it won't have spawnlp[e] either. 987 def spawnlp(mode, file, *args): 988 """spawnlp(mode, file, *args) -> integer 989 990Execute file (which is looked for along $PATH) with arguments from 991args in a subprocess with the supplied environment. 992If mode == P_NOWAIT return the pid of the process. 993If mode == P_WAIT return the process's exit code if it exits normally; 994otherwise return -SIG, where SIG is the signal that killed it. """ 995 return spawnvp(mode, file, args) 996 997 def spawnlpe(mode, file, *args): 998 """spawnlpe(mode, file, *args, env) -> integer 999 1000Execute file (which is looked for along $PATH) with arguments from 1001args in a subprocess with the supplied environment. 1002If mode == P_NOWAIT return the pid of the process. 1003If mode == P_WAIT return the process's exit code if it exits normally; 1004otherwise return -SIG, where SIG is the signal that killed it. """ 1005 env = args[-1] 1006 return spawnvpe(mode, file, args[:-1], env) 1007 1008 1009 __all__.extend(["spawnlp", "spawnlpe"]) 1010 1011# VxWorks has no user space shell provided. As a result, running 1012# command in a shell can't be supported. 1013if sys.platform != 'vxworks': 1014 # Supply os.popen() 1015 def popen(cmd, mode="r", buffering=-1): 1016 if not isinstance(cmd, str): 1017 raise TypeError("invalid cmd type (%s, expected string)" % type(cmd)) 1018 if mode not in ("r", "w"): 1019 raise ValueError("invalid mode %r" % mode) 1020 if buffering == 0 or buffering is None: 1021 raise ValueError("popen() does not support unbuffered streams") 1022 import subprocess 1023 if mode == "r": 1024 proc = subprocess.Popen(cmd, 1025 shell=True, text=True, 1026 stdout=subprocess.PIPE, 1027 bufsize=buffering) 1028 return _wrap_close(proc.stdout, proc) 1029 else: 1030 proc = subprocess.Popen(cmd, 1031 shell=True, text=True, 1032 stdin=subprocess.PIPE, 1033 bufsize=buffering) 1034 return _wrap_close(proc.stdin, proc) 1035 1036 # Helper for popen() -- a proxy for a file whose close waits for the process 1037 class _wrap_close: 1038 def __init__(self, stream, proc): 1039 self._stream = stream 1040 self._proc = proc 1041 def close(self): 1042 self._stream.close() 1043 returncode = self._proc.wait() 1044 if returncode == 0: 1045 return None 1046 if name == 'nt': 1047 return returncode 1048 else: 1049 return returncode << 8 # Shift left to match old behavior 1050 def __enter__(self): 1051 return self 1052 def __exit__(self, *args): 1053 self.close() 1054 def __getattr__(self, name): 1055 return getattr(self._stream, name) 1056 def __iter__(self): 1057 return iter(self._stream) 1058 1059 __all__.append("popen") 1060 1061# Supply os.fdopen() 1062def fdopen(fd, mode="r", buffering=-1, encoding=None, *args, **kwargs): 1063 if not isinstance(fd, int): 1064 raise TypeError("invalid fd type (%s, expected integer)" % type(fd)) 1065 import io 1066 if "b" not in mode: 1067 encoding = io.text_encoding(encoding) 1068 return io.open(fd, mode, buffering, encoding, *args, **kwargs) 1069 1070 1071# For testing purposes, make sure the function is available when the C 1072# implementation exists. 1073def _fspath(path): 1074 """Return the path representation of a path-like object. 1075 1076 If str or bytes is passed in, it is returned unchanged. Otherwise the 1077 os.PathLike interface is used to get the path representation. If the 1078 path representation is not str or bytes, TypeError is raised. If the 1079 provided path is not str, bytes, or os.PathLike, TypeError is raised. 1080 """ 1081 if isinstance(path, (str, bytes)): 1082 return path 1083 1084 # Work from the object's type to match method resolution of other magic 1085 # methods. 1086 path_type = type(path) 1087 try: 1088 path_repr = path_type.__fspath__(path) 1089 except AttributeError: 1090 if hasattr(path_type, '__fspath__'): 1091 raise 1092 else: 1093 raise TypeError("expected str, bytes or os.PathLike object, " 1094 "not " + path_type.__name__) 1095 except TypeError: 1096 if path_type.__fspath__ is None: 1097 raise TypeError("expected str, bytes or os.PathLike object, " 1098 "not " + path_type.__name__) from None 1099 else: 1100 raise 1101 if isinstance(path_repr, (str, bytes)): 1102 return path_repr 1103 else: 1104 raise TypeError("expected {}.__fspath__() to return str or bytes, " 1105 "not {}".format(path_type.__name__, 1106 type(path_repr).__name__)) 1107 1108# If there is no C implementation, make the pure Python version the 1109# implementation as transparently as possible. 1110if not _exists('fspath'): 1111 fspath = _fspath 1112 fspath.__name__ = "fspath" 1113 1114 1115class PathLike(abc.ABC): 1116 1117 """Abstract base class for implementing the file system path protocol.""" 1118 1119 __slots__ = () 1120 1121 @abc.abstractmethod 1122 def __fspath__(self): 1123 """Return the file system path representation of the object.""" 1124 raise NotImplementedError 1125 1126 @classmethod 1127 def __subclasshook__(cls, subclass): 1128 if cls is PathLike: 1129 return _check_methods(subclass, '__fspath__') 1130 return NotImplemented 1131 1132 __class_getitem__ = classmethod(GenericAlias) 1133 1134 1135if name == 'nt': 1136 class _AddedDllDirectory: 1137 def __init__(self, path, cookie, remove_dll_directory): 1138 self.path = path 1139 self._cookie = cookie 1140 self._remove_dll_directory = remove_dll_directory 1141 def close(self): 1142 self._remove_dll_directory(self._cookie) 1143 self.path = None 1144 def __enter__(self): 1145 return self 1146 def __exit__(self, *args): 1147 self.close() 1148 def __repr__(self): 1149 if self.path: 1150 return "<AddedDllDirectory({!r})>".format(self.path) 1151 return "<AddedDllDirectory()>" 1152 1153 def add_dll_directory(path): 1154 """Add a path to the DLL search path. 1155 1156 This search path is used when resolving dependencies for imported 1157 extension modules (the module itself is resolved through sys.path), 1158 and also by ctypes. 1159 1160 Remove the directory by calling close() on the returned object or 1161 using it in a with statement. 1162 """ 1163 import nt 1164 cookie = nt._add_dll_directory(path) 1165 return _AddedDllDirectory( 1166 path, 1167 cookie, 1168 nt._remove_dll_directory 1169 ) 1170 1171 1172if _exists('sched_getaffinity') and sys._get_cpu_count_config() < 0: 1173 def process_cpu_count(): 1174 """ 1175 Get the number of CPUs of the current process. 1176 1177 Return the number of logical CPUs usable by the calling thread of the 1178 current process. Return None if indeterminable. 1179 """ 1180 return len(sched_getaffinity(0)) 1181else: 1182 # Just an alias to cpu_count() (same docstring) 1183 process_cpu_count = cpu_count 1184