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