os.py revision c4e09400422487857a665a5c69a4e2d07a909aed
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
80    import os2
81    __all__.extend(_get_exports_list(os2))
82    del os2
83
84elif 'mac' in _names:
85    name = 'mac'
86    linesep = '\r'
87    from mac import *
88    try:
89        from mac import _exit
90    except ImportError:
91        pass
92    import macpath as path
93
94    import mac
95    __all__.extend(_get_exports_list(mac))
96    del mac
97
98elif 'ce' in _names:
99    name = 'ce'
100    linesep = '\r\n'
101    from ce import *
102    try:
103        from ce import _exit
104    except ImportError:
105        pass
106    # We can use the standard Windows path.
107    import ntpath as path
108
109    import ce
110    __all__.extend(_get_exports_list(ce))
111    del ce
112
113elif 'riscos' in _names:
114    name = 'riscos'
115    linesep = '\n'
116    from riscos import *
117    try:
118        from riscos import _exit
119    except ImportError:
120        pass
121    import riscospath as path
122
123    import riscos
124    __all__.extend(_get_exports_list(riscos))
125    del riscos
126
127else:
128    raise ImportError, 'no os specific module found'
129
130sys.modules['os.path'] = path
131from os.path import curdir, pardir, sep, pathsep, defpath, extsep, altsep
132
133del _names
134
135#'
136
137# Super directory utilities.
138# (Inspired by Eric Raymond; the doc strings are mostly his)
139
140def makedirs(name, mode=0777):
141    """makedirs(path [, mode=0777])
142
143    Super-mkdir; create a leaf directory and all intermediate ones.
144    Works like mkdir, except that any intermediate path segment (not
145    just the rightmost) will be created if it does not exist.  This is
146    recursive.
147
148    """
149    head, tail = path.split(name)
150    if not tail:
151        head, tail = path.split(head)
152    if head and tail and not path.exists(head):
153        makedirs(head, mode)
154    mkdir(name, mode)
155
156def removedirs(name):
157    """removedirs(path)
158
159    Super-rmdir; remove a leaf directory and empty all intermediate
160    ones.  Works like rmdir except that, if the leaf directory is
161    successfully removed, directories corresponding to rightmost path
162    segments will be pruned away until either the whole path is
163    consumed or an error occurs.  Errors during this latter phase are
164    ignored -- they generally mean that a directory was not empty.
165
166    """
167    rmdir(name)
168    head, tail = path.split(name)
169    if not tail:
170        head, tail = path.split(head)
171    while head and tail:
172        try:
173            rmdir(head)
174        except error:
175            break
176        head, tail = path.split(head)
177
178def renames(old, new):
179    """renames(old, new)
180
181    Super-rename; create directories as necessary and delete any left
182    empty.  Works like rename, except creation of any intermediate
183    directories needed to make the new pathname good is attempted
184    first.  After the rename, directories corresponding to rightmost
185    path segments of the old name will be pruned way until either the
186    whole path is consumed or a nonempty directory is found.
187
188    Note: this function can fail with the new directory structure made
189    if you lack permissions needed to unlink the leaf directory or
190    file.
191
192    """
193    head, tail = path.split(new)
194    if head and tail and not path.exists(head):
195        makedirs(head)
196    rename(old, new)
197    head, tail = path.split(old)
198    if head and tail:
199        try:
200            removedirs(head)
201        except error:
202            pass
203
204__all__.extend(["makedirs", "removedirs", "renames"])
205
206def walk(top, topdown=True):
207    """Directory tree generator.
208
209    For each directory in the directory tree rooted at top (including top
210    itself, but excluding '.' and '..'), yields a 3-tuple
211
212        dirpath, dirnames, filenames
213
214    dirpath is a string, the path to the directory.  dirnames is a list of
215    the names of the subdirectories in dirpath (excluding '.' and '..').
216    filenames is a list of the names of the non-directory files in dirpath.
217    Note that the names in the lists are just names, with no path components.
218    To get a full path (which begins with top) to a file or directory in
219    dirpath, do os.path.join(dirpath, name).
220
221    If optional arg 'topdown' is true or not specified, the triple for a
222    directory is generated before the triples for any of its subdirectories
223    (directories are generated top down).  If topdown is false, the triple
224    for a directory is generated after the triples for all of its
225    subdirectories (directories are generated bottom up).
226
227    When topdown is true, the caller can modify the dirnames list in-place
228    (e.g., via del or slice assignment), and walk will only recurse into the
229    subdirectories whose names remain in dirnames; this can be used to prune
230    the search, or to impose a specific order of visiting.  Modifying
231    dirnames when topdown is false is ineffective, since the directories in
232    dirnames have already been generated by the time dirnames itself is
233    generated.
234
235    Caution:  if you pass a relative pathname for top, don't change the
236    current working directory between resumptions of walk.  walk never
237    changes the current directory, and assumes that the client doesn't
238    either.
239
240    Example:
241
242    from os.path import join, getsize
243    for root, dirs, files in walk('python/Lib/email'):
244        print root, "consumes",
245        print sum([getsize(join(root, name)) for name in files]),
246        print "bytes in", len(files), "non-directory files"
247        if 'CVS' in dirs:
248            dirs.remove('CVS')  # don't visit CVS directories
249    """
250
251    from os.path import join, isdir, islink
252
253    # We may not have read permission for top, in which case we can't
254    # get a list of the files the directory contains.  os.path.walk
255    # always suppressed the exception then, rather than blow up for a
256    # minor reason when (say) a thousand readable directories are still
257    # left to visit.  That logic is copied here.
258    try:
259        # Note that listdir and error are globals in this module due
260        # to earlier import-*.
261        names = listdir(top)
262    except error:
263        return
264
265    dirs, nondirs = [], []
266    for name in names:
267        if isdir(join(top, name)):
268            dirs.append(name)
269        else:
270            nondirs.append(name)
271
272    if topdown:
273        yield top, dirs, nondirs
274    for name in dirs:
275        path = join(top, name)
276        if not islink(path):
277            for x in walk(path, topdown):
278                yield x
279    if not topdown:
280        yield top, dirs, nondirs
281
282__all__.append("walk")
283
284# Make sure os.environ exists, at least
285try:
286    environ
287except NameError:
288    environ = {}
289
290def execl(file, *args):
291    """execl(file, *args)
292
293    Execute the executable file with argument list args, replacing the
294    current process. """
295    execv(file, args)
296
297def execle(file, *args):
298    """execle(file, *args, env)
299
300    Execute the executable file with argument list args and
301    environment env, replacing the current process. """
302    env = args[-1]
303    execve(file, args[:-1], env)
304
305def execlp(file, *args):
306    """execlp(file, *args)
307
308    Execute the executable file (which is searched for along $PATH)
309    with argument list args, replacing the current process. """
310    execvp(file, args)
311
312def execlpe(file, *args):
313    """execlpe(file, *args, env)
314
315    Execute the executable file (which is searched for along $PATH)
316    with argument list args and environment env, replacing the current
317    process. """
318    env = args[-1]
319    execvpe(file, args[:-1], env)
320
321def execvp(file, args):
322    """execp(file, args)
323
324    Execute the executable file (which is searched for along $PATH)
325    with argument list args, replacing the current process.
326    args may be a list or tuple of strings. """
327    _execvpe(file, args)
328
329def execvpe(file, args, env):
330    """execvpe(file, args, env)
331
332    Execute the executable file (which is searched for along $PATH)
333    with argument list args and environment env , replacing the
334    current process.
335    args may be a list or tuple of strings. """
336    _execvpe(file, args, env)
337
338__all__.extend(["execl","execle","execlp","execlpe","execvp","execvpe"])
339
340def _execvpe(file, args, env=None):
341    from errno import ENOENT, ENOTDIR
342
343    if env is not None:
344        func = execve
345        argrest = (args, env)
346    else:
347        func = execv
348        argrest = (args,)
349        env = environ
350
351    head, tail = path.split(file)
352    if head:
353        func(file, *argrest)
354        return
355    if 'PATH' in env:
356        envpath = env['PATH']
357    else:
358        envpath = defpath
359    PATH = envpath.split(pathsep)
360    saved_exc = None
361    saved_tb = None
362    for dir in PATH:
363        fullname = path.join(dir, file)
364        try:
365            func(fullname, *argrest)
366        except error, e:
367            tb = sys.exc_info()[2]
368            if (e.errno != ENOENT and e.errno != ENOTDIR
369                and saved_exc is None):
370                saved_exc = e
371                saved_tb = tb
372    if saved_exc:
373        raise error, saved_exc, saved_tb
374    raise error, e, tb
375
376# Change environ to automatically call putenv() if it exists
377try:
378    # This will fail if there's no putenv
379    putenv
380except NameError:
381    pass
382else:
383    import UserDict
384
385    # Fake unsetenv() for Windows
386    # not sure about os2 here but
387    # I'm guessing they are the same.
388
389    if name in ('os2', 'nt'):
390        def unsetenv(key):
391            putenv(key, "")
392
393    if name == "riscos":
394        # On RISC OS, all env access goes through getenv and putenv
395        from riscosenviron import _Environ
396    elif name in ('os2', 'nt'):  # Where Env Var Names Must Be UPPERCASE
397        # But we store them as upper case
398        class _Environ(UserDict.IterableUserDict):
399            def __init__(self, environ):
400                UserDict.UserDict.__init__(self)
401                data = self.data
402                for k, v in environ.items():
403                    data[k.upper()] = v
404            def __setitem__(self, key, item):
405                putenv(key, item)
406                self.data[key.upper()] = item
407            def __getitem__(self, key):
408                return self.data[key.upper()]
409            try:
410                unsetenv
411            except NameError:
412                def __delitem__(self, key):
413                    del self.data[key.upper()]
414            else:
415                def __delitem__(self, key):
416                    unsetenv(key)
417                    del self.data[key.upper()]
418            def has_key(self, key):
419                return key.upper() in self.data
420            def __contains__(self, key):
421                return key.upper() in self.data
422            def get(self, key, failobj=None):
423                return self.data.get(key.upper(), failobj)
424            def update(self, dict):
425                for k, v in dict.items():
426                    self[k] = v
427            def copy(self):
428                return dict(self)
429
430    else:  # Where Env Var Names Can Be Mixed Case
431        class _Environ(UserDict.IterableUserDict):
432            def __init__(self, environ):
433                UserDict.UserDict.__init__(self)
434                self.data = environ
435            def __setitem__(self, key, item):
436                putenv(key, item)
437                self.data[key] = item
438            def update(self, dict):
439                for k, v in dict.items():
440                    self[k] = v
441            try:
442                unsetenv
443            except NameError:
444                pass
445            else:
446                def __delitem__(self, key):
447                    unsetenv(key)
448                    del self.data[key]
449            def copy(self):
450                return dict(self)
451
452
453    environ = _Environ(environ)
454
455def getenv(key, default=None):
456    """Get an environment variable, return None if it doesn't exist.
457    The optional second argument can specify an alternate default."""
458    return environ.get(key, default)
459__all__.append("getenv")
460
461def _exists(name):
462    try:
463        eval(name)
464        return True
465    except NameError:
466        return False
467
468# Supply spawn*() (probably only for Unix)
469if _exists("fork") and not _exists("spawnv") and _exists("execv"):
470
471    P_WAIT = 0
472    P_NOWAIT = P_NOWAITO = 1
473
474    # XXX Should we support P_DETACH?  I suppose it could fork()**2
475    # and close the std I/O streams.  Also, P_OVERLAY is the same
476    # as execv*()?
477
478    def _spawnvef(mode, file, args, env, func):
479        # Internal helper; func is the exec*() function to use
480        pid = fork()
481        if not pid:
482            # Child
483            try:
484                if env is None:
485                    func(file, args)
486                else:
487                    func(file, args, env)
488            except:
489                _exit(127)
490        else:
491            # Parent
492            if mode == P_NOWAIT:
493                return pid # Caller is responsible for waiting!
494            while 1:
495                wpid, sts = waitpid(pid, 0)
496                if WIFSTOPPED(sts):
497                    continue
498                elif WIFSIGNALED(sts):
499                    return -WTERMSIG(sts)
500                elif WIFEXITED(sts):
501                    return WEXITSTATUS(sts)
502                else:
503                    raise error, "Not stopped, signaled or exited???"
504
505    def spawnv(mode, file, args):
506        """spawnv(mode, file, args) -> integer
507
508Execute file with arguments from args in a subprocess.
509If mode == P_NOWAIT return the pid of the process.
510If mode == P_WAIT return the process's exit code if it exits normally;
511otherwise return -SIG, where SIG is the signal that killed it. """
512        return _spawnvef(mode, file, args, None, execv)
513
514    def spawnve(mode, file, args, env):
515        """spawnve(mode, file, args, env) -> integer
516
517Execute file with arguments from args in a subprocess with the
518specified environment.
519If mode == P_NOWAIT return the pid of the process.
520If mode == P_WAIT return the process's exit code if it exits normally;
521otherwise return -SIG, where SIG is the signal that killed it. """
522        return _spawnvef(mode, file, args, env, execve)
523
524    # Note: spawnvp[e] is't currently supported on Windows
525
526    def spawnvp(mode, file, args):
527        """spawnvp(mode, file, args) -> integer
528
529Execute file (which is looked for along $PATH) with arguments from
530args in a subprocess.
531If mode == P_NOWAIT return the pid of the process.
532If mode == P_WAIT return the process's exit code if it exits normally;
533otherwise return -SIG, where SIG is the signal that killed it. """
534        return _spawnvef(mode, file, args, None, execvp)
535
536    def spawnvpe(mode, file, args, env):
537        """spawnvpe(mode, file, args, env) -> integer
538
539Execute file (which is looked for along $PATH) with arguments from
540args in a subprocess with the supplied environment.
541If mode == P_NOWAIT return the pid of the process.
542If mode == P_WAIT return the process's exit code if it exits normally;
543otherwise return -SIG, where SIG is the signal that killed it. """
544        return _spawnvef(mode, file, args, env, execvpe)
545
546if _exists("spawnv"):
547    # These aren't supplied by the basic Windows code
548    # but can be easily implemented in Python
549
550    def spawnl(mode, file, *args):
551        """spawnl(mode, file, *args) -> integer
552
553Execute file with arguments from args in a subprocess.
554If mode == P_NOWAIT return the pid of the process.
555If mode == P_WAIT return the process's exit code if it exits normally;
556otherwise return -SIG, where SIG is the signal that killed it. """
557        return spawnv(mode, file, args)
558
559    def spawnle(mode, file, *args):
560        """spawnle(mode, file, *args, env) -> integer
561
562Execute file with arguments from args in a subprocess with the
563supplied environment.
564If mode == P_NOWAIT return the pid of the process.
565If mode == P_WAIT return the process's exit code if it exits normally;
566otherwise return -SIG, where SIG is the signal that killed it. """
567        env = args[-1]
568        return spawnve(mode, file, args[:-1], env)
569
570if _exists("spawnvp"):
571    # At the moment, Windows doesn't implement spawnvp[e],
572    # so it won't have spawnlp[e] either.
573    def spawnlp(mode, file, *args):
574        """spawnlp(mode, file, *args, env) -> integer
575
576Execute file (which is looked for along $PATH) with arguments from
577args in a subprocess with the supplied environment.
578If mode == P_NOWAIT return the pid of the process.
579If mode == P_WAIT return the process's exit code if it exits normally;
580otherwise return -SIG, where SIG is the signal that killed it. """
581        return spawnvp(mode, file, args)
582
583    def spawnlpe(mode, file, *args):
584        """spawnlpe(mode, file, *args, env) -> 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        env = args[-1]
592        return spawnvpe(mode, file, args[:-1], env)
593
594
595    __all__.extend(["spawnlp","spawnlpe","spawnv", "spawnve","spawnvp",
596                    "spawnvpe","spawnl","spawnle",])
597
598
599# Supply popen2 etc. (for Unix)
600if _exists("fork"):
601    if not _exists("popen2"):
602        def popen2(cmd, mode="t", bufsize=-1):
603            import popen2
604            stdout, stdin = popen2.popen2(cmd, bufsize)
605            return stdin, stdout
606        __all__.append("popen2")
607
608    if not _exists("popen3"):
609        def popen3(cmd, mode="t", bufsize=-1):
610            import popen2
611            stdout, stdin, stderr = popen2.popen3(cmd, bufsize)
612            return stdin, stdout, stderr
613        __all__.append("popen3")
614
615    if not _exists("popen4"):
616        def popen4(cmd, mode="t", bufsize=-1):
617            import popen2
618            stdout, stdin = popen2.popen4(cmd, bufsize)
619            return stdin, stdout
620        __all__.append("popen4")
621
622import copy_reg as _copy_reg
623
624def _make_stat_result(tup, dict):
625    return stat_result(tup, dict)
626
627def _pickle_stat_result(sr):
628    (type, args) = sr.__reduce__()
629    return (_make_stat_result, args)
630
631try:
632    _copy_reg.pickle(stat_result, _pickle_stat_result, _make_stat_result)
633except NameError: # stat_result may not exist
634    pass
635
636def _make_statvfs_result(tup, dict):
637    return statvfs_result(tup, dict)
638
639def _pickle_statvfs_result(sr):
640    (type, args) = sr.__reduce__()
641    return (_make_statvfs_result, args)
642
643try:
644    _copy_reg.pickle(statvfs_result, _pickle_statvfs_result,
645                     _make_statvfs_result)
646except NameError: # statvfs_result may not exist
647    pass
648