Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/os.py: 6%

569 statements  

« prev     ^ index     » next       coverage.py v7.0.1, created at 2022-12-25 06:11 +0000

1r"""OS routines for NT or Posix depending on what system we're on. 

2 

3This exports: 

4 - all functions from posix or nt, e.g. unlink, stat, etc. 

5 - os.path is either posixpath or ntpath 

6 - os.name is either 'posix' or 'nt' 

7 - os.curdir is a string representing the current directory (always '.') 

8 - os.pardir is a string representing the parent directory (always '..') 

9 - os.sep is the (or a most common) pathname separator ('/' or '\\') 

10 - os.extsep is the extension separator (always '.') 

11 - os.altsep is the alternate pathname separator (None or '/') 

12 - os.pathsep is the component separator used in $PATH etc 

13 - os.linesep is the line separator in text files ('\r' or '\n' or '\r\n') 

14 - os.defpath is the default search path for executables 

15 - os.devnull is the file path of the null device ('/dev/null', etc.) 

16 

17Programs that import and use 'os' stand a better chance of being 

18portable between different platforms. Of course, they must then 

19only use functions that are defined by all platforms (e.g., unlink 

20and opendir), and leave all pathname manipulation to os.path 

21(e.g., split and join). 

22""" 

23 

24#' 

25import abc 

26import sys 

27import stat as st 

28 

29from _collections_abc import _check_methods 

30 

31_names = sys.builtin_module_names 

32 

33# Note: more names are added to __all__ later. 

34__all__ = ["altsep", "curdir", "pardir", "sep", "pathsep", "linesep", 

35 "defpath", "name", "path", "devnull", "SEEK_SET", "SEEK_CUR", 

36 "SEEK_END", "fsencode", "fsdecode", "get_exec_path", "fdopen", 

37 "popen", "extsep"] 

38 

39def _exists(name): 

40 return name in globals() 

41 

42def _get_exports_list(module): 

43 try: 

44 return list(module.__all__) 

45 except AttributeError: 

46 return [n for n in dir(module) if n[0] != '_'] 

47 

48# Any new dependencies of the os module and/or changes in path separator 

49# requires updating importlib as well. 

50if 'posix' in _names: 

51 name = 'posix' 

52 linesep = '\n' 

53 from posix import * 

54 try: 

55 from posix import _exit 

56 __all__.append('_exit') 

57 except ImportError: 

58 pass 

59 import posixpath as path 

60 

61 try: 

62 from posix import _have_functions 

63 except ImportError: 

64 pass 

65 

66 import posix 

67 __all__.extend(_get_exports_list(posix)) 

68 del posix 

69 

70elif 'nt' in _names: 

71 name = 'nt' 

72 linesep = '\r\n' 

73 from nt import * 

74 try: 

75 from nt import _exit 

76 __all__.append('_exit') 

77 except ImportError: 

78 pass 

79 import ntpath as path 

80 

81 import nt 

82 __all__.extend(_get_exports_list(nt)) 

83 del nt 

84 

85 try: 

86 from nt import _have_functions 

87 except ImportError: 

88 pass 

89 

90else: 

91 raise ImportError('no os specific module found') 

92 

93sys.modules['os.path'] = path 

94from os.path import (curdir, pardir, sep, pathsep, defpath, extsep, altsep, 

95 devnull) 

96 

97del _names 

98 

99 

100if _exists("_have_functions"): 

101 _globals = globals() 

102 def _add(str, fn): 

103 if (fn in _globals) and (str in _have_functions): 

104 _set.add(_globals[fn]) 

105 

106 _set = set() 

107 _add("HAVE_FACCESSAT", "access") 

108 _add("HAVE_FCHMODAT", "chmod") 

109 _add("HAVE_FCHOWNAT", "chown") 

110 _add("HAVE_FSTATAT", "stat") 

111 _add("HAVE_FUTIMESAT", "utime") 

112 _add("HAVE_LINKAT", "link") 

113 _add("HAVE_MKDIRAT", "mkdir") 

114 _add("HAVE_MKFIFOAT", "mkfifo") 

115 _add("HAVE_MKNODAT", "mknod") 

116 _add("HAVE_OPENAT", "open") 

117 _add("HAVE_READLINKAT", "readlink") 

118 _add("HAVE_RENAMEAT", "rename") 

119 _add("HAVE_SYMLINKAT", "symlink") 

120 _add("HAVE_UNLINKAT", "unlink") 

121 _add("HAVE_UNLINKAT", "rmdir") 

122 _add("HAVE_UTIMENSAT", "utime") 

123 supports_dir_fd = _set 

124 

125 _set = set() 

126 _add("HAVE_FACCESSAT", "access") 

127 supports_effective_ids = _set 

128 

129 _set = set() 

130 _add("HAVE_FCHDIR", "chdir") 

131 _add("HAVE_FCHMOD", "chmod") 

132 _add("HAVE_FCHOWN", "chown") 

133 _add("HAVE_FDOPENDIR", "listdir") 

134 _add("HAVE_FDOPENDIR", "scandir") 

135 _add("HAVE_FEXECVE", "execve") 

136 _set.add(stat) # fstat always works 

137 _add("HAVE_FTRUNCATE", "truncate") 

138 _add("HAVE_FUTIMENS", "utime") 

139 _add("HAVE_FUTIMES", "utime") 

140 _add("HAVE_FPATHCONF", "pathconf") 

141 if _exists("statvfs") and _exists("fstatvfs"): # mac os x10.3 

142 _add("HAVE_FSTATVFS", "statvfs") 

143 supports_fd = _set 

144 

145 _set = set() 

146 _add("HAVE_FACCESSAT", "access") 

147 # Some platforms don't support lchmod(). Often the function exists 

148 # anyway, as a stub that always returns ENOSUP or perhaps EOPNOTSUPP. 

149 # (No, I don't know why that's a good design.) ./configure will detect 

150 # this and reject it--so HAVE_LCHMOD still won't be defined on such 

151 # platforms. This is Very Helpful. 

152 # 

153 # However, sometimes platforms without a working lchmod() *do* have 

154 # fchmodat(). (Examples: Linux kernel 3.2 with glibc 2.15, 

155 # OpenIndiana 3.x.) And fchmodat() has a flag that theoretically makes 

156 # it behave like lchmod(). So in theory it would be a suitable 

157 # replacement for lchmod(). But when lchmod() doesn't work, fchmodat()'s 

158 # flag doesn't work *either*. Sadly ./configure isn't sophisticated 

159 # enough to detect this condition--it only determines whether or not 

160 # fchmodat() minimally works. 

161 # 

162 # Therefore we simply ignore fchmodat() when deciding whether or not 

163 # os.chmod supports follow_symlinks. Just checking lchmod() is 

164 # sufficient. After all--if you have a working fchmodat(), your 

165 # lchmod() almost certainly works too. 

166 # 

167 # _add("HAVE_FCHMODAT", "chmod") 

168 _add("HAVE_FCHOWNAT", "chown") 

169 _add("HAVE_FSTATAT", "stat") 

170 _add("HAVE_LCHFLAGS", "chflags") 

171 _add("HAVE_LCHMOD", "chmod") 

172 if _exists("lchown"): # mac os x10.3 

173 _add("HAVE_LCHOWN", "chown") 

174 _add("HAVE_LINKAT", "link") 

175 _add("HAVE_LUTIMES", "utime") 

176 _add("HAVE_LSTAT", "stat") 

177 _add("HAVE_FSTATAT", "stat") 

178 _add("HAVE_UTIMENSAT", "utime") 

179 _add("MS_WINDOWS", "stat") 

180 supports_follow_symlinks = _set 

181 

182 del _set 

183 del _have_functions 

184 del _globals 

185 del _add 

186 

187 

188# Python uses fixed values for the SEEK_ constants; they are mapped 

189# to native constants if necessary in posixmodule.c 

190# Other possible SEEK values are directly imported from posixmodule.c 

191SEEK_SET = 0 

192SEEK_CUR = 1 

193SEEK_END = 2 

194 

195# Super directory utilities. 

196# (Inspired by Eric Raymond; the doc strings are mostly his) 

197 

198def makedirs(name, mode=0o777, exist_ok=False): 

199 """makedirs(name [, mode=0o777][, exist_ok=False]) 

200 

201 Super-mkdir; create a leaf directory and all intermediate ones. Works like 

202 mkdir, except that any intermediate path segment (not just the rightmost) 

203 will be created if it does not exist. If the target directory already 

204 exists, raise an OSError if exist_ok is False. Otherwise no exception is 

205 raised. This is recursive. 

206 

207 """ 

208 head, tail = path.split(name) 

209 if not tail: 

210 head, tail = path.split(head) 

211 if head and tail and not path.exists(head): 

212 try: 

213 makedirs(head, exist_ok=exist_ok) 

214 except FileExistsError: 

215 # Defeats race condition when another thread created the path 

216 pass 

217 cdir = curdir 

218 if isinstance(tail, bytes): 

219 cdir = bytes(curdir, 'ASCII') 

220 if tail == cdir: # xxx/newdir/. exists if xxx/newdir exists 

221 return 

222 try: 

223 mkdir(name, mode) 

224 except OSError: 

225 # Cannot rely on checking for EEXIST, since the operating system 

226 # could give priority to other errors like EACCES or EROFS 

227 if not exist_ok or not path.isdir(name): 

228 raise 

229 

230def removedirs(name): 

231 """removedirs(name) 

232 

233 Super-rmdir; remove a leaf directory and all empty intermediate 

234 ones. Works like rmdir except that, if the leaf directory is 

235 successfully removed, directories corresponding to rightmost path 

236 segments will be pruned away until either the whole path is 

237 consumed or an error occurs. Errors during this latter phase are 

238 ignored -- they generally mean that a directory was not empty. 

239 

240 """ 

241 rmdir(name) 

242 head, tail = path.split(name) 

243 if not tail: 

244 head, tail = path.split(head) 

245 while head and tail: 

246 try: 

247 rmdir(head) 

248 except OSError: 

249 break 

250 head, tail = path.split(head) 

251 

252def renames(old, new): 

253 """renames(old, new) 

254 

255 Super-rename; create directories as necessary and delete any left 

256 empty. Works like rename, except creation of any intermediate 

257 directories needed to make the new pathname good is attempted 

258 first. After the rename, directories corresponding to rightmost 

259 path segments of the old name will be pruned until either the 

260 whole path is consumed or a nonempty directory is found. 

261 

262 Note: this function can fail with the new directory structure made 

263 if you lack permissions needed to unlink the leaf directory or 

264 file. 

265 

266 """ 

267 head, tail = path.split(new) 

268 if head and tail and not path.exists(head): 

269 makedirs(head) 

270 rename(old, new) 

271 head, tail = path.split(old) 

272 if head and tail: 

273 try: 

274 removedirs(head) 

275 except OSError: 

276 pass 

277 

278__all__.extend(["makedirs", "removedirs", "renames"]) 

279 

280def walk(top, topdown=True, onerror=None, followlinks=False): 

281 """Directory tree generator. 

282 

283 For each directory in the directory tree rooted at top (including top 

284 itself, but excluding '.' and '..'), yields a 3-tuple 

285 

286 dirpath, dirnames, filenames 

287 

288 dirpath is a string, the path to the directory. dirnames is a list of 

289 the names of the subdirectories in dirpath (excluding '.' and '..'). 

290 filenames is a list of the names of the non-directory files in dirpath. 

291 Note that the names in the lists are just names, with no path components. 

292 To get a full path (which begins with top) to a file or directory in 

293 dirpath, do os.path.join(dirpath, name). 

294 

295 If optional arg 'topdown' is true or not specified, the triple for a 

296 directory is generated before the triples for any of its subdirectories 

297 (directories are generated top down). If topdown is false, the triple 

298 for a directory is generated after the triples for all of its 

299 subdirectories (directories are generated bottom up). 

300 

301 When topdown is true, the caller can modify the dirnames list in-place 

302 (e.g., via del or slice assignment), and walk will only recurse into the 

303 subdirectories whose names remain in dirnames; this can be used to prune the 

304 search, or to impose a specific order of visiting. Modifying dirnames when 

305 topdown is false has no effect on the behavior of os.walk(), since the 

306 directories in dirnames have already been generated by the time dirnames 

307 itself is generated. No matter the value of topdown, the list of 

308 subdirectories is retrieved before the tuples for the directory and its 

309 subdirectories are generated. 

310 

311 By default errors from the os.scandir() call are ignored. If 

312 optional arg 'onerror' is specified, it should be a function; it 

313 will be called with one argument, an OSError instance. It can 

314 report the error to continue with the walk, or raise the exception 

315 to abort the walk. Note that the filename is available as the 

316 filename attribute of the exception object. 

317 

318 By default, os.walk does not follow symbolic links to subdirectories on 

319 systems that support them. In order to get this functionality, set the 

320 optional argument 'followlinks' to true. 

321 

322 Caution: if you pass a relative pathname for top, don't change the 

323 current working directory between resumptions of walk. walk never 

324 changes the current directory, and assumes that the client doesn't 

325 either. 

326 

327 Example: 

328 

329 import os 

330 from os.path import join, getsize 

331 for root, dirs, files in os.walk('python/Lib/email'): 

332 print(root, "consumes", end="") 

333 print(sum(getsize(join(root, name)) for name in files), end="") 

334 print("bytes in", len(files), "non-directory files") 

335 if 'CVS' in dirs: 

336 dirs.remove('CVS') # don't visit CVS directories 

337 

338 """ 

339 top = fspath(top) 

340 dirs = [] 

341 nondirs = [] 

342 walk_dirs = [] 

343 

344 # We may not have read permission for top, in which case we can't 

345 # get a list of the files the directory contains. os.walk 

346 # always suppressed the exception then, rather than blow up for a 

347 # minor reason when (say) a thousand readable directories are still 

348 # left to visit. That logic is copied here. 

349 try: 

350 # Note that scandir is global in this module due 

351 # to earlier import-*. 

352 scandir_it = scandir(top) 

353 except OSError as error: 

354 if onerror is not None: 

355 onerror(error) 

356 return 

357 

358 with scandir_it: 

359 while True: 

360 try: 

361 try: 

362 entry = next(scandir_it) 

363 except StopIteration: 

364 break 

365 except OSError as error: 

366 if onerror is not None: 

367 onerror(error) 

368 return 

369 

370 try: 

371 is_dir = entry.is_dir() 

372 except OSError: 

373 # If is_dir() raises an OSError, consider that the entry is not 

374 # a directory, same behaviour than os.path.isdir(). 

375 is_dir = False 

376 

377 if is_dir: 

378 dirs.append(entry.name) 

379 else: 

380 nondirs.append(entry.name) 

381 

382 if not topdown and is_dir: 

383 # Bottom-up: recurse into sub-directory, but exclude symlinks to 

384 # directories if followlinks is False 

385 if followlinks: 

386 walk_into = True 

387 else: 

388 try: 

389 is_symlink = entry.is_symlink() 

390 except OSError: 

391 # If is_symlink() raises an OSError, consider that the 

392 # entry is not a symbolic link, same behaviour than 

393 # os.path.islink(). 

394 is_symlink = False 

395 walk_into = not is_symlink 

396 

397 if walk_into: 

398 walk_dirs.append(entry.path) 

399 

400 # Yield before recursion if going top down 

401 if topdown: 

402 yield top, dirs, nondirs 

403 

404 # Recurse into sub-directories 

405 islink, join = path.islink, path.join 

406 for dirname in dirs: 

407 new_path = join(top, dirname) 

408 # Issue #23605: os.path.islink() is used instead of caching 

409 # entry.is_symlink() result during the loop on os.scandir() because 

410 # the caller can replace the directory entry during the "yield" 

411 # above. 

412 if followlinks or not islink(new_path): 

413 yield from walk(new_path, topdown, onerror, followlinks) 

414 else: 

415 # Recurse into sub-directories 

416 for new_path in walk_dirs: 

417 yield from walk(new_path, topdown, onerror, followlinks) 

418 # Yield after recursion if going bottom up 

419 yield top, dirs, nondirs 

420 

421__all__.append("walk") 

422 

423if {open, stat} <= supports_dir_fd and {scandir, stat} <= supports_fd: 

424 

425 def fwalk(top=".", topdown=True, onerror=None, *, follow_symlinks=False, dir_fd=None): 

426 """Directory tree generator. 

427 

428 This behaves exactly like walk(), except that it yields a 4-tuple 

429 

430 dirpath, dirnames, filenames, dirfd 

431 

432 `dirpath`, `dirnames` and `filenames` are identical to walk() output, 

433 and `dirfd` is a file descriptor referring to the directory `dirpath`. 

434 

435 The advantage of fwalk() over walk() is that it's safe against symlink 

436 races (when follow_symlinks is False). 

437 

438 If dir_fd is not None, it should be a file descriptor open to a directory, 

439 and top should be relative; top will then be relative to that directory. 

440 (dir_fd is always supported for fwalk.) 

441 

442 Caution: 

443 Since fwalk() yields file descriptors, those are only valid until the 

444 next iteration step, so you should dup() them if you want to keep them 

445 for a longer period. 

446 

447 Example: 

448 

449 import os 

450 for root, dirs, files, rootfd in os.fwalk('python/Lib/email'): 

451 print(root, "consumes", end="") 

452 print(sum(os.stat(name, dir_fd=rootfd).st_size for name in files), 

453 end="") 

454 print("bytes in", len(files), "non-directory files") 

455 if 'CVS' in dirs: 

456 dirs.remove('CVS') # don't visit CVS directories 

457 """ 

458 if not isinstance(top, int) or not hasattr(top, '__index__'): 

459 top = fspath(top) 

460 # Note: To guard against symlink races, we use the standard 

461 # lstat()/open()/fstat() trick. 

462 if not follow_symlinks: 

463 orig_st = stat(top, follow_symlinks=False, dir_fd=dir_fd) 

464 topfd = open(top, O_RDONLY, dir_fd=dir_fd) 

465 try: 

466 if (follow_symlinks or (st.S_ISDIR(orig_st.st_mode) and 

467 path.samestat(orig_st, stat(topfd)))): 

468 yield from _fwalk(topfd, top, isinstance(top, bytes), 

469 topdown, onerror, follow_symlinks) 

470 finally: 

471 close(topfd) 

472 

473 def _fwalk(topfd, toppath, isbytes, topdown, onerror, follow_symlinks): 

474 # Note: This uses O(depth of the directory tree) file descriptors: if 

475 # necessary, it can be adapted to only require O(1) FDs, see issue 

476 # #13734. 

477 

478 scandir_it = scandir(topfd) 

479 dirs = [] 

480 nondirs = [] 

481 entries = None if topdown or follow_symlinks else [] 

482 for entry in scandir_it: 

483 name = entry.name 

484 if isbytes: 

485 name = fsencode(name) 

486 try: 

487 if entry.is_dir(): 

488 dirs.append(name) 

489 if entries is not None: 

490 entries.append(entry) 

491 else: 

492 nondirs.append(name) 

493 except OSError: 

494 try: 

495 # Add dangling symlinks, ignore disappeared files 

496 if entry.is_symlink(): 

497 nondirs.append(name) 

498 except OSError: 

499 pass 

500 

501 if topdown: 

502 yield toppath, dirs, nondirs, topfd 

503 

504 for name in dirs if entries is None else zip(dirs, entries): 

505 try: 

506 if not follow_symlinks: 

507 if topdown: 

508 orig_st = stat(name, dir_fd=topfd, follow_symlinks=False) 

509 else: 

510 assert entries is not None 

511 name, entry = name 

512 orig_st = entry.stat(follow_symlinks=False) 

513 dirfd = open(name, O_RDONLY, dir_fd=topfd) 

514 except OSError as err: 

515 if onerror is not None: 

516 onerror(err) 

517 continue 

518 try: 

519 if follow_symlinks or path.samestat(orig_st, stat(dirfd)): 

520 dirpath = path.join(toppath, name) 

521 yield from _fwalk(dirfd, dirpath, isbytes, 

522 topdown, onerror, follow_symlinks) 

523 finally: 

524 close(dirfd) 

525 

526 if not topdown: 

527 yield toppath, dirs, nondirs, topfd 

528 

529 __all__.append("fwalk") 

530 

531def execl(file, *args): 

532 """execl(file, *args) 

533 

534 Execute the executable file with argument list args, replacing the 

535 current process. """ 

536 execv(file, args) 

537 

538def execle(file, *args): 

539 """execle(file, *args, env) 

540 

541 Execute the executable file with argument list args and 

542 environment env, replacing the current process. """ 

543 env = args[-1] 

544 execve(file, args[:-1], env) 

545 

546def execlp(file, *args): 

547 """execlp(file, *args) 

548 

549 Execute the executable file (which is searched for along $PATH) 

550 with argument list args, replacing the current process. """ 

551 execvp(file, args) 

552 

553def execlpe(file, *args): 

554 """execlpe(file, *args, env) 

555 

556 Execute the executable file (which is searched for along $PATH) 

557 with argument list args and environment env, replacing the current 

558 process. """ 

559 env = args[-1] 

560 execvpe(file, args[:-1], env) 

561 

562def execvp(file, args): 

563 """execvp(file, args) 

564 

565 Execute the executable file (which is searched for along $PATH) 

566 with argument list args, replacing the current process. 

567 args may be a list or tuple of strings. """ 

568 _execvpe(file, args) 

569 

570def execvpe(file, args, env): 

571 """execvpe(file, args, env) 

572 

573 Execute the executable file (which is searched for along $PATH) 

574 with argument list args and environment env, replacing the 

575 current process. 

576 args may be a list or tuple of strings. """ 

577 _execvpe(file, args, env) 

578 

579__all__.extend(["execl","execle","execlp","execlpe","execvp","execvpe"]) 

580 

581def _execvpe(file, args, env=None): 

582 if env is not None: 

583 exec_func = execve 

584 argrest = (args, env) 

585 else: 

586 exec_func = execv 

587 argrest = (args,) 

588 env = environ 

589 

590 if path.dirname(file): 

591 exec_func(file, *argrest) 

592 return 

593 saved_exc = None 

594 path_list = get_exec_path(env) 

595 if name != 'nt': 

596 file = fsencode(file) 

597 path_list = map(fsencode, path_list) 

598 for dir in path_list: 

599 fullname = path.join(dir, file) 

600 try: 

601 exec_func(fullname, *argrest) 

602 except (FileNotFoundError, NotADirectoryError) as e: 

603 last_exc = e 

604 except OSError as e: 

605 last_exc = e 

606 if saved_exc is None: 

607 saved_exc = e 

608 if saved_exc is not None: 

609 raise saved_exc 

610 raise last_exc 

611 

612 

613def get_exec_path(env=None): 

614 """Returns the sequence of directories that will be searched for the 

615 named executable (similar to a shell) when launching a process. 

616 

617 *env* must be an environment variable dict or None. If *env* is None, 

618 os.environ will be used. 

619 """ 

620 # Use a local import instead of a global import to limit the number of 

621 # modules loaded at startup: the os module is always loaded at startup by 

622 # Python. It may also avoid a bootstrap issue. 

623 import warnings 

624 

625 if env is None: 

626 env = environ 

627 

628 # {b'PATH': ...}.get('PATH') and {'PATH': ...}.get(b'PATH') emit a 

629 # BytesWarning when using python -b or python -bb: ignore the warning 

630 with warnings.catch_warnings(): 

631 warnings.simplefilter("ignore", BytesWarning) 

632 

633 try: 

634 path_list = env.get('PATH') 

635 except TypeError: 

636 path_list = None 

637 

638 if supports_bytes_environ: 

639 try: 

640 path_listb = env[b'PATH'] 

641 except (KeyError, TypeError): 

642 pass 

643 else: 

644 if path_list is not None: 

645 raise ValueError( 

646 "env cannot contain 'PATH' and b'PATH' keys") 

647 path_list = path_listb 

648 

649 if path_list is not None and isinstance(path_list, bytes): 

650 path_list = fsdecode(path_list) 

651 

652 if path_list is None: 

653 path_list = defpath 

654 return path_list.split(pathsep) 

655 

656 

657# Change environ to automatically call putenv(), unsetenv if they exist. 

658from _collections_abc import MutableMapping 

659 

660class _Environ(MutableMapping): 

661 def __init__(self, data, encodekey, decodekey, encodevalue, decodevalue, putenv, unsetenv): 

662 self.encodekey = encodekey 

663 self.decodekey = decodekey 

664 self.encodevalue = encodevalue 

665 self.decodevalue = decodevalue 

666 self.putenv = putenv 

667 self.unsetenv = unsetenv 

668 self._data = data 

669 

670 def __getitem__(self, key): 

671 try: 

672 value = self._data[self.encodekey(key)] 

673 except KeyError: 

674 # raise KeyError with the original key value 

675 raise KeyError(key) from None 

676 return self.decodevalue(value) 

677 

678 def __setitem__(self, key, value): 

679 key = self.encodekey(key) 

680 value = self.encodevalue(value) 

681 self.putenv(key, value) 

682 self._data[key] = value 

683 

684 def __delitem__(self, key): 

685 encodedkey = self.encodekey(key) 

686 self.unsetenv(encodedkey) 

687 try: 

688 del self._data[encodedkey] 

689 except KeyError: 

690 # raise KeyError with the original key value 

691 raise KeyError(key) from None 

692 

693 def __iter__(self): 

694 # list() from dict object is an atomic operation 

695 keys = list(self._data) 

696 for key in keys: 

697 yield self.decodekey(key) 

698 

699 def __len__(self): 

700 return len(self._data) 

701 

702 def __repr__(self): 

703 return 'environ({{{}}})'.format(', '.join( 

704 ('{!r}: {!r}'.format(self.decodekey(key), self.decodevalue(value)) 

705 for key, value in self._data.items()))) 

706 

707 def copy(self): 

708 return dict(self) 

709 

710 def setdefault(self, key, value): 

711 if key not in self: 

712 self[key] = value 

713 return self[key] 

714 

715try: 

716 _putenv = putenv 

717except NameError: 

718 _putenv = lambda key, value: None 

719else: 

720 if "putenv" not in __all__: 

721 __all__.append("putenv") 

722 

723try: 

724 _unsetenv = unsetenv 

725except NameError: 

726 _unsetenv = lambda key: _putenv(key, "") 

727else: 

728 if "unsetenv" not in __all__: 

729 __all__.append("unsetenv") 

730 

731def _createenviron(): 

732 if name == 'nt': 

733 # Where Env Var Names Must Be UPPERCASE 

734 def check_str(value): 

735 if not isinstance(value, str): 

736 raise TypeError("str expected, not %s" % type(value).__name__) 

737 return value 

738 encode = check_str 

739 decode = str 

740 def encodekey(key): 

741 return encode(key).upper() 

742 data = {} 

743 for key, value in environ.items(): 

744 data[encodekey(key)] = value 

745 else: 

746 # Where Env Var Names Can Be Mixed Case 

747 encoding = sys.getfilesystemencoding() 

748 def encode(value): 

749 if not isinstance(value, str): 

750 raise TypeError("str expected, not %s" % type(value).__name__) 

751 return value.encode(encoding, 'surrogateescape') 

752 def decode(value): 

753 return value.decode(encoding, 'surrogateescape') 

754 encodekey = encode 

755 data = environ 

756 return _Environ(data, 

757 encodekey, decode, 

758 encode, decode, 

759 _putenv, _unsetenv) 

760 

761# unicode environ 

762environ = _createenviron() 

763del _createenviron 

764 

765 

766def getenv(key, default=None): 

767 """Get an environment variable, return None if it doesn't exist. 

768 The optional second argument can specify an alternate default. 

769 key, default and the result are str.""" 

770 return environ.get(key, default) 

771 

772supports_bytes_environ = (name != 'nt') 

773__all__.extend(("getenv", "supports_bytes_environ")) 

774 

775if supports_bytes_environ: 

776 def _check_bytes(value): 

777 if not isinstance(value, bytes): 

778 raise TypeError("bytes expected, not %s" % type(value).__name__) 

779 return value 

780 

781 # bytes environ 

782 environb = _Environ(environ._data, 

783 _check_bytes, bytes, 

784 _check_bytes, bytes, 

785 _putenv, _unsetenv) 

786 del _check_bytes 

787 

788 def getenvb(key, default=None): 

789 """Get an environment variable, return None if it doesn't exist. 

790 The optional second argument can specify an alternate default. 

791 key, default and the result are bytes.""" 

792 return environb.get(key, default) 

793 

794 __all__.extend(("environb", "getenvb")) 

795 

796def _fscodec(): 

797 encoding = sys.getfilesystemencoding() 

798 errors = sys.getfilesystemencodeerrors() 

799 

800 def fsencode(filename): 

801 """Encode filename (an os.PathLike, bytes, or str) to the filesystem 

802 encoding with 'surrogateescape' error handler, return bytes unchanged. 

803 On Windows, use 'strict' error handler if the file system encoding is 

804 'mbcs' (which is the default encoding). 

805 """ 

806 filename = fspath(filename) # Does type-checking of `filename`. 

807 if isinstance(filename, str): 

808 return filename.encode(encoding, errors) 

809 else: 

810 return filename 

811 

812 def fsdecode(filename): 

813 """Decode filename (an os.PathLike, bytes, or str) from the filesystem 

814 encoding with 'surrogateescape' error handler, return str unchanged. On 

815 Windows, use 'strict' error handler if the file system encoding is 

816 'mbcs' (which is the default encoding). 

817 """ 

818 filename = fspath(filename) # Does type-checking of `filename`. 

819 if isinstance(filename, bytes): 

820 return filename.decode(encoding, errors) 

821 else: 

822 return filename 

823 

824 return fsencode, fsdecode 

825 

826fsencode, fsdecode = _fscodec() 

827del _fscodec 

828 

829# Supply spawn*() (probably only for Unix) 

830if _exists("fork") and not _exists("spawnv") and _exists("execv"): 

831 

832 P_WAIT = 0 

833 P_NOWAIT = P_NOWAITO = 1 

834 

835 __all__.extend(["P_WAIT", "P_NOWAIT", "P_NOWAITO"]) 

836 

837 # XXX Should we support P_DETACH? I suppose it could fork()**2 

838 # and close the std I/O streams. Also, P_OVERLAY is the same 

839 # as execv*()? 

840 

841 def _spawnvef(mode, file, args, env, func): 

842 # Internal helper; func is the exec*() function to use 

843 if not isinstance(args, (tuple, list)): 

844 raise TypeError('argv must be a tuple or a list') 

845 if not args or not args[0]: 

846 raise ValueError('argv first element cannot be empty') 

847 pid = fork() 

848 if not pid: 

849 # Child 

850 try: 

851 if env is None: 

852 func(file, args) 

853 else: 

854 func(file, args, env) 

855 except: 

856 _exit(127) 

857 else: 

858 # Parent 

859 if mode == P_NOWAIT: 

860 return pid # Caller is responsible for waiting! 

861 while 1: 

862 wpid, sts = waitpid(pid, 0) 

863 if WIFSTOPPED(sts): 

864 continue 

865 elif WIFSIGNALED(sts): 

866 return -WTERMSIG(sts) 

867 elif WIFEXITED(sts): 

868 return WEXITSTATUS(sts) 

869 else: 

870 raise OSError("Not stopped, signaled or exited???") 

871 

872 def spawnv(mode, file, args): 

873 """spawnv(mode, file, args) -> integer 

874 

875Execute file with arguments from args in a subprocess. 

876If mode == P_NOWAIT return the pid of the process. 

877If mode == P_WAIT return the process's exit code if it exits normally; 

878otherwise return -SIG, where SIG is the signal that killed it. """ 

879 return _spawnvef(mode, file, args, None, execv) 

880 

881 def spawnve(mode, file, args, env): 

882 """spawnve(mode, file, args, env) -> integer 

883 

884Execute file with arguments from args in a subprocess with the 

885specified environment. 

886If mode == P_NOWAIT return the pid of the process. 

887If mode == P_WAIT return the process's exit code if it exits normally; 

888otherwise return -SIG, where SIG is the signal that killed it. """ 

889 return _spawnvef(mode, file, args, env, execve) 

890 

891 # Note: spawnvp[e] isn't currently supported on Windows 

892 

893 def spawnvp(mode, file, args): 

894 """spawnvp(mode, file, args) -> integer 

895 

896Execute file (which is looked for along $PATH) with arguments from 

897args in a subprocess. 

898If mode == P_NOWAIT return the pid of the process. 

899If mode == P_WAIT return the process's exit code if it exits normally; 

900otherwise return -SIG, where SIG is the signal that killed it. """ 

901 return _spawnvef(mode, file, args, None, execvp) 

902 

903 def spawnvpe(mode, file, args, env): 

904 """spawnvpe(mode, file, args, env) -> integer 

905 

906Execute file (which is looked for along $PATH) with arguments from 

907args in a subprocess with the supplied environment. 

908If mode == P_NOWAIT return the pid of the process. 

909If mode == P_WAIT return the process's exit code if it exits normally; 

910otherwise return -SIG, where SIG is the signal that killed it. """ 

911 return _spawnvef(mode, file, args, env, execvpe) 

912 

913 

914 __all__.extend(["spawnv", "spawnve", "spawnvp", "spawnvpe"]) 

915 

916 

917if _exists("spawnv"): 

918 # These aren't supplied by the basic Windows code 

919 # but can be easily implemented in Python 

920 

921 def spawnl(mode, file, *args): 

922 """spawnl(mode, file, *args) -> integer 

923 

924Execute file with arguments from args in a subprocess. 

925If mode == P_NOWAIT return the pid of the process. 

926If mode == P_WAIT return the process's exit code if it exits normally; 

927otherwise return -SIG, where SIG is the signal that killed it. """ 

928 return spawnv(mode, file, args) 

929 

930 def spawnle(mode, file, *args): 

931 """spawnle(mode, file, *args, env) -> integer 

932 

933Execute file with arguments from args in a subprocess with the 

934supplied environment. 

935If mode == P_NOWAIT return the pid of the process. 

936If mode == P_WAIT return the process's exit code if it exits normally; 

937otherwise return -SIG, where SIG is the signal that killed it. """ 

938 env = args[-1] 

939 return spawnve(mode, file, args[:-1], env) 

940 

941 

942 __all__.extend(["spawnl", "spawnle"]) 

943 

944 

945if _exists("spawnvp"): 

946 # At the moment, Windows doesn't implement spawnvp[e], 

947 # so it won't have spawnlp[e] either. 

948 def spawnlp(mode, file, *args): 

949 """spawnlp(mode, file, *args) -> integer 

950 

951Execute file (which is looked for along $PATH) with arguments from 

952args in a subprocess with the supplied environment. 

953If mode == P_NOWAIT return the pid of the process. 

954If mode == P_WAIT return the process's exit code if it exits normally; 

955otherwise return -SIG, where SIG is the signal that killed it. """ 

956 return spawnvp(mode, file, args) 

957 

958 def spawnlpe(mode, file, *args): 

959 """spawnlpe(mode, file, *args, env) -> integer 

960 

961Execute file (which is looked for along $PATH) with arguments from 

962args in a subprocess with the supplied environment. 

963If mode == P_NOWAIT return the pid of the process. 

964If mode == P_WAIT return the process's exit code if it exits normally; 

965otherwise return -SIG, where SIG is the signal that killed it. """ 

966 env = args[-1] 

967 return spawnvpe(mode, file, args[:-1], env) 

968 

969 

970 __all__.extend(["spawnlp", "spawnlpe"]) 

971 

972 

973# Supply os.popen() 

974def popen(cmd, mode="r", buffering=-1): 

975 if not isinstance(cmd, str): 

976 raise TypeError("invalid cmd type (%s, expected string)" % type(cmd)) 

977 if mode not in ("r", "w"): 

978 raise ValueError("invalid mode %r" % mode) 

979 if buffering == 0 or buffering is None: 

980 raise ValueError("popen() does not support unbuffered streams") 

981 import subprocess, io 

982 if mode == "r": 

983 proc = subprocess.Popen(cmd, 

984 shell=True, 

985 stdout=subprocess.PIPE, 

986 bufsize=buffering) 

987 return _wrap_close(io.TextIOWrapper(proc.stdout), proc) 

988 else: 

989 proc = subprocess.Popen(cmd, 

990 shell=True, 

991 stdin=subprocess.PIPE, 

992 bufsize=buffering) 

993 return _wrap_close(io.TextIOWrapper(proc.stdin), proc) 

994 

995# Helper for popen() -- a proxy for a file whose close waits for the process 

996class _wrap_close: 

997 def __init__(self, stream, proc): 

998 self._stream = stream 

999 self._proc = proc 

1000 def close(self): 

1001 self._stream.close() 

1002 returncode = self._proc.wait() 

1003 if returncode == 0: 

1004 return None 

1005 if name == 'nt': 

1006 return returncode 

1007 else: 

1008 return returncode << 8 # Shift left to match old behavior 

1009 def __enter__(self): 

1010 return self 

1011 def __exit__(self, *args): 

1012 self.close() 

1013 def __getattr__(self, name): 

1014 return getattr(self._stream, name) 

1015 def __iter__(self): 

1016 return iter(self._stream) 

1017 

1018# Supply os.fdopen() 

1019def fdopen(fd, *args, **kwargs): 

1020 if not isinstance(fd, int): 

1021 raise TypeError("invalid fd type (%s, expected integer)" % type(fd)) 

1022 import io 

1023 return io.open(fd, *args, **kwargs) 

1024 

1025 

1026# For testing purposes, make sure the function is available when the C 

1027# implementation exists. 

1028def _fspath(path): 

1029 """Return the path representation of a path-like object. 

1030 

1031 If str or bytes is passed in, it is returned unchanged. Otherwise the 

1032 os.PathLike interface is used to get the path representation. If the 

1033 path representation is not str or bytes, TypeError is raised. If the 

1034 provided path is not str, bytes, or os.PathLike, TypeError is raised. 

1035 """ 

1036 if isinstance(path, (str, bytes)): 

1037 return path 

1038 

1039 # Work from the object's type to match method resolution of other magic 

1040 # methods. 

1041 path_type = type(path) 

1042 try: 

1043 path_repr = path_type.__fspath__(path) 

1044 except AttributeError: 

1045 if hasattr(path_type, '__fspath__'): 

1046 raise 

1047 else: 

1048 raise TypeError("expected str, bytes or os.PathLike object, " 

1049 "not " + path_type.__name__) 

1050 if isinstance(path_repr, (str, bytes)): 

1051 return path_repr 

1052 else: 

1053 raise TypeError("expected {}.__fspath__() to return str or bytes, " 

1054 "not {}".format(path_type.__name__, 

1055 type(path_repr).__name__)) 

1056 

1057# If there is no C implementation, make the pure Python version the 

1058# implementation as transparently as possible. 

1059if not _exists('fspath'): 

1060 fspath = _fspath 

1061 fspath.__name__ = "fspath" 

1062 

1063 

1064class PathLike(abc.ABC): 

1065 

1066 """Abstract base class for implementing the file system path protocol.""" 

1067 

1068 @abc.abstractmethod 

1069 def __fspath__(self): 

1070 """Return the file system path representation of the object.""" 

1071 raise NotImplementedError 

1072 

1073 @classmethod 

1074 def __subclasshook__(cls, subclass): 

1075 if cls is PathLike: 

1076 return _check_methods(subclass, '__fspath__') 

1077 return NotImplemented 

1078 

1079 

1080if name == 'nt': 

1081 class _AddedDllDirectory: 

1082 def __init__(self, path, cookie, remove_dll_directory): 

1083 self.path = path 

1084 self._cookie = cookie 

1085 self._remove_dll_directory = remove_dll_directory 

1086 def close(self): 

1087 self._remove_dll_directory(self._cookie) 

1088 self.path = None 

1089 def __enter__(self): 

1090 return self 

1091 def __exit__(self, *args): 

1092 self.close() 

1093 def __repr__(self): 

1094 if self.path: 

1095 return "<AddedDllDirectory({!r})>".format(self.path) 

1096 return "<AddedDllDirectory()>" 

1097 

1098 def add_dll_directory(path): 

1099 """Add a path to the DLL search path. 

1100 

1101 This search path is used when resolving dependencies for imported 

1102 extension modules (the module itself is resolved through sys.path), 

1103 and also by ctypes. 

1104 

1105 Remove the directory by calling close() on the returned object or 

1106 using it in a with statement. 

1107 """ 

1108 import nt 

1109 cookie = nt._add_dll_directory(path) 

1110 return _AddedDllDirectory( 

1111 path, 

1112 cookie, 

1113 nt._remove_dll_directory 

1114 )