os.py revision 7e47402264cf87b9bbb61fc9ff610af08add7c7b
1"""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', or 'ce'
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.altsep is the alternate pathname separator (None or '/')
11  - os.pathsep is the component separator used in $PATH etc
12  - os.linesep is the line separator in text files ('\r' or '\n' or '\r\n')
13  - os.defpath is the default search path for executables
14
15Programs that import and use 'os' stand a better chance of being
16portable between different platforms.  Of course, they must then
17only use functions that are defined by all platforms (e.g., unlink
18and opendir), and leave all pathname manipulation to os.path
19(e.g., split and join).
20"""
21
22import sys
23
24_names = sys.builtin_module_names
25
26altsep = None
27
28if 'posix' in _names:
29    name = 'posix'
30    linesep = '\n'
31    curdir = '.'; pardir = '..'; sep = '/'; pathsep = ':'
32    defpath = ':/bin:/usr/bin'
33    from posix import *
34    try:
35        from posix import _exit
36    except ImportError:
37        pass
38    import posixpath
39    path = posixpath
40    del posixpath
41elif 'nt' in _names:
42    name = 'nt'
43    linesep = '\r\n'
44    curdir = '.'; pardir = '..'; sep = '\\'; pathsep = ';'
45    defpath = '.;C:\\bin'
46    from nt import *
47    for i in ['_exit']:
48        try:
49            exec "from nt import " + i
50        except ImportError:
51            pass
52    import ntpath
53    path = ntpath
54    del ntpath
55elif 'dos' in _names:
56    name = 'dos'
57    linesep = '\r\n'
58    curdir = '.'; pardir = '..'; sep = '\\'; pathsep = ';'
59    defpath = '.;C:\\bin'
60    from dos import *
61    try:
62        from dos import _exit
63    except ImportError:
64        pass
65    import dospath
66    path = dospath
67    del dospath
68elif 'os2' in _names:
69    name = 'os2'
70    linesep = '\r\n'
71    curdir = '.'; pardir = '..'; sep = '\\'; pathsep = ';'
72    defpath = '.;C:\\bin'
73    from os2 import *
74    try:
75        from os2 import _exit
76    except ImportError:
77        pass
78    import ntpath
79    path = ntpath
80    del ntpath
81elif 'mac' in _names:
82    name = 'mac'
83    linesep = '\r'
84    curdir = ':'; pardir = '::'; sep = ':'; pathsep = '\n'
85    defpath = ':'
86    from mac import *
87    try:
88        from mac import _exit
89    except ImportError:
90        pass
91    import macpath
92    path = macpath
93    del macpath
94elif 'ce' in _names:
95    name = 'ce'
96    linesep = '\r\n'
97    curdir = '.'; pardir = '..'; sep = '\\'; pathsep = ';'
98    defpath = '\\Windows'
99    from ce import *
100    for i in ['_exit']:
101        try:
102            exec "from ce import " + i
103        except ImportError:
104            pass
105    # We can use the standard Windows path.
106    import ntpath
107    path = ntpath
108    del ntpath
109else:
110    raise ImportError, 'no os specific module found'
111
112del _names
113
114sys.modules['os.path'] = path
115
116# Super directory utilities.
117# (Inspired by Eric Raymond; the doc strings are mostly his)
118
119def makedirs(name, mode=0777):
120    """makedirs(path [, mode=0777]) -> None
121
122    Super-mkdir; create a leaf directory and all intermediate ones.
123    Works like mkdir, except that any intermediate path segment (not
124    just the rightmost) will be created if it does not exist.  This is
125    recursive.
126
127    """
128    head, tail = path.split(name)
129    if head and tail and not path.exists(head):
130        makedirs(head, mode)
131    mkdir(name, mode)
132
133def removedirs(name):
134    """removedirs(path) -> None
135
136    Super-rmdir; remove a leaf directory and empty all intermediate
137    ones.  Works like rmdir except that, if the leaf directory is
138    successfully removed, directories corresponding to rightmost path
139    segments will be pruned way until either the whole path is
140    consumed or an error occurs.  Errors during this latter phase are
141    ignored -- they generally mean that a directory was not empty.
142
143    """
144    rmdir(name)
145    head, tail = path.split(name)
146    while head and tail:
147        try:
148            rmdir(head)
149        except error:
150            break
151        head, tail = path.split(head)
152
153def renames(old, new):
154    """renames(old, new) -> None
155
156    Super-rename; create directories as necessary and delete any left
157    empty.  Works like rename, except creation of any intermediate
158    directories needed to make the new pathname good is attempted
159    first.  After the rename, directories corresponding to rightmost
160    path segments of the old name will be pruned way until either the
161    whole path is consumed or a nonempty directory is found.
162
163    Note: this function can fail with the new directory structure made
164    if you lack permissions needed to unlink the leaf directory or
165    file.
166
167    """
168    head, tail = path.split(new)
169    if head and tail and not path.exists(head):
170        makedirs(head)
171    rename(old, new)
172    head, tail = path.split(old)
173    if head and tail:
174        try:
175            removedirs(head)
176        except error:
177            pass
178
179# Make sure os.environ exists, at least
180try:
181    environ
182except NameError:
183    environ = {}
184
185def execl(file, *args):
186    """execl(file, *args)
187
188    Execute the executable file with argument list args, replacing the
189    current process. """
190    execv(file, args)
191
192def execle(file, *args):
193    """execle(file, *args, env)
194
195    Execute the executable file with argument list args and
196    environment env, replacing the current process. """
197    env = args[-1]
198    execve(file, args[:-1], env)
199
200def execlp(file, *args):
201    """execlp(file, *args)
202
203    Execute the executable file (which is searched for along $PATH)
204    with argument list args, replacing the current process. """
205    execvp(file, args)
206
207def execlpe(file, *args):
208    """execlpe(file, *args, env)
209
210    Execute the executable file (which is searched for along $PATH)
211    with argument list args and environment env, replacing the current
212    process. """
213    env = args[-1]
214    execvpe(file, args[:-1], env)
215
216def execvp(file, args):
217    """execp(file, args)
218
219    Execute the executable file (which is searched for along $PATH)
220    with argument list args, replacing the current process.
221    args may be a list or tuple of strings. """
222    _execvpe(file, args)
223
224def execvpe(file, args, env):
225    """execv(file, args, env)
226
227    Execute the executable file (which is searched for along $PATH)
228    with argument list args and environment env , replacing the
229    current process.
230    args may be a list or tuple of strings. """
231    _execvpe(file, args, env)
232
233_notfound = None
234def _execvpe(file, args, env=None):
235    if env is not None:
236        func = execve
237        argrest = (args, env)
238    else:
239        func = execv
240        argrest = (args,)
241        env = environ
242    global _notfound
243    head, tail = path.split(file)
244    if head:
245        apply(func, (file,) + argrest)
246        return
247    if env.has_key('PATH'):
248        envpath = env['PATH']
249    else:
250        envpath = defpath
251    PATH = envpath.split(pathsep)
252    if not _notfound:
253        import tempfile
254        # Exec a file that is guaranteed not to exist
255        try: execv(tempfile.mktemp(), ('blah',))
256        except error, _notfound: pass
257    exc, arg = error, _notfound
258    for dir in PATH:
259        fullname = path.join(dir, file)
260        try:
261            apply(func, (fullname,) + argrest)
262        except error, (errno, msg):
263            if errno != arg[0]:
264                exc, arg = error, (errno, msg)
265    raise exc, arg
266
267# Change environ to automatically call putenv() if it exists
268try:
269    # This will fail if there's no putenv
270    putenv
271except NameError:
272    pass
273else:
274    import UserDict
275
276    if name in ('os2', 'nt', 'dos'):  # Where Env Var Names Must Be UPPERCASE
277        # But we store them as upper case
278        class _Environ(UserDict.UserDict):
279            def __init__(self, environ):
280                UserDict.UserDict.__init__(self)
281                data = self.data
282                for k, v in environ.items():
283                    data[k.upper()] = v
284            def __setitem__(self, key, item):
285                putenv(key, item)
286                self.data[key.upper()] = item
287            def __getitem__(self, key):
288                return self.data[key.upper()]
289            def __delitem__(self, key):
290                del self.data[key.upper()]
291            def has_key(self, key):
292                return self.data.has_key(key.upper())
293            def get(self, key, failobj=None):
294                return self.data.get(key.upper(), failobj)
295            def update(self, dict):
296                for k, v in dict.items():
297                    self[k] = v
298
299    else:  # Where Env Var Names Can Be Mixed Case
300        class _Environ(UserDict.UserDict):
301            def __init__(self, environ):
302                UserDict.UserDict.__init__(self)
303                self.data = environ
304            def __setitem__(self, key, item):
305                putenv(key, item)
306                self.data[key] = item
307            def update(self, dict):
308                for k, v in dict.items():
309                    self[k] = v
310
311    environ = _Environ(environ)
312
313def getenv(key, default=None):
314    """Get an environment variable, return None if it doesn't exist.
315
316    The optional second argument can specify an alternative default."""
317    return environ.get(key, default)
318
319def _exists(name):
320    try:
321        eval(name)
322        return 1
323    except NameError:
324        return 0
325
326# Supply spawn*() (probably only for Unix)
327if _exists("fork") and not _exists("spawnv") and _exists("execv"):
328
329    P_WAIT = 0
330    P_NOWAIT = P_NOWAITO = 1
331
332    # XXX Should we support P_DETACH?  I suppose it could fork()**2
333    # and close the std I/O streams.  Also, P_OVERLAY is the same
334    # as execv*()?
335
336    def _spawnvef(mode, file, args, env, func):
337        # Internal helper; func is the exec*() function to use
338        pid = fork()
339        if not pid:
340            # Child
341            try:
342                if env is None:
343                    func(file, args)
344                else:
345                    func(file, args, env)
346            except:
347                _exit(127)
348        else:
349            # Parent
350            if mode == P_NOWAIT:
351                return pid # Caller is responsible for waiting!
352            while 1:
353                wpid, sts = waitpid(pid, 0)
354                if WIFSTOPPED(sts):
355                    continue
356                elif WIFSIGNALED(sts):
357                    return -WTERMSIG(sts)
358                elif WIFEXITED(sts):
359                    return WEXITSTATUS(sts)
360                else:
361                    raise error, "Not stopped, signaled or exited???"
362
363    def spawnv(mode, file, args):
364        """spawnv(mode, file, args) -> integer
365
366Execute file with arguments from args in a subprocess.
367If mode == P_NOWAIT return the pid of the process.
368If mode == P_WAIT return the process's exit code if it exits normally;
369otherwise return -SIG, where SIG is the signal that killed it. """
370        return _spawnvef(mode, file, args, None, execv)
371
372    def spawnve(mode, file, args, env):
373        """spawnve(mode, file, args, env) -> integer
374
375Execute file with arguments from args in a subprocess with the
376specified environment.
377If mode == P_NOWAIT return the pid of the process.
378If mode == P_WAIT return the process's exit code if it exits normally;
379otherwise return -SIG, where SIG is the signal that killed it. """
380        return _spawnvef(mode, file, args, env, execve)
381
382    # Note: spawnvp[e] is't currently supported on Windows
383
384    def spawnvp(mode, file, args):
385        """spawnvp(mode, file, args) -> integer
386
387Execute file (which is looked for along $PATH) with arguments from
388args in a subprocess.
389If mode == P_NOWAIT return the pid of the process.
390If mode == P_WAIT return the process's exit code if it exits normally;
391otherwise return -SIG, where SIG is the signal that killed it. """
392        return _spawnvef(mode, file, args, None, execvp)
393
394    def spawnvpe(mode, file, args, env):
395        """spawnvpe(mode, file, args, env) -> integer
396
397Execute file (which is looked for along $PATH) with arguments from
398args in a subprocess with the supplied environment.
399If mode == P_NOWAIT return the pid of the process.
400If mode == P_WAIT return the process's exit code if it exits normally;
401otherwise return -SIG, where SIG is the signal that killed it. """
402        return _spawnvef(mode, file, args, env, execvpe)
403
404if _exists("spawnv"):
405    # These aren't supplied by the basic Windows code
406    # but can be easily implemented in Python
407
408    def spawnl(mode, file, *args):
409        """spawnl(mode, file, *args) -> integer
410
411Execute file with arguments from args in a subprocess.
412If mode == P_NOWAIT return the pid of the process.
413If mode == P_WAIT return the process's exit code if it exits normally;
414otherwise return -SIG, where SIG is the signal that killed it. """
415        return spawnv(mode, file, args)
416
417    def spawnle(mode, file, *args):
418        """spawnle(mode, file, *args, env) -> integer
419
420Execute file with arguments from args in a subprocess with the
421supplied environment.
422If mode == P_NOWAIT return the pid of the process.
423If mode == P_WAIT return the process's exit code if it exits normally;
424otherwise return -SIG, where SIG is the signal that killed it. """
425        env = args[-1]
426        return spawnve(mode, file, args[:-1], env)
427
428if _exists("spawnvp"):
429    # At the moment, Windows doesn't implement spawnvp[e],
430    # so it won't have spawnlp[e] either.
431    def spawnlp(mode, file, *args):
432        """spawnlp(mode, file, *args, env) -> integer
433
434Execute file (which is looked for along $PATH) with arguments from
435args in a subprocess with the supplied environment.
436If mode == P_NOWAIT return the pid of the process.
437If mode == P_WAIT return the process's exit code if it exits normally;
438otherwise return -SIG, where SIG is the signal that killed it. """
439        return spawnvp(mode, file, args)
440
441    def spawnlpe(mode, file, *args):
442        """spawnlpe(mode, file, *args, env) -> integer
443
444Execute file (which is looked for along $PATH) with arguments from
445args in a subprocess with the supplied environment.
446If mode == P_NOWAIT return the pid of the process.
447If mode == P_WAIT return the process's exit code if it exits normally;
448otherwise return -SIG, where SIG is the signal that killed it. """
449        env = args[-1]
450        return spawnvpe(mode, file, args[:-1], env)
451
452
453