os.py revision 68468eba635570400f607e140425a222018e56f9
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__all__ = ["altsep", "curdir", "pardir", "sep", "pathsep", "linesep",
30           "defpath", "name", "path"]
31
32def _get_exports_list(module):
33    try:
34        return list(module.__all__)
35    except AttributeError:
36        return [n for n in dir(module) if n[0] != '_']
37
38if 'posix' in _names:
39    name = 'posix'
40    linesep = '\n'
41    from posix import *
42    try:
43        from posix import _exit
44    except ImportError:
45        pass
46    import posixpath as path
47
48    import posix
49    __all__.extend(_get_exports_list(posix))
50    del posix
51
52elif 'nt' in _names:
53    name = 'nt'
54    linesep = '\r\n'
55    from nt import *
56    try:
57        from nt import _exit
58    except ImportError:
59        pass
60    import ntpath as path
61
62    import nt
63    __all__.extend(_get_exports_list(nt))
64    del nt
65
66elif 'os2' in _names:
67    name = 'os2'
68    linesep = '\r\n'
69    from os2 import *
70    try:
71        from os2 import _exit
72    except ImportError:
73        pass
74    if sys.version.find('EMX GCC') == -1:
75        import ntpath as path
76    else:
77        import os2emxpath as path
78
79    import os2
80    __all__.extend(_get_exports_list(os2))
81    del os2
82
83elif 'mac' in _names:
84    name = 'mac'
85    linesep = '\r'
86    from mac import *
87    try:
88        from mac import _exit
89    except ImportError:
90        pass
91    import macpath as path
92
93    import mac
94    __all__.extend(_get_exports_list(mac))
95    del mac
96
97elif 'ce' in _names:
98    name = 'ce'
99    linesep = '\r\n'
100    from ce import *
101    try:
102        from ce import _exit
103    except ImportError:
104        pass
105    # We can use the standard Windows path.
106    import ntpath as path
107
108    import ce
109    __all__.extend(_get_exports_list(ce))
110    del ce
111
112elif 'riscos' in _names:
113    name = 'riscos'
114    linesep = '\n'
115    from riscos import *
116    try:
117        from riscos import _exit
118    except ImportError:
119        pass
120    import riscospath as path
121
122    import riscos
123    __all__.extend(_get_exports_list(riscos))
124    del riscos
125
126else:
127    raise ImportError, 'no os specific module found'
128
129sys.modules['os.path'] = path
130from os.path import curdir, pardir, sep, pathsep, defpath, extsep, altsep
131
132del _names
133
134#'
135
136# Super directory utilities.
137# (Inspired by Eric Raymond; the doc strings are mostly his)
138
139def makedirs(name, mode=0777):
140    """makedirs(path [, mode=0777])
141
142    Super-mkdir; create a leaf directory and all intermediate ones.
143    Works like mkdir, except that any intermediate path segment (not
144    just the rightmost) will be created if it does not exist.  This is
145    recursive.
146
147    """
148    head, tail = path.split(name)
149    if not tail:
150        head, tail = path.split(head)
151    if head and tail and not path.exists(head):
152        makedirs(head, mode)
153    mkdir(name, mode)
154
155def removedirs(name):
156    """removedirs(path)
157
158    Super-rmdir; remove a leaf directory and empty all intermediate
159    ones.  Works like rmdir except that, if the leaf directory is
160    successfully removed, directories corresponding to rightmost path
161    segments will be pruned way until either the whole path is
162    consumed or an error occurs.  Errors during this latter phase are
163    ignored -- they generally mean that a directory was not empty.
164
165    """
166    rmdir(name)
167    head, tail = path.split(name)
168    if not tail:
169        head, tail = path.split(head)
170    while head and tail:
171        try:
172            rmdir(head)
173        except error:
174            break
175        head, tail = path.split(head)
176
177def renames(old, new):
178    """renames(old, new)
179
180    Super-rename; create directories as necessary and delete any left
181    empty.  Works like rename, except creation of any intermediate
182    directories needed to make the new pathname good is attempted
183    first.  After the rename, directories corresponding to rightmost
184    path segments of the old name will be pruned way until either the
185    whole path is consumed or a nonempty directory is found.
186
187    Note: this function can fail with the new directory structure made
188    if you lack permissions needed to unlink the leaf directory or
189    file.
190
191    """
192    head, tail = path.split(new)
193    if head and tail and not path.exists(head):
194        makedirs(head)
195    rename(old, new)
196    head, tail = path.split(old)
197    if head and tail:
198        try:
199            removedirs(head)
200        except error:
201            pass
202
203__all__.extend(["makedirs", "removedirs", "renames"])
204
205# Make sure os.environ exists, at least
206try:
207    environ
208except NameError:
209    environ = {}
210
211def execl(file, *args):
212    """execl(file, *args)
213
214    Execute the executable file with argument list args, replacing the
215    current process. """
216    execv(file, args)
217
218def execle(file, *args):
219    """execle(file, *args, env)
220
221    Execute the executable file with argument list args and
222    environment env, replacing the current process. """
223    env = args[-1]
224    execve(file, args[:-1], env)
225
226def execlp(file, *args):
227    """execlp(file, *args)
228
229    Execute the executable file (which is searched for along $PATH)
230    with argument list args, replacing the current process. """
231    execvp(file, args)
232
233def execlpe(file, *args):
234    """execlpe(file, *args, env)
235
236    Execute the executable file (which is searched for along $PATH)
237    with argument list args and environment env, replacing the current
238    process. """
239    env = args[-1]
240    execvpe(file, args[:-1], env)
241
242def execvp(file, args):
243    """execp(file, args)
244
245    Execute the executable file (which is searched for along $PATH)
246    with argument list args, replacing the current process.
247    args may be a list or tuple of strings. """
248    _execvpe(file, args)
249
250def execvpe(file, args, env):
251    """execvpe(file, args, env)
252
253    Execute the executable file (which is searched for along $PATH)
254    with argument list args and environment env , replacing the
255    current process.
256    args may be a list or tuple of strings. """
257    _execvpe(file, args, env)
258
259__all__.extend(["execl","execle","execlp","execlpe","execvp","execvpe"])
260
261def _execvpe(file, args, env=None):
262    from errno import ENOENT, ENOTDIR
263
264    if env is not None:
265        func = execve
266        argrest = (args, env)
267    else:
268        func = execv
269        argrest = (args,)
270        env = environ
271
272    head, tail = path.split(file)
273    if head:
274        func(file, *argrest)
275        return
276    if 'PATH' in env:
277        envpath = env['PATH']
278    else:
279        envpath = defpath
280    PATH = envpath.split(pathsep)
281    saved_exc = None
282    saved_tb = None
283    for dir in PATH:
284        fullname = path.join(dir, file)
285        try:
286            func(fullname, *argrest)
287        except error, e:
288            tb = sys.exc_info()[2]
289            if (e.errno != ENOENT and e.errno != ENOTDIR
290                and saved_exc is None):
291                saved_exc = e
292                saved_tb = tb
293    if saved_exc:
294        raise error, saved_exc, saved_tb
295    raise error, e, tb
296
297# Change environ to automatically call putenv() if it exists
298try:
299    # This will fail if there's no putenv
300    putenv
301except NameError:
302    pass
303else:
304    import UserDict
305
306    # Fake unsetenv() for Windows
307    # not sure about os2 here but
308    # I'm guessing they are the same.
309
310    if name in ('os2', 'nt'):
311        def unsetenv(key):
312            putenv(key, "")
313
314    if name == "riscos":
315        # On RISC OS, all env access goes through getenv and putenv
316        from riscosenviron import _Environ
317    elif name in ('os2', 'nt'):  # Where Env Var Names Must Be UPPERCASE
318        # But we store them as upper case
319        class _Environ(UserDict.IterableUserDict):
320            def __init__(self, environ):
321                UserDict.UserDict.__init__(self)
322                data = self.data
323                for k, v in environ.items():
324                    data[k.upper()] = v
325            def __setitem__(self, key, item):
326                putenv(key, item)
327                self.data[key.upper()] = item
328            def __getitem__(self, key):
329                return self.data[key.upper()]
330            try:
331                unsetenv
332            except NameError:
333                def __delitem__(self, key):
334                    del self.data[key.upper()]
335            else:
336                def __delitem__(self, key):
337                    unsetenv(key)
338                    del self.data[key.upper()]
339            def has_key(self, key):
340                return key.upper() in self.data
341            def __contains__(self, key):
342                return key.upper() in self.data
343            def get(self, key, failobj=None):
344                return self.data.get(key.upper(), failobj)
345            def update(self, dict):
346                for k, v in dict.items():
347                    self[k] = v
348            def copy(self):
349                return dict(self)
350
351    else:  # Where Env Var Names Can Be Mixed Case
352        class _Environ(UserDict.IterableUserDict):
353            def __init__(self, environ):
354                UserDict.UserDict.__init__(self)
355                self.data = environ
356            def __setitem__(self, key, item):
357                putenv(key, item)
358                self.data[key] = item
359            def update(self, dict):
360                for k, v in dict.items():
361                    self[k] = v
362            try:
363                unsetenv
364            except NameError:
365                pass
366            else:
367                def __delitem__(self, key):
368                    unsetenv(key)
369                    del self.data[key]
370            def copy(self):
371                return dict(self)
372
373
374    environ = _Environ(environ)
375
376def getenv(key, default=None):
377    """Get an environment variable, return None if it doesn't exist.
378    The optional second argument can specify an alternate default."""
379    return environ.get(key, default)
380__all__.append("getenv")
381
382def _exists(name):
383    try:
384        eval(name)
385        return True
386    except NameError:
387        return False
388
389# Supply spawn*() (probably only for Unix)
390if _exists("fork") and not _exists("spawnv") and _exists("execv"):
391
392    P_WAIT = 0
393    P_NOWAIT = P_NOWAITO = 1
394
395    # XXX Should we support P_DETACH?  I suppose it could fork()**2
396    # and close the std I/O streams.  Also, P_OVERLAY is the same
397    # as execv*()?
398
399    def _spawnvef(mode, file, args, env, func):
400        # Internal helper; func is the exec*() function to use
401        pid = fork()
402        if not pid:
403            # Child
404            try:
405                if env is None:
406                    func(file, args)
407                else:
408                    func(file, args, env)
409            except:
410                _exit(127)
411        else:
412            # Parent
413            if mode == P_NOWAIT:
414                return pid # Caller is responsible for waiting!
415            while 1:
416                wpid, sts = waitpid(pid, 0)
417                if WIFSTOPPED(sts):
418                    continue
419                elif WIFSIGNALED(sts):
420                    return -WTERMSIG(sts)
421                elif WIFEXITED(sts):
422                    return WEXITSTATUS(sts)
423                else:
424                    raise error, "Not stopped, signaled or exited???"
425
426    def spawnv(mode, file, args):
427        """spawnv(mode, file, args) -> integer
428
429Execute file with arguments from args in a subprocess.
430If mode == P_NOWAIT return the pid of the process.
431If mode == P_WAIT return the process's exit code if it exits normally;
432otherwise return -SIG, where SIG is the signal that killed it. """
433        return _spawnvef(mode, file, args, None, execv)
434
435    def spawnve(mode, file, args, env):
436        """spawnve(mode, file, args, env) -> integer
437
438Execute file with arguments from args in a subprocess with the
439specified environment.
440If mode == P_NOWAIT return the pid of the process.
441If mode == P_WAIT return the process's exit code if it exits normally;
442otherwise return -SIG, where SIG is the signal that killed it. """
443        return _spawnvef(mode, file, args, env, execve)
444
445    # Note: spawnvp[e] is't currently supported on Windows
446
447    def spawnvp(mode, file, args):
448        """spawnvp(mode, file, args) -> integer
449
450Execute file (which is looked for along $PATH) with arguments from
451args in a subprocess.
452If mode == P_NOWAIT return the pid of the process.
453If mode == P_WAIT return the process's exit code if it exits normally;
454otherwise return -SIG, where SIG is the signal that killed it. """
455        return _spawnvef(mode, file, args, None, execvp)
456
457    def spawnvpe(mode, file, args, env):
458        """spawnvpe(mode, file, args, env) -> integer
459
460Execute file (which is looked for along $PATH) with arguments from
461args in a subprocess with the supplied environment.
462If mode == P_NOWAIT return the pid of the process.
463If mode == P_WAIT return the process's exit code if it exits normally;
464otherwise return -SIG, where SIG is the signal that killed it. """
465        return _spawnvef(mode, file, args, env, execvpe)
466
467if _exists("spawnv"):
468    # These aren't supplied by the basic Windows code
469    # but can be easily implemented in Python
470
471    def spawnl(mode, file, *args):
472        """spawnl(mode, file, *args) -> integer
473
474Execute file with arguments from args in a subprocess.
475If mode == P_NOWAIT return the pid of the process.
476If mode == P_WAIT return the process's exit code if it exits normally;
477otherwise return -SIG, where SIG is the signal that killed it. """
478        return spawnv(mode, file, args)
479
480    def spawnle(mode, file, *args):
481        """spawnle(mode, file, *args, env) -> integer
482
483Execute file with arguments from args in a subprocess with the
484supplied environment.
485If mode == P_NOWAIT return the pid of the process.
486If mode == P_WAIT return the process's exit code if it exits normally;
487otherwise return -SIG, where SIG is the signal that killed it. """
488        env = args[-1]
489        return spawnve(mode, file, args[:-1], env)
490
491if _exists("spawnvp"):
492    # At the moment, Windows doesn't implement spawnvp[e],
493    # so it won't have spawnlp[e] either.
494    def spawnlp(mode, file, *args):
495        """spawnlp(mode, file, *args, env) -> integer
496
497Execute file (which is looked for along $PATH) with arguments from
498args in a subprocess with the supplied environment.
499If mode == P_NOWAIT return the pid of the process.
500If mode == P_WAIT return the process's exit code if it exits normally;
501otherwise return -SIG, where SIG is the signal that killed it. """
502        return spawnvp(mode, file, args)
503
504    def spawnlpe(mode, file, *args):
505        """spawnlpe(mode, file, *args, env) -> integer
506
507Execute file (which is looked for along $PATH) with arguments from
508args in a subprocess with the supplied environment.
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        env = args[-1]
513        return spawnvpe(mode, file, args[:-1], env)
514
515
516    __all__.extend(["spawnlp","spawnlpe","spawnv", "spawnve","spawnvp",
517                    "spawnvpe","spawnl","spawnle",])
518
519
520# Supply popen2 etc. (for Unix)
521if _exists("fork"):
522    if not _exists("popen2"):
523        def popen2(cmd, mode="t", bufsize=-1):
524            import popen2
525            stdout, stdin = popen2.popen2(cmd, bufsize)
526            return stdin, stdout
527        __all__.append("popen2")
528
529    if not _exists("popen3"):
530        def popen3(cmd, mode="t", bufsize=-1):
531            import popen2
532            stdout, stdin, stderr = popen2.popen3(cmd, bufsize)
533            return stdin, stdout, stderr
534        __all__.append("popen3")
535
536    if not _exists("popen4"):
537        def popen4(cmd, mode="t", bufsize=-1):
538            import popen2
539            stdout, stdin = popen2.popen4(cmd, bufsize)
540            return stdin, stdout
541        __all__.append("popen4")
542
543import copy_reg as _copy_reg
544
545def _make_stat_result(tup, dict):
546    return stat_result(tup, dict)
547
548def _pickle_stat_result(sr):
549    (type, args) = sr.__reduce__()
550    return (_make_stat_result, args)
551
552try:
553    _copy_reg.pickle(stat_result, _pickle_stat_result, _make_stat_result)
554except NameError: # stat_result may not exist
555    pass
556
557def _make_statvfs_result(tup, dict):
558    return statvfs_result(tup, dict)
559
560def _pickle_statvfs_result(sr):
561    (type, args) = sr.__reduce__()
562    return (_make_statvfs_result, args)
563
564try:
565    _copy_reg.pickle(statvfs_result, _pickle_statvfs_result,
566                     _make_statvfs_result)
567except NameError: # statvfs_result may not exist
568    pass
569