os.py revision 69e18c9344b1bc72d1f6c26de0bd41f3ba2c274c
1r"""OS routines for Mac, DOS, NT, or Posix depending on what system we're on.
2
3This exports:
4  - all functions from posix, nt, os2, mac, or ce, e.g. unlink, stat, etc.
5  - os.path is one of the modules posixpath, ntpath, or macpath
6  - os.name is 'posix', 'nt', 'os2', 'mac', '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
16Programs that import and use 'os' stand a better chance of being
17portable between different platforms.  Of course, they must then
18only use functions that are defined by all platforms (e.g., unlink
19and opendir), and leave all pathname manipulation to os.path
20(e.g., split and join).
21"""
22
23#'
24
25import sys
26
27_names = sys.builtin_module_names
28
29# Note:  more names are added to __all__ later.
30__all__ = ["altsep", "curdir", "pardir", "sep", "pathsep", "linesep",
31           "defpath", "name", "path"]
32
33def _get_exports_list(module):
34    try:
35        return list(module.__all__)
36    except AttributeError:
37        return [n for n in dir(module) if n[0] != '_']
38
39if 'posix' in _names:
40    name = 'posix'
41    linesep = '\n'
42    from posix import *
43    try:
44        from posix import _exit
45    except ImportError:
46        pass
47    import posixpath as path
48
49    import posix
50    __all__.extend(_get_exports_list(posix))
51    del posix
52
53elif 'nt' in _names:
54    name = 'nt'
55    linesep = '\r\n'
56    from nt import *
57    try:
58        from nt import _exit
59    except ImportError:
60        pass
61    import ntpath as path
62
63    import nt
64    __all__.extend(_get_exports_list(nt))
65    del nt
66
67elif 'os2' in _names:
68    name = 'os2'
69    linesep = '\r\n'
70    from os2 import *
71    try:
72        from os2 import _exit
73    except ImportError:
74        pass
75    if sys.version.find('EMX GCC') == -1:
76        import ntpath as path
77    else:
78        import os2emxpath as path
79        from _emx_link import link
80
81    import os2
82    __all__.extend(_get_exports_list(os2))
83    del os2
84
85elif 'mac' in _names:
86    name = 'mac'
87    linesep = '\r'
88    from mac import *
89    try:
90        from mac import _exit
91    except ImportError:
92        pass
93    import macpath as path
94
95    import mac
96    __all__.extend(_get_exports_list(mac))
97    del mac
98
99elif 'ce' in _names:
100    name = 'ce'
101    linesep = '\r\n'
102    from ce import *
103    try:
104        from ce import _exit
105    except ImportError:
106        pass
107    # We can use the standard Windows path.
108    import ntpath as path
109
110    import ce
111    __all__.extend(_get_exports_list(ce))
112    del ce
113
114elif 'riscos' in _names:
115    name = 'riscos'
116    linesep = '\n'
117    from riscos import *
118    try:
119        from riscos import _exit
120    except ImportError:
121        pass
122    import riscospath as path
123
124    import riscos
125    __all__.extend(_get_exports_list(riscos))
126    del riscos
127
128else:
129    raise ImportError, 'no os specific module found'
130
131sys.modules['os.path'] = path
132from os.path import curdir, pardir, sep, pathsep, defpath, extsep, altsep
133
134del _names
135
136#'
137
138# Super directory utilities.
139# (Inspired by Eric Raymond; the doc strings are mostly his)
140
141def makedirs(name, mode=0777):
142    """makedirs(path [, mode=0777])
143
144    Super-mkdir; create a leaf directory and all intermediate ones.
145    Works like mkdir, except that any intermediate path segment (not
146    just the rightmost) will be created if it does not exist.  This is
147    recursive.
148
149    """
150    head, tail = path.split(name)
151    if not tail:
152        head, tail = path.split(head)
153    if head and tail and not path.exists(head):
154        makedirs(head, mode)
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 empty all 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 way 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):
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
233    the search, or to impose a specific order of visiting.  Modifying
234    dirnames when topdown is false is ineffective, since the directories in
235    dirnames have already been generated by the time dirnames itself is
236    generated.
237
238    By default errors from the os.listdir() call are ignored.  If
239    optional arg 'onerror' is specified, it should be a function; it
240    will be called with one argument, an os.error instance.  It can
241    report the error to continue with the walk, or raise the exception
242    to abort the walk.  Note that the filename is available as the
243    filename attribute of the exception object.
244
245    Caution:  if you pass a relative pathname for top, don't change the
246    current working directory between resumptions of walk.  walk never
247    changes the current directory, and assumes that the client doesn't
248    either.
249
250    Example:
251
252    from os.path import join, getsize
253    for root, dirs, files in walk('python/Lib/email'):
254        print root, "consumes",
255        print sum([getsize(join(root, name)) for name in files]),
256        print "bytes in", len(files), "non-directory files"
257        if 'CVS' in dirs:
258            dirs.remove('CVS')  # don't visit CVS directories
259    """
260
261    from os.path import join, isdir, islink
262
263    # We may not have read permission for top, in which case we can't
264    # get a list of the files the directory contains.  os.path.walk
265    # always suppressed the exception then, rather than blow up for a
266    # minor reason when (say) a thousand readable directories are still
267    # left to visit.  That logic is copied here.
268    try:
269        # Note that listdir and error are globals in this module due
270        # to earlier import-*.
271        names = listdir(top)
272    except error, err:
273        if onerror is not None:
274            onerror(err)
275        return
276
277    dirs, nondirs = [], []
278    for name in names:
279        if isdir(join(top, name)):
280            dirs.append(name)
281        else:
282            nondirs.append(name)
283
284    if topdown:
285        yield top, dirs, nondirs
286    for name in dirs:
287        path = join(top, name)
288        if not islink(path):
289            for x in walk(path, topdown, onerror):
290                yield x
291    if not topdown:
292        yield top, dirs, nondirs
293
294__all__.append("walk")
295
296# Make sure os.environ exists, at least
297try:
298    environ
299except NameError:
300    environ = {}
301
302def execl(file, *args):
303    """execl(file, *args)
304
305    Execute the executable file with argument list args, replacing the
306    current process. """
307    execv(file, args)
308
309def execle(file, *args):
310    """execle(file, *args, env)
311
312    Execute the executable file with argument list args and
313    environment env, replacing the current process. """
314    env = args[-1]
315    execve(file, args[:-1], env)
316
317def execlp(file, *args):
318    """execlp(file, *args)
319
320    Execute the executable file (which is searched for along $PATH)
321    with argument list args, replacing the current process. """
322    execvp(file, args)
323
324def execlpe(file, *args):
325    """execlpe(file, *args, env)
326
327    Execute the executable file (which is searched for along $PATH)
328    with argument list args and environment env, replacing the current
329    process. """
330    env = args[-1]
331    execvpe(file, args[:-1], env)
332
333def execvp(file, args):
334    """execp(file, args)
335
336    Execute the executable file (which is searched for along $PATH)
337    with argument list args, replacing the current process.
338    args may be a list or tuple of strings. """
339    _execvpe(file, args)
340
341def execvpe(file, args, env):
342    """execvpe(file, args, env)
343
344    Execute the executable file (which is searched for along $PATH)
345    with argument list args and environment env , replacing the
346    current process.
347    args may be a list or tuple of strings. """
348    _execvpe(file, args, env)
349
350__all__.extend(["execl","execle","execlp","execlpe","execvp","execvpe"])
351
352def _execvpe(file, args, env=None):
353    from errno import ENOENT, ENOTDIR
354
355    if env is not None:
356        func = execve
357        argrest = (args, env)
358    else:
359        func = execv
360        argrest = (args,)
361        env = environ
362
363    head, tail = path.split(file)
364    if head:
365        func(file, *argrest)
366        return
367    if 'PATH' in env:
368        envpath = env['PATH']
369    else:
370        envpath = defpath
371    PATH = envpath.split(pathsep)
372    saved_exc = None
373    saved_tb = None
374    for dir in PATH:
375        fullname = path.join(dir, file)
376        try:
377            func(fullname, *argrest)
378        except error, e:
379            tb = sys.exc_info()[2]
380            if (e.errno != ENOENT and e.errno != ENOTDIR
381                and saved_exc is None):
382                saved_exc = e
383                saved_tb = tb
384    if saved_exc:
385        raise error, saved_exc, saved_tb
386    raise error, e, tb
387
388# Change environ to automatically call putenv() if it exists
389try:
390    # This will fail if there's no putenv
391    putenv
392except NameError:
393    pass
394else:
395    import UserDict
396
397    # Fake unsetenv() for Windows
398    # not sure about os2 here but
399    # I'm guessing they are the same.
400
401    if name in ('os2', 'nt'):
402        def unsetenv(key):
403            putenv(key, "")
404
405    if name == "riscos":
406        # On RISC OS, all env access goes through getenv and putenv
407        from riscosenviron import _Environ
408    elif name in ('os2', 'nt'):  # Where Env Var Names Must Be UPPERCASE
409        # But we store them as upper case
410        class _Environ(UserDict.IterableUserDict):
411            def __init__(self, environ):
412                UserDict.UserDict.__init__(self)
413                data = self.data
414                for k, v in environ.items():
415                    data[k.upper()] = v
416            def __setitem__(self, key, item):
417                putenv(key, item)
418                self.data[key.upper()] = item
419            def __getitem__(self, key):
420                return self.data[key.upper()]
421            try:
422                unsetenv
423            except NameError:
424                def __delitem__(self, key):
425                    del self.data[key.upper()]
426            else:
427                def __delitem__(self, key):
428                    unsetenv(key)
429                    del self.data[key.upper()]
430            def has_key(self, key):
431                return key.upper() in self.data
432            def __contains__(self, key):
433                return key.upper() in self.data
434            def get(self, key, failobj=None):
435                return self.data.get(key.upper(), failobj)
436            def copy(self):
437                return dict(self)
438
439    else:  # Where Env Var Names Can Be Mixed Case
440        class _Environ(UserDict.IterableUserDict):
441            def __init__(self, environ):
442                UserDict.UserDict.__init__(self)
443                self.data = environ
444            def __setitem__(self, key, item):
445                putenv(key, item)
446                self.data[key] = item
447            try:
448                unsetenv
449            except NameError:
450                pass
451            else:
452                def __delitem__(self, key):
453                    unsetenv(key)
454                    del self.data[key]
455            def copy(self):
456                return dict(self)
457
458
459    environ = _Environ(environ)
460
461def getenv(key, default=None):
462    """Get an environment variable, return None if it doesn't exist.
463    The optional second argument can specify an alternate default."""
464    return environ.get(key, default)
465__all__.append("getenv")
466
467def _exists(name):
468    try:
469        eval(name)
470        return True
471    except NameError:
472        return False
473
474# Supply spawn*() (probably only for Unix)
475if _exists("fork") and not _exists("spawnv") and _exists("execv"):
476
477    P_WAIT = 0
478    P_NOWAIT = P_NOWAITO = 1
479
480    # XXX Should we support P_DETACH?  I suppose it could fork()**2
481    # and close the std I/O streams.  Also, P_OVERLAY is the same
482    # as execv*()?
483
484    def _spawnvef(mode, file, args, env, func):
485        # Internal helper; func is the exec*() function to use
486        pid = fork()
487        if not pid:
488            # Child
489            try:
490                if env is None:
491                    func(file, args)
492                else:
493                    func(file, args, env)
494            except:
495                _exit(127)
496        else:
497            # Parent
498            if mode == P_NOWAIT:
499                return pid # Caller is responsible for waiting!
500            while 1:
501                wpid, sts = waitpid(pid, 0)
502                if WIFSTOPPED(sts):
503                    continue
504                elif WIFSIGNALED(sts):
505                    return -WTERMSIG(sts)
506                elif WIFEXITED(sts):
507                    return WEXITSTATUS(sts)
508                else:
509                    raise error, "Not stopped, signaled or exited???"
510
511    def spawnv(mode, file, args):
512        """spawnv(mode, file, args) -> integer
513
514Execute file with arguments from args in a subprocess.
515If mode == P_NOWAIT return the pid of the process.
516If mode == P_WAIT return the process's exit code if it exits normally;
517otherwise return -SIG, where SIG is the signal that killed it. """
518        return _spawnvef(mode, file, args, None, execv)
519
520    def spawnve(mode, file, args, env):
521        """spawnve(mode, file, args, env) -> integer
522
523Execute file with arguments from args in a subprocess with the
524specified environment.
525If mode == P_NOWAIT return the pid of the process.
526If mode == P_WAIT return the process's exit code if it exits normally;
527otherwise return -SIG, where SIG is the signal that killed it. """
528        return _spawnvef(mode, file, args, env, execve)
529
530    # Note: spawnvp[e] is't currently supported on Windows
531
532    def spawnvp(mode, file, args):
533        """spawnvp(mode, file, args) -> integer
534
535Execute file (which is looked for along $PATH) with arguments from
536args in a subprocess.
537If mode == P_NOWAIT return the pid of the process.
538If mode == P_WAIT return the process's exit code if it exits normally;
539otherwise return -SIG, where SIG is the signal that killed it. """
540        return _spawnvef(mode, file, args, None, execvp)
541
542    def spawnvpe(mode, file, args, env):
543        """spawnvpe(mode, file, args, env) -> integer
544
545Execute file (which is looked for along $PATH) with arguments from
546args in a subprocess with the supplied environment.
547If mode == P_NOWAIT return the pid of the process.
548If mode == P_WAIT return the process's exit code if it exits normally;
549otherwise return -SIG, where SIG is the signal that killed it. """
550        return _spawnvef(mode, file, args, env, execvpe)
551
552if _exists("spawnv"):
553    # These aren't supplied by the basic Windows code
554    # but can be easily implemented in Python
555
556    def spawnl(mode, file, *args):
557        """spawnl(mode, file, *args) -> integer
558
559Execute file with arguments from args in a subprocess.
560If mode == P_NOWAIT return the pid of the process.
561If mode == P_WAIT return the process's exit code if it exits normally;
562otherwise return -SIG, where SIG is the signal that killed it. """
563        return spawnv(mode, file, args)
564
565    def spawnle(mode, file, *args):
566        """spawnle(mode, file, *args, env) -> integer
567
568Execute file with arguments from args in a subprocess with the
569supplied environment.
570If mode == P_NOWAIT return the pid of the process.
571If mode == P_WAIT return the process's exit code if it exits normally;
572otherwise return -SIG, where SIG is the signal that killed it. """
573        env = args[-1]
574        return spawnve(mode, file, args[:-1], env)
575
576
577    __all__.extend(["spawnv", "spawnve", "spawnl", "spawnle",])
578
579
580if _exists("spawnvp"):
581    # At the moment, Windows doesn't implement spawnvp[e],
582    # so it won't have spawnlp[e] either.
583    def spawnlp(mode, file, *args):
584        """spawnlp(mode, file, *args) -> integer
585
586Execute file (which is looked for along $PATH) with arguments from
587args in a subprocess with the supplied environment.
588If mode == P_NOWAIT return the pid of the process.
589If mode == P_WAIT return the process's exit code if it exits normally;
590otherwise return -SIG, where SIG is the signal that killed it. """
591        return spawnvp(mode, file, args)
592
593    def spawnlpe(mode, file, *args):
594        """spawnlpe(mode, file, *args, env) -> integer
595
596Execute file (which is looked for along $PATH) with arguments from
597args in a subprocess with the supplied environment.
598If mode == P_NOWAIT return the pid of the process.
599If mode == P_WAIT return the process's exit code if it exits normally;
600otherwise return -SIG, where SIG is the signal that killed it. """
601        env = args[-1]
602        return spawnvpe(mode, file, args[:-1], env)
603
604
605    __all__.extend(["spawnvp", "spawnvpe", "spawnlp", "spawnlpe",])
606
607
608# Supply popen2 etc. (for Unix)
609if _exists("fork"):
610    if not _exists("popen2"):
611        def popen2(cmd, mode="t", bufsize=-1):
612            import popen2
613            stdout, stdin = popen2.popen2(cmd, bufsize)
614            return stdin, stdout
615        __all__.append("popen2")
616
617    if not _exists("popen3"):
618        def popen3(cmd, mode="t", bufsize=-1):
619            import popen2
620            stdout, stdin, stderr = popen2.popen3(cmd, bufsize)
621            return stdin, stdout, stderr
622        __all__.append("popen3")
623
624    if not _exists("popen4"):
625        def popen4(cmd, mode="t", bufsize=-1):
626            import popen2
627            stdout, stdin = popen2.popen4(cmd, bufsize)
628            return stdin, stdout
629        __all__.append("popen4")
630
631import copy_reg as _copy_reg
632
633def _make_stat_result(tup, dict):
634    return stat_result(tup, dict)
635
636def _pickle_stat_result(sr):
637    (type, args) = sr.__reduce__()
638    return (_make_stat_result, args)
639
640try:
641    _copy_reg.pickle(stat_result, _pickle_stat_result, _make_stat_result)
642except NameError: # stat_result may not exist
643    pass
644
645def _make_statvfs_result(tup, dict):
646    return statvfs_result(tup, dict)
647
648def _pickle_statvfs_result(sr):
649    (type, args) = sr.__reduce__()
650    return (_make_statvfs_result, args)
651
652try:
653    _copy_reg.pickle(statvfs_result, _pickle_statvfs_result,
654                     _make_statvfs_result)
655except NameError: # statvfs_result may not exist
656    pass
657