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