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