ยปCore Development>Code coverage>Lib/os.py

Python code coverage for Lib/os.py

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