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