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 is ineffective, since the directories in dirnames have 304 already been generated by the time dirnames itself is generated. No matter 305 the value of topdown, the list of subdirectories is retrieved before the 306 tuples for the directory and its subdirectories are generated. 307 308 By default errors from the os.scandir() call are ignored. If 309 optional arg 'onerror' is specified, it should be a function; it 310 will be called with one argument, an OSError instance. It can 311 report the error to continue with the walk, or raise the exception 312 to abort the walk. Note that the filename is available as the 313 filename attribute of the exception object. 314 315 By default, os.walk does not follow symbolic links to subdirectories on 316 systems that support them. In order to get this functionality, set the 317 optional argument 'followlinks' to true. 318 319 Caution: if you pass a relative pathname for top, don't change the 320 current working directory between resumptions of walk. walk never 321 changes the current directory, and assumes that the client doesn't 322 either. 323 324 Example: 325 326 import os 327 from os.path import join, getsize 328 for root, dirs, files in os.walk('python/Lib/email'): 329 print(root, "consumes", end="") 330 print(sum([getsize(join(root, name)) for name in files]), end="") 331 print("bytes in", len(files), "non-directory files") 332 if 'CVS' in dirs: 333 dirs.remove('CVS') # don't visit CVS directories 334 335 """ 336 top = fspath(top) 337 dirs = [] 338 nondirs = [] 339 walk_dirs = [] 340 341 # We may not have read permission for top, in which case we can't 342 # get a list of the files the directory contains. os.walk 343 # always suppressed the exception then, rather than blow up for a 344 # minor reason when (say) a thousand readable directories are still 345 # left to visit. That logic is copied here. 346 try: 347 # Note that scandir is global in this module due 348 # to earlier import-*. 349 scandir_it = scandir(top) 350 except OSError as error: 351 if onerror is not None: 352 onerror(error) 353 return 354 355 with scandir_it: 356 while True: 357 try: 358 try: 359 entry = next(scandir_it) 360 except StopIteration: 361 break 362 except OSError as error: 363 if onerror is not None: 364 onerror(error) 365 return 366 367 try: 368 is_dir = entry.is_dir() 369 except OSError: 370 # If is_dir() raises an OSError, consider that the entry is not 371 # a directory, same behaviour than os.path.isdir(). 372 is_dir = False 373 374 if is_dir: 375 dirs.append(entry.name) 376 else: 377 nondirs.append(entry.name) 378 379 if not topdown and is_dir: 380 # Bottom-up: recurse into sub-directory, but exclude symlinks to 381 # directories if followlinks is False 382 if followlinks: 383 walk_into = True 384 else: 385 try: 386 is_symlink = entry.is_symlink() 387 except OSError: 388 # If is_symlink() raises an OSError, consider that the 389 # entry is not a symbolic link, same behaviour than 390 # os.path.islink(). 391 is_symlink = False 392 walk_into = not is_symlink 393 394 if walk_into: 395 walk_dirs.append(entry.path) 396 397 # Yield before recursion if going top down 398 if topdown: 399 yield top, dirs, nondirs 400 401 # Recurse into sub-directories 402 islink, join = path.islink, path.join 403 for dirname in dirs: 404 new_path = join(top, dirname) 405 # Issue #23605: os.path.islink() is used instead of caching 406 # entry.is_symlink() result during the loop on os.scandir() because 407 # the caller can replace the directory entry during the "yield" 408 # above. 409 if followlinks or not islink(new_path): 410 yield from walk(new_path, topdown, onerror, followlinks) 411 else: 412 # Recurse into sub-directories 413 for new_path in walk_dirs: 414 yield from walk(new_path, topdown, onerror, followlinks) 415 # Yield after recursion if going bottom up 416 yield top, dirs, nondirs 417 418__all__.append("walk") 419 420if {open, stat} <= supports_dir_fd and {scandir, stat} <= supports_fd: 421 422 def fwalk(top=".", topdown=True, onerror=None, *, follow_symlinks=False, dir_fd=None): 423 """Directory tree generator. 424 425 This behaves exactly like walk(), except that it yields a 4-tuple 426 427 dirpath, dirnames, filenames, dirfd 428 429 `dirpath`, `dirnames` and `filenames` are identical to walk() output, 430 and `dirfd` is a file descriptor referring to the directory `dirpath`. 431 432 The advantage of fwalk() over walk() is that it's safe against symlink 433 races (when follow_symlinks is False). 434 435 If dir_fd is not None, it should be a file descriptor open to a directory, 436 and top should be relative; top will then be relative to that directory. 437 (dir_fd is always supported for fwalk.) 438 439 Caution: 440 Since fwalk() yields file descriptors, those are only valid until the 441 next iteration step, so you should dup() them if you want to keep them 442 for a longer period. 443 444 Example: 445 446 import os 447 for root, dirs, files, rootfd in os.fwalk('python/Lib/email'): 448 print(root, "consumes", end="") 449 print(sum([os.stat(name, dir_fd=rootfd).st_size for name in files]), 450 end="") 451 print("bytes in", len(files), "non-directory files") 452 if 'CVS' in dirs: 453 dirs.remove('CVS') # don't visit CVS directories 454 """ 455 if not isinstance(top, int) or not hasattr(top, '__index__'): 456 top = fspath(top) 457 # Note: To guard against symlink races, we use the standard 458 # lstat()/open()/fstat() trick. 459 if not follow_symlinks: 460 orig_st = stat(top, follow_symlinks=False, dir_fd=dir_fd) 461 topfd = open(top, O_RDONLY, dir_fd=dir_fd) 462 try: 463 if (follow_symlinks or (st.S_ISDIR(orig_st.st_mode) and 464 path.samestat(orig_st, stat(topfd)))): 465 yield from _fwalk(topfd, top, isinstance(top, bytes), 466 topdown, onerror, follow_symlinks) 467 finally: 468 close(topfd) 469 470 def _fwalk(topfd, toppath, isbytes, topdown, onerror, follow_symlinks): 471 # Note: This uses O(depth of the directory tree) file descriptors: if 472 # necessary, it can be adapted to only require O(1) FDs, see issue 473 # #13734. 474 475 scandir_it = scandir(topfd) 476 dirs = [] 477 nondirs = [] 478 entries = None if topdown or follow_symlinks else [] 479 for entry in scandir_it: 480 name = entry.name 481 if isbytes: 482 name = fsencode(name) 483 try: 484 if entry.is_dir(): 485 dirs.append(name) 486 if entries is not None: 487 entries.append(entry) 488 else: 489 nondirs.append(name) 490 except OSError: 491 try: 492 # Add dangling symlinks, ignore disappeared files 493 if entry.is_symlink(): 494 nondirs.append(name) 495 except OSError: 496 pass 497 498 if topdown: 499 yield toppath, dirs, nondirs, topfd 500 501 for name in dirs if entries is None else zip(dirs, entries): 502 try: 503 if not follow_symlinks: 504 if topdown: 505 orig_st = stat(name, dir_fd=topfd, follow_symlinks=False) 506 else: 507 assert entries is not None 508 name, entry = name 509 orig_st = entry.stat(follow_symlinks=False) 510 dirfd = open(name, O_RDONLY, dir_fd=topfd) 511 except OSError as err: 512 if onerror is not None: 513 onerror(err) 514 continue 515 try: 516 if follow_symlinks or path.samestat(orig_st, stat(dirfd)): 517 dirpath = path.join(toppath, name) 518 yield from _fwalk(dirfd, dirpath, isbytes, 519 topdown, onerror, follow_symlinks) 520 finally: 521 close(dirfd) 522 523 if not topdown: 524 yield toppath, dirs, nondirs, topfd 525 526 __all__.append("fwalk") 527 528# Make sure os.environ exists, at least 529try: 530 environ 531except NameError: 532 environ = {} 533 534def execl(file, *args): 535 """execl(file, *args) 536 537 Execute the executable file with argument list args, replacing the 538 current process. """ 539 execv(file, args) 540 541def execle(file, *args): 542 """execle(file, *args, env) 543 544 Execute the executable file with argument list args and 545 environment env, replacing the current process. """ 546 env = args[-1] 547 execve(file, args[:-1], env) 548 549def execlp(file, *args): 550 """execlp(file, *args) 551 552 Execute the executable file (which is searched for along $PATH) 553 with argument list args, replacing the current process. """ 554 execvp(file, args) 555 556def execlpe(file, *args): 557 """execlpe(file, *args, env) 558 559 Execute the executable file (which is searched for along $PATH) 560 with argument list args and environment env, replacing the current 561 process. """ 562 env = args[-1] 563 execvpe(file, args[:-1], env) 564 565def execvp(file, args): 566 """execvp(file, args) 567 568 Execute the executable file (which is searched for along $PATH) 569 with argument list args, replacing the current process. 570 args may be a list or tuple of strings. """ 571 _execvpe(file, args) 572 573def execvpe(file, args, env): 574 """execvpe(file, args, env) 575 576 Execute the executable file (which is searched for along $PATH) 577 with argument list args and environment env , replacing the 578 current process. 579 args may be a list or tuple of strings. """ 580 _execvpe(file, args, env) 581 582__all__.extend(["execl","execle","execlp","execlpe","execvp","execvpe"]) 583 584def _execvpe(file, args, env=None): 585 if env is not None: 586 exec_func = execve 587 argrest = (args, env) 588 else: 589 exec_func = execv 590 argrest = (args,) 591 env = environ 592 593 if path.dirname(file): 594 exec_func(file, *argrest) 595 return 596 saved_exc = None 597 path_list = get_exec_path(env) 598 if name != 'nt': 599 file = fsencode(file) 600 path_list = map(fsencode, path_list) 601 for dir in path_list: 602 fullname = path.join(dir, file) 603 try: 604 exec_func(fullname, *argrest) 605 except (FileNotFoundError, NotADirectoryError) as e: 606 last_exc = e 607 except OSError as e: 608 last_exc = e 609 if saved_exc is None: 610 saved_exc = e 611 if saved_exc is not None: 612 raise saved_exc 613 raise last_exc 614 615 616def get_exec_path(env=None): 617 """Returns the sequence of directories that will be searched for the 618 named executable (similar to a shell) when launching a process. 619 620 *env* must be an environment variable dict or None. If *env* is None, 621 os.environ will be used. 622 """ 623 # Use a local import instead of a global import to limit the number of 624 # modules loaded at startup: the os module is always loaded at startup by 625 # Python. It may also avoid a bootstrap issue. 626 import warnings 627 628 if env is None: 629 env = environ 630 631 # {b'PATH': ...}.get('PATH') and {'PATH': ...}.get(b'PATH') emit a 632 # BytesWarning when using python -b or python -bb: ignore the warning 633 with warnings.catch_warnings(): 634 warnings.simplefilter("ignore", BytesWarning) 635 636 try: 637 path_list = env.get('PATH') 638 except TypeError: 639 path_list = None 640 641 if supports_bytes_environ: 642 try: 643 path_listb = env[b'PATH'] 644 except (KeyError, TypeError): 645 pass 646 else: 647 if path_list is not None: 648 raise ValueError( 649 "env cannot contain 'PATH' and b'PATH' keys") 650 path_list = path_listb 651 652 if path_list is not None and isinstance(path_list, bytes): 653 path_list = fsdecode(path_list) 654 655 if path_list is None: 656 path_list = defpath 657 return path_list.split(pathsep) 658 659 660# Change environ to automatically call putenv(), unsetenv if they exist. 661from _collections_abc import MutableMapping 662 663class _Environ(MutableMapping): 664 def __init__(self, data, encodekey, decodekey, encodevalue, decodevalue, putenv, unsetenv): 665 self.encodekey = encodekey 666 self.decodekey = decodekey 667 self.encodevalue = encodevalue 668 self.decodevalue = decodevalue 669 self.putenv = putenv 670 self.unsetenv = unsetenv 671 self._data = data 672 673 def __getitem__(self, key): 674 try: 675 value = self._data[self.encodekey(key)] 676 except KeyError: 677 # raise KeyError with the original key value 678 raise KeyError(key) from None 679 return self.decodevalue(value) 680 681 def __setitem__(self, key, value): 682 key = self.encodekey(key) 683 value = self.encodevalue(value) 684 self.putenv(key, value) 685 self._data[key] = value 686 687 def __delitem__(self, key): 688 encodedkey = self.encodekey(key) 689 self.unsetenv(encodedkey) 690 try: 691 del self._data[encodedkey] 692 except KeyError: 693 # raise KeyError with the original key value 694 raise KeyError(key) from None 695 696 def __iter__(self): 697 # list() from dict object is an atomic operation 698 keys = list(self._data) 699 for key in keys: 700 yield self.decodekey(key) 701 702 def __len__(self): 703 return len(self._data) 704 705 def __repr__(self): 706 return 'environ({{{}}})'.format(', '.join( 707 ('{!r}: {!r}'.format(self.decodekey(key), self.decodevalue(value)) 708 for key, value in self._data.items()))) 709 710 def copy(self): 711 return dict(self) 712 713 def setdefault(self, key, value): 714 if key not in self: 715 self[key] = value 716 return self[key] 717 718try: 719 _putenv = putenv 720except NameError: 721 _putenv = lambda key, value: None 722else: 723 if "putenv" not in __all__: 724 __all__.append("putenv") 725 726try: 727 _unsetenv = unsetenv 728except NameError: 729 _unsetenv = lambda key: _putenv(key, "") 730else: 731 if "unsetenv" not in __all__: 732 __all__.append("unsetenv") 733 734def _createenviron(): 735 if name == 'nt': 736 # Where Env Var Names Must Be UPPERCASE 737 def check_str(value): 738 if not isinstance(value, str): 739 raise TypeError("str expected, not %s" % type(value).__name__) 740 return value 741 encode = check_str 742 decode = str 743 def encodekey(key): 744 return encode(key).upper() 745 data = {} 746 for key, value in environ.items(): 747 data[encodekey(key)] = value 748 else: 749 # Where Env Var Names Can Be Mixed Case 750 encoding = sys.getfilesystemencoding() 751 def encode(value): 752 if not isinstance(value, str): 753 raise TypeError("str expected, not %s" % type(value).__name__) 754 return value.encode(encoding, 'surrogateescape') 755 def decode(value): 756 return value.decode(encoding, 'surrogateescape') 757 encodekey = encode 758 data = environ 759 return _Environ(data, 760 encodekey, decode, 761 encode, decode, 762 _putenv, _unsetenv) 763 764# unicode environ 765environ = _createenviron() 766del _createenviron 767 768 769def getenv(key, default=None): 770 """Get an environment variable, return None if it doesn't exist. 771 The optional second argument can specify an alternate default. 772 key, default and the result are str.""" 773 return environ.get(key, default) 774 775supports_bytes_environ = (name != 'nt') 776__all__.extend(("getenv", "supports_bytes_environ")) 777 778if supports_bytes_environ: 779 def _check_bytes(value): 780 if not isinstance(value, bytes): 781 raise TypeError("bytes expected, not %s" % type(value).__name__) 782 return value 783 784 # bytes environ 785 environb = _Environ(environ._data, 786 _check_bytes, bytes, 787 _check_bytes, bytes, 788 _putenv, _unsetenv) 789 del _check_bytes 790 791 def getenvb(key, default=None): 792 """Get an environment variable, return None if it doesn't exist. 793 The optional second argument can specify an alternate default. 794 key, default and the result are bytes.""" 795 return environb.get(key, default) 796 797 __all__.extend(("environb", "getenvb")) 798 799def _fscodec(): 800 encoding = sys.getfilesystemencoding() 801 errors = sys.getfilesystemencodeerrors() 802 803 def fsencode(filename): 804 """Encode filename (an os.PathLike, bytes, or str) to the filesystem 805 encoding with 'surrogateescape' error handler, return bytes unchanged. 806 On Windows, use 'strict' error handler if the file system encoding is 807 'mbcs' (which is the default encoding). 808 """ 809 filename = fspath(filename) # Does type-checking of `filename`. 810 if isinstance(filename, str): 811 return filename.encode(encoding, errors) 812 else: 813 return filename 814 815 def fsdecode(filename): 816 """Decode filename (an os.PathLike, bytes, or str) from the filesystem 817 encoding with 'surrogateescape' error handler, return str unchanged. On 818 Windows, use 'strict' error handler if the file system encoding is 819 'mbcs' (which is the default encoding). 820 """ 821 filename = fspath(filename) # Does type-checking of `filename`. 822 if isinstance(filename, bytes): 823 return filename.decode(encoding, errors) 824 else: 825 return filename 826 827 return fsencode, fsdecode 828 829fsencode, fsdecode = _fscodec() 830del _fscodec 831 832# Supply spawn*() (probably only for Unix) 833if _exists("fork") and not _exists("spawnv") and _exists("execv"): 834 835 P_WAIT = 0 836 P_NOWAIT = P_NOWAITO = 1 837 838 __all__.extend(["P_WAIT", "P_NOWAIT", "P_NOWAITO"]) 839 840 # XXX Should we support P_DETACH? I suppose it could fork()**2 841 # and close the std I/O streams. Also, P_OVERLAY is the same 842 # as execv*()? 843 844 def _spawnvef(mode, file, args, env, func): 845 # Internal helper; func is the exec*() function to use 846 if not isinstance(args, (tuple, list)): 847 raise TypeError('argv must be a tuple or a list') 848 if not args or not args[0]: 849 raise ValueError('argv first element cannot be empty') 850 pid = fork() 851 if not pid: 852 # Child 853 try: 854 if env is None: 855 func(file, args) 856 else: 857 func(file, args, env) 858 except: 859 _exit(127) 860 else: 861 # Parent 862 if mode == P_NOWAIT: 863 return pid # Caller is responsible for waiting! 864 while 1: 865 wpid, sts = waitpid(pid, 0) 866 if WIFSTOPPED(sts): 867 continue 868 elif WIFSIGNALED(sts): 869 return -WTERMSIG(sts) 870 elif WIFEXITED(sts): 871 return WEXITSTATUS(sts) 872 else: 873 raise OSError("Not stopped, signaled or exited???") 874 875 def spawnv(mode, file, args): 876 """spawnv(mode, file, args) -> integer 877 878Execute file with arguments from args in a subprocess. 879If mode == P_NOWAIT return the pid of the process. 880If mode == P_WAIT return the process's exit code if it exits normally; 881otherwise return -SIG, where SIG is the signal that killed it. """ 882 return _spawnvef(mode, file, args, None, execv) 883 884 def spawnve(mode, file, args, env): 885 """spawnve(mode, file, args, env) -> integer 886 887Execute file with arguments from args in a subprocess with the 888specified environment. 889If mode == P_NOWAIT return the pid of the process. 890If mode == P_WAIT return the process's exit code if it exits normally; 891otherwise return -SIG, where SIG is the signal that killed it. """ 892 return _spawnvef(mode, file, args, env, execve) 893 894 # Note: spawnvp[e] isn't currently supported on Windows 895 896 def spawnvp(mode, file, args): 897 """spawnvp(mode, file, args) -> integer 898 899Execute file (which is looked for along $PATH) with arguments from 900args in a subprocess. 901If mode == P_NOWAIT return the pid of the process. 902If mode == P_WAIT return the process's exit code if it exits normally; 903otherwise return -SIG, where SIG is the signal that killed it. """ 904 return _spawnvef(mode, file, args, None, execvp) 905 906 def spawnvpe(mode, file, args, env): 907 """spawnvpe(mode, file, args, env) -> integer 908 909Execute file (which is looked for along $PATH) with arguments from 910args in a subprocess with the supplied environment. 911If mode == P_NOWAIT return the pid of the process. 912If mode == P_WAIT return the process's exit code if it exits normally; 913otherwise return -SIG, where SIG is the signal that killed it. """ 914 return _spawnvef(mode, file, args, env, execvpe) 915 916 917 __all__.extend(["spawnv", "spawnve", "spawnvp", "spawnvpe"]) 918 919 920if _exists("spawnv"): 921 # These aren't supplied by the basic Windows code 922 # but can be easily implemented in Python 923 924 def spawnl(mode, file, *args): 925 """spawnl(mode, file, *args) -> integer 926 927Execute file with arguments from args in a subprocess. 928If mode == P_NOWAIT return the pid of the process. 929If mode == P_WAIT return the process's exit code if it exits normally; 930otherwise return -SIG, where SIG is the signal that killed it. """ 931 return spawnv(mode, file, args) 932 933 def spawnle(mode, file, *args): 934 """spawnle(mode, file, *args, env) -> integer 935 936Execute file with arguments from args in a subprocess with the 937supplied environment. 938If mode == P_NOWAIT return the pid of the process. 939If mode == P_WAIT return the process's exit code if it exits normally; 940otherwise return -SIG, where SIG is the signal that killed it. """ 941 env = args[-1] 942 return spawnve(mode, file, args[:-1], env) 943 944 945 __all__.extend(["spawnl", "spawnle"]) 946 947 948if _exists("spawnvp"): 949 # At the moment, Windows doesn't implement spawnvp[e], 950 # so it won't have spawnlp[e] either. 951 def spawnlp(mode, file, *args): 952 """spawnlp(mode, file, *args) -> integer 953 954Execute file (which is looked for along $PATH) with arguments from 955args in a subprocess with the supplied environment. 956If mode == P_NOWAIT return the pid of the process. 957If mode == P_WAIT return the process's exit code if it exits normally; 958otherwise return -SIG, where SIG is the signal that killed it. """ 959 return spawnvp(mode, file, args) 960 961 def spawnlpe(mode, file, *args): 962 """spawnlpe(mode, file, *args, env) -> integer 963 964Execute file (which is looked for along $PATH) with arguments from 965args in a subprocess with the supplied environment. 966If mode == P_NOWAIT return the pid of the process. 967If mode == P_WAIT return the process's exit code if it exits normally; 968otherwise return -SIG, where SIG is the signal that killed it. """ 969 env = args[-1] 970 return spawnvpe(mode, file, args[:-1], env) 971 972 973 __all__.extend(["spawnlp", "spawnlpe"]) 974 975 976# Supply os.popen() 977def 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, 988 stdout=subprocess.PIPE, 989 bufsize=buffering) 990 return _wrap_close(io.TextIOWrapper(proc.stdout), proc) 991 else: 992 proc = subprocess.Popen(cmd, 993 shell=True, 994 stdin=subprocess.PIPE, 995 bufsize=buffering) 996 return _wrap_close(io.TextIOWrapper(proc.stdin), proc) 997 998# Helper for popen() -- a proxy for a file whose close waits for the process 999class _wrap_close: 1000 def __init__(self, stream, proc): 1001 self._stream = stream 1002 self._proc = proc 1003 def close(self): 1004 self._stream.close() 1005 returncode = self._proc.wait() 1006 if returncode == 0: 1007 return None 1008 if name == 'nt': 1009 return returncode 1010 else: 1011 return returncode << 8 # Shift left to match old behavior 1012 def __enter__(self): 1013 return self 1014 def __exit__(self, *args): 1015 self.close() 1016 def __getattr__(self, name): 1017 return getattr(self._stream, name) 1018 def __iter__(self): 1019 return iter(self._stream) 1020 1021# Supply os.fdopen() 1022def fdopen(fd, *args, **kwargs): 1023 if not isinstance(fd, int): 1024 raise TypeError("invalid fd type (%s, expected integer)" % type(fd)) 1025 import io 1026 return io.open(fd, *args, **kwargs) 1027 1028 1029# For testing purposes, make sure the function is available when the C 1030# implementation exists. 1031def _fspath(path): 1032 """Return the path representation of a path-like object. 1033 1034 If str or bytes is passed in, it is returned unchanged. Otherwise the 1035 os.PathLike interface is used to get the path representation. If the 1036 path representation is not str or bytes, TypeError is raised. If the 1037 provided path is not str, bytes, or os.PathLike, TypeError is raised. 1038 """ 1039 if isinstance(path, (str, bytes)): 1040 return path 1041 1042 # Work from the object's type to match method resolution of other magic 1043 # methods. 1044 path_type = type(path) 1045 try: 1046 path_repr = path_type.__fspath__(path) 1047 except AttributeError: 1048 if hasattr(path_type, '__fspath__'): 1049 raise 1050 else: 1051 raise TypeError("expected str, bytes or os.PathLike object, " 1052 "not " + path_type.__name__) 1053 if isinstance(path_repr, (str, bytes)): 1054 return path_repr 1055 else: 1056 raise TypeError("expected {}.__fspath__() to return str or bytes, " 1057 "not {}".format(path_type.__name__, 1058 type(path_repr).__name__)) 1059 1060# If there is no C implementation, make the pure Python version the 1061# implementation as transparently as possible. 1062if not _exists('fspath'): 1063 fspath = _fspath 1064 fspath.__name__ = "fspath" 1065 1066 1067class PathLike(abc.ABC): 1068 1069 """Abstract base class for implementing the file system path protocol.""" 1070 1071 @abc.abstractmethod 1072 def __fspath__(self): 1073 """Return the file system path representation of the object.""" 1074 raise NotImplementedError 1075 1076 @classmethod 1077 def __subclasshook__(cls, subclass): 1078 return hasattr(subclass, '__fspath__') 1079