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