1r"""OS routines for NT or Posix depending on what system we're on.
2
3This exports:
4  - all functions from posix, nt, os2, or ce, e.g. unlink, stat, etc.
5  - os.path is one of the modules posixpath, or ntpath
6  - os.name is 'posix', 'nt', 'os2', 'ce' or 'riscos'
7  - os.curdir is a string representing the current directory ('.' or ':')
8  - os.pardir is a string representing the parent directory ('..' or '::')
9  - os.sep is the (or a most common) pathname separator ('/' or ':' or '\\')
10  - os.extsep is the extension separator ('.' or '/')
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#'
25
26import sys, errno
27
28_names = sys.builtin_module_names
29
30# Note:  more names are added to __all__ later.
31__all__ = ["altsep", "curdir", "pardir", "sep", "extsep", "pathsep", "linesep",
32           "defpath", "name", "path", "devnull",
33           "SEEK_SET", "SEEK_CUR", "SEEK_END"]
34
35def _get_exports_list(module):
36    try:
37        return list(module.__all__)
38    except AttributeError:
39        return [n for n in dir(module) if n[0] != '_']
40
41if 'posix' in _names:
42    name = 'posix'
43    linesep = '\n'
44    from posix import *
45    try:
46        from posix import _exit
47    except ImportError:
48        pass
49    import posixpath as path
50
51    import posix
52    __all__.extend(_get_exports_list(posix))
53    del posix
54
55elif 'nt' in _names:
56    name = 'nt'
57    linesep = '\r\n'
58    from nt import *
59    try:
60        from nt import _exit
61    except ImportError:
62        pass
63    import ntpath as path
64
65    import nt
66    __all__.extend(_get_exports_list(nt))
67    del nt
68
69elif 'os2' in _names:
70    name = 'os2'
71    linesep = '\r\n'
72    from os2 import *
73    try:
74        from os2 import _exit
75    except ImportError:
76        pass
77    if sys.version.find('EMX GCC') == -1:
78        import ntpath as path
79    else:
80        import os2emxpath as path
81        from _emx_link import link
82
83    import os2
84    __all__.extend(_get_exports_list(os2))
85    del os2
86
87elif 'ce' in _names:
88    name = 'ce'
89    linesep = '\r\n'
90    from ce import *
91    try:
92        from ce import _exit
93    except ImportError:
94        pass
95    # We can use the standard Windows path.
96    import ntpath as path
97
98    import ce
99    __all__.extend(_get_exports_list(ce))
100    del ce
101
102elif 'riscos' in _names:
103    name = 'riscos'
104    linesep = '\n'
105    from riscos import *
106    try:
107        from riscos import _exit
108    except ImportError:
109        pass
110    import riscospath as path
111
112    import riscos
113    __all__.extend(_get_exports_list(riscos))
114    del riscos
115
116else:
117    raise ImportError, 'no os specific module found'
118
119sys.modules['os.path'] = path
120from os.path import (curdir, pardir, sep, pathsep, defpath, extsep, altsep,
121    devnull)
122
123del _names
124
125# Python uses fixed values for the SEEK_ constants; they are mapped
126# to native constants if necessary in posixmodule.c
127SEEK_SET = 0
128SEEK_CUR = 1
129SEEK_END = 2
130
131#'
132
133# Super directory utilities.
134# (Inspired by Eric Raymond; the doc strings are mostly his)
135
136def makedirs(name, mode=0777):
137    """makedirs(path [, mode=0777])
138
139    Super-mkdir; create a leaf directory and all intermediate ones.
140    Works like mkdir, except that any intermediate path segment (not
141    just the rightmost) will be created if it does not exist.  This is
142    recursive.
143
144    """
145    head, tail = path.split(name)
146    if not tail:
147        head, tail = path.split(head)
148    if head and tail and not path.exists(head):
149        try:
150            makedirs(head, mode)
151        except OSError, e:
152            # be happy if someone already created the path
153            if e.errno != errno.EEXIST:
154                raise
155        if tail == curdir:           # xxx/newdir/. exists if xxx/newdir exists
156            return
157    mkdir(name, mode)
158
159def removedirs(name):
160    """removedirs(path)
161
162    Super-rmdir; remove a leaf directory and all empty intermediate
163    ones.  Works like rmdir except that, if the leaf directory is
164    successfully removed, directories corresponding to rightmost path
165    segments will be pruned away until either the whole path is
166    consumed or an error occurs.  Errors during this latter phase are
167    ignored -- they generally mean that a directory was not empty.
168
169    """
170    rmdir(name)
171    head, tail = path.split(name)
172    if not tail:
173        head, tail = path.split(head)
174    while head and tail:
175        try:
176            rmdir(head)
177        except error:
178            break
179        head, tail = path.split(head)
180
181def renames(old, new):
182    """renames(old, new)
183
184    Super-rename; create directories as necessary and delete any left
185    empty.  Works like rename, except creation of any intermediate
186    directories needed to make the new pathname good is attempted
187    first.  After the rename, directories corresponding to rightmost
188    path segments of the old name will be pruned until either the
189    whole path is consumed or a nonempty directory is found.
190
191    Note: this function can fail with the new directory structure made
192    if you lack permissions needed to unlink the leaf directory or
193    file.
194
195    """
196    head, tail = path.split(new)
197    if head and tail and not path.exists(head):
198        makedirs(head)
199    rename(old, new)
200    head, tail = path.split(old)
201    if head and tail:
202        try:
203            removedirs(head)
204        except error:
205            pass
206
207__all__.extend(["makedirs", "removedirs", "renames"])
208
209def walk(top, topdown=True, onerror=None, followlinks=False):
210    """Directory tree generator.
211
212    For each directory in the directory tree rooted at top (including top
213    itself, but excluding '.' and '..'), yields a 3-tuple
214
215        dirpath, dirnames, filenames
216
217    dirpath is a string, the path to the directory.  dirnames is a list of
218    the names of the subdirectories in dirpath (excluding '.' and '..').
219    filenames is a list of the names of the non-directory files in dirpath.
220    Note that the names in the lists are just names, with no path components.
221    To get a full path (which begins with top) to a file or directory in
222    dirpath, do os.path.join(dirpath, name).
223
224    If optional arg 'topdown' is true or not specified, the triple for a
225    directory is generated before the triples for any of its subdirectories
226    (directories are generated top down).  If topdown is false, the triple
227    for a directory is generated after the triples for all of its
228    subdirectories (directories are generated bottom up).
229
230    When topdown is true, the caller can modify the dirnames list in-place
231    (e.g., via del or slice assignment), and walk will only recurse into the
232    subdirectories whose names remain in dirnames; this can be used to prune the
233    search, or to impose a specific order of visiting.  Modifying dirnames when
234    topdown is false is ineffective, since the directories in dirnames have
235    already been generated by the time dirnames itself is generated. No matter
236    the value of topdown, the list of subdirectories is retrieved before the
237    tuples for the directory and its subdirectories are generated.
238
239    By default errors from the os.listdir() call are ignored.  If
240    optional arg 'onerror' is specified, it should be a function; it
241    will be called with one argument, an os.error instance.  It can
242    report the error to continue with the walk, or raise the exception
243    to abort the walk.  Note that the filename is available as the
244    filename attribute of the exception object.
245
246    By default, os.walk does not follow symbolic links to subdirectories on
247    systems that support them.  In order to get this functionality, set the
248    optional argument 'followlinks' to true.
249
250    Caution:  if you pass a relative pathname for top, don't change the
251    current working directory between resumptions of walk.  walk never
252    changes the current directory, and assumes that the client doesn't
253    either.
254
255    Example:
256
257    import os
258    from os.path import join, getsize
259    for root, dirs, files in os.walk('python/Lib/email'):
260        print root, "consumes",
261        print sum([getsize(join(root, name)) for name in files]),
262        print "bytes in", len(files), "non-directory files"
263        if 'CVS' in dirs:
264            dirs.remove('CVS')  # don't visit CVS directories
265
266    """
267
268    islink, join, isdir = path.islink, path.join, path.isdir
269
270    # We may not have read permission for top, in which case we can't
271    # get a list of the files the directory contains.  os.path.walk
272    # always suppressed the exception then, rather than blow up for a
273    # minor reason when (say) a thousand readable directories are still
274    # left to visit.  That logic is copied here.
275    try:
276        # Note that listdir and error are globals in this module due
277        # to earlier import-*.
278        names = listdir(top)
279    except error, err:
280        if onerror is not None:
281            onerror(err)
282        return
283
284    dirs, nondirs = [], []
285    for name in names:
286        if isdir(join(top, name)):
287            dirs.append(name)
288        else:
289            nondirs.append(name)
290
291    if topdown:
292        yield top, dirs, nondirs
293    for name in dirs:
294        new_path = join(top, name)
295        if followlinks or not islink(new_path):
296            for x in walk(new_path, topdown, onerror, followlinks):
297                yield x
298    if not topdown:
299        yield top, dirs, nondirs
300
301__all__.append("walk")
302
303# Make sure os.environ exists, at least
304try:
305    environ
306except NameError:
307    environ = {}
308
309def execl(file, *args):
310    """execl(file, *args)
311
312    Execute the executable file with argument list args, replacing the
313    current process. """
314    execv(file, args)
315
316def execle(file, *args):
317    """execle(file, *args, env)
318
319    Execute the executable file with argument list args and
320    environment env, replacing the current process. """
321    env = args[-1]
322    execve(file, args[:-1], env)
323
324def execlp(file, *args):
325    """execlp(file, *args)
326
327    Execute the executable file (which is searched for along $PATH)
328    with argument list args, replacing the current process. """
329    execvp(file, args)
330
331def execlpe(file, *args):
332    """execlpe(file, *args, env)
333
334    Execute the executable file (which is searched for along $PATH)
335    with argument list args and environment env, replacing the current
336    process. """
337    env = args[-1]
338    execvpe(file, args[:-1], env)
339
340def execvp(file, args):
341    """execvp(file, args)
342
343    Execute the executable file (which is searched for along $PATH)
344    with argument list args, replacing the current process.
345    args may be a list or tuple of strings. """
346    _execvpe(file, args)
347
348def execvpe(file, args, env):
349    """execvpe(file, args, env)
350
351    Execute the executable file (which is searched for along $PATH)
352    with argument list args and environment env , replacing the
353    current process.
354    args may be a list or tuple of strings. """
355    _execvpe(file, args, env)
356
357__all__.extend(["execl","execle","execlp","execlpe","execvp","execvpe"])
358
359def _execvpe(file, args, env=None):
360    if env is not None:
361        func = execve
362        argrest = (args, env)
363    else:
364        func = execv
365        argrest = (args,)
366        env = environ
367
368    head, tail = path.split(file)
369    if head:
370        func(file, *argrest)
371        return
372    if 'PATH' in env:
373        envpath = env['PATH']
374    else:
375        envpath = defpath
376    PATH = envpath.split(pathsep)
377    saved_exc = None
378    saved_tb = None
379    for dir in PATH:
380        fullname = path.join(dir, file)
381        try:
382            func(fullname, *argrest)
383        except error, e:
384            tb = sys.exc_info()[2]
385            if (e.errno != errno.ENOENT and e.errno != errno.ENOTDIR
386                and saved_exc is None):
387                saved_exc = e
388                saved_tb = tb
389    if saved_exc:
390        raise error, saved_exc, saved_tb
391    raise error, e, tb
392
393# Change environ to automatically call putenv() if it exists
394try:
395    # This will fail if there's no putenv
396    putenv
397except NameError:
398    pass
399else:
400    import UserDict
401
402    # Fake unsetenv() for Windows
403    # not sure about os2 here but
404    # I'm guessing they are the same.
405
406    if name in ('os2', 'nt'):
407        def unsetenv(key):
408            putenv(key, "")
409
410    if name == "riscos":
411        # On RISC OS, all env access goes through getenv and putenv
412        from riscosenviron import _Environ
413    elif name in ('os2', 'nt'):  # Where Env Var Names Must Be UPPERCASE
414        # But we store them as upper case
415        class _Environ(UserDict.IterableUserDict):
416            def __init__(self, environ):
417                UserDict.UserDict.__init__(self)
418                data = self.data
419                for k, v in environ.items():
420                    data[k.upper()] = v
421            def __setitem__(self, key, item):
422                putenv(key, item)
423                self.data[key.upper()] = item
424            def __getitem__(self, key):
425                return self.data[key.upper()]
426            try:
427                unsetenv
428            except NameError:
429                def __delitem__(self, key):
430                    del self.data[key.upper()]
431            else:
432                def __delitem__(self, key):
433                    unsetenv(key)
434                    del self.data[key.upper()]
435                def clear(self):
436                    for key in self.data.keys():
437                        unsetenv(key)
438                        del self.data[key]
439                def pop(self, key, *args):
440                    unsetenv(key)
441                    return self.data.pop(key.upper(), *args)
442            def has_key(self, key):
443                return key.upper() in self.data
444            def __contains__(self, key):
445                return key.upper() in self.data
446            def get(self, key, failobj=None):
447                return self.data.get(key.upper(), failobj)
448            def update(self, dict=None, **kwargs):
449                if dict:
450                    try:
451                        keys = dict.keys()
452                    except AttributeError:
453                        # List of (key, value)
454                        for k, v in dict:
455                            self[k] = v
456                    else:
457                        # got keys
458                        # cannot use items(), since mappings
459                        # may not have them.
460                        for k in keys:
461                            self[k] = dict[k]
462                if kwargs:
463                    self.update(kwargs)
464            def copy(self):
465                return dict(self)
466
467    else:  # Where Env Var Names Can Be Mixed Case
468        class _Environ(UserDict.IterableUserDict):
469            def __init__(self, environ):
470                UserDict.UserDict.__init__(self)
471                self.data = environ
472            def __setitem__(self, key, item):
473                putenv(key, item)
474                self.data[key] = item
475            def update(self,  dict=None, **kwargs):
476                if dict:
477                    try:
478                        keys = dict.keys()
479                    except AttributeError:
480                        # List of (key, value)
481                        for k, v in dict:
482                            self[k] = v
483                    else:
484                        # got keys
485                        # cannot use items(), since mappings
486                        # may not have them.
487                        for k in keys:
488                            self[k] = dict[k]
489                if kwargs:
490                    self.update(kwargs)
491            try:
492                unsetenv
493            except NameError:
494                pass
495            else:
496                def __delitem__(self, key):
497                    unsetenv(key)
498                    del self.data[key]
499                def clear(self):
500                    for key in self.data.keys():
501                        unsetenv(key)
502                        del self.data[key]
503                def pop(self, key, *args):
504                    unsetenv(key)
505                    return self.data.pop(key, *args)
506            def copy(self):
507                return dict(self)
508
509
510    environ = _Environ(environ)
511
512def getenv(key, default=None):
513    """Get an environment variable, return None if it doesn't exist.
514    The optional second argument can specify an alternate default."""
515    return environ.get(key, default)
516__all__.append("getenv")
517
518def _exists(name):
519    return name in globals()
520
521# Supply spawn*() (probably only for Unix)
522if _exists("fork") and not _exists("spawnv") and _exists("execv"):
523
524    P_WAIT = 0
525    P_NOWAIT = P_NOWAITO = 1
526
527    # XXX Should we support P_DETACH?  I suppose it could fork()**2
528    # and close the std I/O streams.  Also, P_OVERLAY is the same
529    # as execv*()?
530
531    def _spawnvef(mode, file, args, env, func):
532        # Internal helper; func is the exec*() function to use
533        pid = fork()
534        if not pid:
535            # Child
536            try:
537                if env is None:
538                    func(file, args)
539                else:
540                    func(file, args, env)
541            except:
542                _exit(127)
543        else:
544            # Parent
545            if mode == P_NOWAIT:
546                return pid # Caller is responsible for waiting!
547            while 1:
548                wpid, sts = waitpid(pid, 0)
549                if WIFSTOPPED(sts):
550                    continue
551                elif WIFSIGNALED(sts):
552                    return -WTERMSIG(sts)
553                elif WIFEXITED(sts):
554                    return WEXITSTATUS(sts)
555                else:
556                    raise error, "Not stopped, signaled or exited???"
557
558    def spawnv(mode, file, args):
559        """spawnv(mode, file, args) -> integer
560
561Execute file with arguments from args in a subprocess.
562If mode == P_NOWAIT return the pid of the process.
563If mode == P_WAIT return the process's exit code if it exits normally;
564otherwise return -SIG, where SIG is the signal that killed it. """
565        return _spawnvef(mode, file, args, None, execv)
566
567    def spawnve(mode, file, args, env):
568        """spawnve(mode, file, args, env) -> integer
569
570Execute file with arguments from args in a subprocess with the
571specified environment.
572If mode == P_NOWAIT return the pid of the process.
573If mode == P_WAIT return the process's exit code if it exits normally;
574otherwise return -SIG, where SIG is the signal that killed it. """
575        return _spawnvef(mode, file, args, env, execve)
576
577    # Note: spawnvp[e] is't currently supported on Windows
578
579    def spawnvp(mode, file, args):
580        """spawnvp(mode, file, args) -> integer
581
582Execute file (which is looked for along $PATH) with arguments from
583args in a subprocess.
584If mode == P_NOWAIT return the pid of the process.
585If mode == P_WAIT return the process's exit code if it exits normally;
586otherwise return -SIG, where SIG is the signal that killed it. """
587        return _spawnvef(mode, file, args, None, execvp)
588
589    def spawnvpe(mode, file, args, env):
590        """spawnvpe(mode, file, args, env) -> integer
591
592Execute file (which is looked for along $PATH) with arguments from
593args in a subprocess with the supplied environment.
594If mode == P_NOWAIT return the pid of the process.
595If mode == P_WAIT return the process's exit code if it exits normally;
596otherwise return -SIG, where SIG is the signal that killed it. """
597        return _spawnvef(mode, file, args, env, execvpe)
598
599if _exists("spawnv"):
600    # These aren't supplied by the basic Windows code
601    # but can be easily implemented in Python
602
603    def spawnl(mode, file, *args):
604        """spawnl(mode, file, *args) -> integer
605
606Execute file with arguments from args in a subprocess.
607If mode == P_NOWAIT return the pid of the process.
608If mode == P_WAIT return the process's exit code if it exits normally;
609otherwise return -SIG, where SIG is the signal that killed it. """
610        return spawnv(mode, file, args)
611
612    def spawnle(mode, file, *args):
613        """spawnle(mode, file, *args, env) -> integer
614
615Execute file with arguments from args in a subprocess with the
616supplied environment.
617If mode == P_NOWAIT return the pid of the process.
618If mode == P_WAIT return the process's exit code if it exits normally;
619otherwise return -SIG, where SIG is the signal that killed it. """
620        env = args[-1]
621        return spawnve(mode, file, args[:-1], env)
622
623
624    __all__.extend(["spawnv", "spawnve", "spawnl", "spawnle",])
625
626
627if _exists("spawnvp"):
628    # At the moment, Windows doesn't implement spawnvp[e],
629    # so it won't have spawnlp[e] either.
630    def spawnlp(mode, file, *args):
631        """spawnlp(mode, file, *args) -> integer
632
633Execute file (which is looked for along $PATH) with arguments from
634args in a subprocess with the supplied environment.
635If mode == P_NOWAIT return the pid of the process.
636If mode == P_WAIT return the process's exit code if it exits normally;
637otherwise return -SIG, where SIG is the signal that killed it. """
638        return spawnvp(mode, file, args)
639
640    def spawnlpe(mode, file, *args):
641        """spawnlpe(mode, file, *args, env) -> integer
642
643Execute file (which is looked for along $PATH) with arguments from
644args in a subprocess with the supplied environment.
645If mode == P_NOWAIT return the pid of the process.
646If mode == P_WAIT return the process's exit code if it exits normally;
647otherwise return -SIG, where SIG is the signal that killed it. """
648        env = args[-1]
649        return spawnvpe(mode, file, args[:-1], env)
650
651
652    __all__.extend(["spawnvp", "spawnvpe", "spawnlp", "spawnlpe",])
653
654
655# Supply popen2 etc. (for Unix)
656if _exists("fork"):
657    if not _exists("popen2"):
658        def popen2(cmd, mode="t", bufsize=-1):
659            """Execute the shell command 'cmd' in a sub-process.  On UNIX, 'cmd'
660            may be a sequence, in which case arguments will be passed directly to
661            the program without shell intervention (as with os.spawnv()).  If 'cmd'
662            is a string it will be passed to the shell (as with os.system()). If
663            'bufsize' is specified, it sets the buffer size for the I/O pipes.  The
664            file objects (child_stdin, child_stdout) are returned."""
665            import warnings
666            msg = "os.popen2 is deprecated.  Use the subprocess module."
667            warnings.warn(msg, DeprecationWarning, stacklevel=2)
668
669            import subprocess
670            PIPE = subprocess.PIPE
671            p = subprocess.Popen(cmd, shell=isinstance(cmd, basestring),
672                                 bufsize=bufsize, stdin=PIPE, stdout=PIPE,
673                                 close_fds=True)
674            return p.stdin, p.stdout
675        __all__.append("popen2")
676
677    if not _exists("popen3"):
678        def popen3(cmd, mode="t", bufsize=-1):
679            """Execute the shell command 'cmd' in a sub-process.  On UNIX, 'cmd'
680            may be a sequence, in which case arguments will be passed directly to
681            the program without shell intervention (as with os.spawnv()).  If 'cmd'
682            is a string it will be passed to the shell (as with os.system()). If
683            'bufsize' is specified, it sets the buffer size for the I/O pipes.  The
684            file objects (child_stdin, child_stdout, child_stderr) are returned."""
685            import warnings
686            msg = "os.popen3 is deprecated.  Use the subprocess module."
687            warnings.warn(msg, DeprecationWarning, stacklevel=2)
688
689            import subprocess
690            PIPE = subprocess.PIPE
691            p = subprocess.Popen(cmd, shell=isinstance(cmd, basestring),
692                                 bufsize=bufsize, stdin=PIPE, stdout=PIPE,
693                                 stderr=PIPE, close_fds=True)
694            return p.stdin, p.stdout, p.stderr
695        __all__.append("popen3")
696
697    if not _exists("popen4"):
698        def popen4(cmd, mode="t", bufsize=-1):
699            """Execute the shell command 'cmd' in a sub-process.  On UNIX, 'cmd'
700            may be a sequence, in which case arguments will be passed directly to
701            the program without shell intervention (as with os.spawnv()).  If 'cmd'
702            is a string it will be passed to the shell (as with os.system()). If
703            'bufsize' is specified, it sets the buffer size for the I/O pipes.  The
704            file objects (child_stdin, child_stdout_stderr) are returned."""
705            import warnings
706            msg = "os.popen4 is deprecated.  Use the subprocess module."
707            warnings.warn(msg, DeprecationWarning, stacklevel=2)
708
709            import subprocess
710            PIPE = subprocess.PIPE
711            p = subprocess.Popen(cmd, shell=isinstance(cmd, basestring),
712                                 bufsize=bufsize, stdin=PIPE, stdout=PIPE,
713                                 stderr=subprocess.STDOUT, close_fds=True)
714            return p.stdin, p.stdout
715        __all__.append("popen4")
716
717import copy_reg as _copy_reg
718
719def _make_stat_result(tup, dict):
720    return stat_result(tup, dict)
721
722def _pickle_stat_result(sr):
723    (type, args) = sr.__reduce__()
724    return (_make_stat_result, args)
725
726try:
727    _copy_reg.pickle(stat_result, _pickle_stat_result, _make_stat_result)
728except NameError: # stat_result may not exist
729    pass
730
731def _make_statvfs_result(tup, dict):
732    return statvfs_result(tup, dict)
733
734def _pickle_statvfs_result(sr):
735    (type, args) = sr.__reduce__()
736    return (_make_statvfs_result, args)
737
738try:
739    _copy_reg.pickle(statvfs_result, _pickle_statvfs_result,
740                     _make_statvfs_result)
741except NameError: # statvfs_result may not exist
742    pass
743