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
« 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.
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.)
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"""
24#'
25import abc
26import sys
27import stat as st
29from _collections_abc import _check_methods
31_names = sys.builtin_module_names
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"]
39def _exists(name):
40 return name in globals()
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] != '_']
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
61 try:
62 from posix import _have_functions
63 except ImportError:
64 pass
66 import posix
67 __all__.extend(_get_exports_list(posix))
68 del posix
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
81 import nt
82 __all__.extend(_get_exports_list(nt))
83 del nt
85 try:
86 from nt import _have_functions
87 except ImportError:
88 pass
90else:
91 raise ImportError('no os specific module found')
93sys.modules['os.path'] = path
94from os.path import (curdir, pardir, sep, pathsep, defpath, extsep, altsep,
95 devnull)
97del _names
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])
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
125 _set = set()
126 _add("HAVE_FACCESSAT", "access")
127 supports_effective_ids = _set
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
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
182 del _set
183 del _have_functions
184 del _globals
185 del _add
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
195# Super directory utilities.
196# (Inspired by Eric Raymond; the doc strings are mostly his)
198def makedirs(name, mode=0o777, exist_ok=False):
199 """makedirs(name [, mode=0o777][, exist_ok=False])
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.
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
230def removedirs(name):
231 """removedirs(name)
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.
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)
252def renames(old, new):
253 """renames(old, new)
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.
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.
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
278__all__.extend(["makedirs", "removedirs", "renames"])
280def walk(top, topdown=True, onerror=None, followlinks=False):
281 """Directory tree generator.
283 For each directory in the directory tree rooted at top (including top
284 itself, but excluding '.' and '..'), yields a 3-tuple
286 dirpath, dirnames, filenames
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).
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).
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.
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.
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.
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.
327 Example:
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
338 """
339 top = fspath(top)
340 dirs = []
341 nondirs = []
342 walk_dirs = []
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
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
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
377 if is_dir:
378 dirs.append(entry.name)
379 else:
380 nondirs.append(entry.name)
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
397 if walk_into:
398 walk_dirs.append(entry.path)
400 # Yield before recursion if going top down
401 if topdown:
402 yield top, dirs, nondirs
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
421__all__.append("walk")
423if {open, stat} <= supports_dir_fd and {scandir, stat} <= supports_fd:
425 def fwalk(top=".", topdown=True, onerror=None, *, follow_symlinks=False, dir_fd=None):
426 """Directory tree generator.
428 This behaves exactly like walk(), except that it yields a 4-tuple
430 dirpath, dirnames, filenames, dirfd
432 `dirpath`, `dirnames` and `filenames` are identical to walk() output,
433 and `dirfd` is a file descriptor referring to the directory `dirpath`.
435 The advantage of fwalk() over walk() is that it's safe against symlink
436 races (when follow_symlinks is False).
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.)
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.
447 Example:
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)
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.
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
501 if topdown:
502 yield toppath, dirs, nondirs, topfd
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)
526 if not topdown:
527 yield toppath, dirs, nondirs, topfd
529 __all__.append("fwalk")
531def execl(file, *args):
532 """execl(file, *args)
534 Execute the executable file with argument list args, replacing the
535 current process. """
536 execv(file, args)
538def execle(file, *args):
539 """execle(file, *args, env)
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)
546def execlp(file, *args):
547 """execlp(file, *args)
549 Execute the executable file (which is searched for along $PATH)
550 with argument list args, replacing the current process. """
551 execvp(file, args)
553def execlpe(file, *args):
554 """execlpe(file, *args, env)
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)
562def execvp(file, args):
563 """execvp(file, args)
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)
570def execvpe(file, args, env):
571 """execvpe(file, args, env)
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)
579__all__.extend(["execl","execle","execlp","execlpe","execvp","execvpe"])
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
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
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.
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
625 if env is None:
626 env = environ
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)
633 try:
634 path_list = env.get('PATH')
635 except TypeError:
636 path_list = None
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
649 if path_list is not None and isinstance(path_list, bytes):
650 path_list = fsdecode(path_list)
652 if path_list is None:
653 path_list = defpath
654 return path_list.split(pathsep)
657# Change environ to automatically call putenv(), unsetenv if they exist.
658from _collections_abc import MutableMapping
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
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)
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
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
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)
699 def __len__(self):
700 return len(self._data)
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())))
707 def copy(self):
708 return dict(self)
710 def setdefault(self, key, value):
711 if key not in self:
712 self[key] = value
713 return self[key]
715try:
716 _putenv = putenv
717except NameError:
718 _putenv = lambda key, value: None
719else:
720 if "putenv" not in __all__:
721 __all__.append("putenv")
723try:
724 _unsetenv = unsetenv
725except NameError:
726 _unsetenv = lambda key: _putenv(key, "")
727else:
728 if "unsetenv" not in __all__:
729 __all__.append("unsetenv")
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)
761# unicode environ
762environ = _createenviron()
763del _createenviron
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)
772supports_bytes_environ = (name != 'nt')
773__all__.extend(("getenv", "supports_bytes_environ"))
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
781 # bytes environ
782 environb = _Environ(environ._data,
783 _check_bytes, bytes,
784 _check_bytes, bytes,
785 _putenv, _unsetenv)
786 del _check_bytes
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)
794 __all__.extend(("environb", "getenvb"))
796def _fscodec():
797 encoding = sys.getfilesystemencoding()
798 errors = sys.getfilesystemencodeerrors()
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
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
824 return fsencode, fsdecode
826fsencode, fsdecode = _fscodec()
827del _fscodec
829# Supply spawn*() (probably only for Unix)
830if _exists("fork") and not _exists("spawnv") and _exists("execv"):
832 P_WAIT = 0
833 P_NOWAIT = P_NOWAITO = 1
835 __all__.extend(["P_WAIT", "P_NOWAIT", "P_NOWAITO"])
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*()?
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???")
872 def spawnv(mode, file, args):
873 """spawnv(mode, file, args) -> integer
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)
881 def spawnve(mode, file, args, env):
882 """spawnve(mode, file, args, env) -> integer
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)
891 # Note: spawnvp[e] isn't currently supported on Windows
893 def spawnvp(mode, file, args):
894 """spawnvp(mode, file, args) -> integer
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)
903 def spawnvpe(mode, file, args, env):
904 """spawnvpe(mode, file, args, env) -> integer
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)
914 __all__.extend(["spawnv", "spawnve", "spawnvp", "spawnvpe"])
917if _exists("spawnv"):
918 # These aren't supplied by the basic Windows code
919 # but can be easily implemented in Python
921 def spawnl(mode, file, *args):
922 """spawnl(mode, file, *args) -> integer
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)
930 def spawnle(mode, file, *args):
931 """spawnle(mode, file, *args, env) -> integer
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)
942 __all__.extend(["spawnl", "spawnle"])
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
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)
958 def spawnlpe(mode, file, *args):
959 """spawnlpe(mode, file, *args, env) -> integer
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)
970 __all__.extend(["spawnlp", "spawnlpe"])
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)
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)
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)
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.
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
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__))
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"
1064class PathLike(abc.ABC):
1066 """Abstract base class for implementing the file system path protocol."""
1068 @abc.abstractmethod
1069 def __fspath__(self):
1070 """Return the file system path representation of the object."""
1071 raise NotImplementedError
1073 @classmethod
1074 def __subclasshook__(cls, subclass):
1075 if cls is PathLike:
1076 return _check_methods(subclass, '__fspath__')
1077 return NotImplemented
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()>"
1098 def add_dll_directory(path):
1099 """Add a path to the DLL search path.
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.
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 )