os.py revision e0cd291b8123859191cbef90316d55b39e4ce3a1
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    execv(file, args)
187
188def execle(file, *args):
189    env = args[-1]
190    execve(file, args[:-1], env)
191
192def execlp(file, *args):
193    execvp(file, args)
194
195def execlpe(file, *args):
196    env = args[-1]
197    execvpe(file, args[:-1], env)
198
199def execvp(file, args):
200    _execvpe(file, args)
201
202def execvpe(file, args, env):
203    _execvpe(file, args, env)
204
205_notfound = None
206def _execvpe(file, args, env=None):
207    if env is not None:
208        func = execve
209        argrest = (args, env)
210    else:
211        func = execv
212        argrest = (args,)
213        env = environ
214    global _notfound
215    head, tail = path.split(file)
216    if head:
217        apply(func, (file,) + argrest)
218        return
219    if env.has_key('PATH'):
220        envpath = env['PATH']
221    else:
222        envpath = defpath
223    PATH = envpath.split(pathsep)
224    if not _notfound:
225        import tempfile
226        # Exec a file that is guaranteed not to exist
227        try: execv(tempfile.mktemp(), ())
228        except error, _notfound: pass
229    exc, arg = error, _notfound
230    for dir in PATH:
231        fullname = path.join(dir, file)
232        try:
233            apply(func, (fullname,) + argrest)
234        except error, (errno, msg):
235            if errno != arg[0]:
236                exc, arg = error, (errno, msg)
237    raise exc, arg
238
239# Change environ to automatically call putenv() if it exists
240try:
241    # This will fail if there's no putenv
242    putenv
243except NameError:
244    pass
245else:
246    import UserDict
247
248    if name in ('os2', 'nt', 'dos'):  # Where Env Var Names Must Be UPPERCASE
249        # But we store them as upper case
250        class _Environ(UserDict.UserDict):
251            def __init__(self, environ):
252                UserDict.UserDict.__init__(self)
253                data = self.data
254                for k, v in environ.items():
255                    data[k.upper()] = v
256            def __setitem__(self, key, item):
257                putenv(key, item)
258                self.data[key.upper()] = item
259            def __getitem__(self, key):
260                return self.data[key.upper()]
261            def __delitem__(self, key):
262                del self.data[key.upper()]
263            def has_key(self, key):
264                return self.data.has_key(key.upper())
265            def get(self, key, failobj=None):
266                return self.data.get(key.upper(), failobj)
267            def update(self, dict):
268                for k, v in dict.items():
269                    self[k] = v
270
271    else:  # Where Env Var Names Can Be Mixed Case
272        class _Environ(UserDict.UserDict):
273            def __init__(self, environ):
274                UserDict.UserDict.__init__(self)
275                self.data = environ
276            def __setitem__(self, key, item):
277                putenv(key, item)
278                self.data[key] = item
279            def update(self, dict):
280                for k, v in dict.items():
281                    self[k] = v
282
283    environ = _Environ(environ)
284
285def getenv(key, default=None):
286    """Get an environment variable, return None if it doesn't exist.
287
288    The optional second argument can specify an alternative default."""
289    return environ.get(key, default)
290
291def _exists(name):
292    try:
293        eval(name)
294        return 1
295    except NameError:
296        return 0
297
298# Supply spawn*() (probably only for Unix)
299if _exists("fork") and not _exists("spawnv") and _exists("execv"):
300
301    P_WAIT = 0
302    P_NOWAIT = P_NOWAITO = 1
303
304    # XXX Should we support P_DETACH?  I suppose it could fork()**2
305    # and close the std I/O streams.  Also, P_OVERLAY is the same
306    # as execv*()?
307
308    def _spawnvef(mode, file, args, env, func):
309        # Internal helper; func is the exec*() function to use
310        pid = fork()
311        if not pid:
312            # Child
313            try:
314                if env is None:
315                    func(file, args)
316                else:
317                    func(file, args, env)
318            except:
319                _exit(127)
320        else:
321            # Parent
322            if mode == P_NOWAIT:
323                return pid # Caller is responsible for waiting!
324            while 1:
325                wpid, sts = waitpid(pid, 0)
326                if WIFSTOPPED(sts):
327                    continue
328                elif WIFSIGNALED(sts):
329                    return -WTERMSIG(sts)
330                elif WIFEXITED(sts):
331                    return WEXITSTATUS(sts)
332                else:
333                    raise error, "Not stopped, signaled or exited???"
334
335    def spawnv(mode, file, args):
336        """spawnv(mode, file, args) -> integer
337
338Execute file with arguments from args in a subprocess.
339If mode == P_NOWAIT return the pid of the process.
340If mode == P_WAIT return the process's exit code if it exits normally;
341otherwise return - (the signal that killed it). """
342        return _spawnvef(mode, file, args, None, execv)
343
344    def spawnve(mode, file, args, env):
345        """spawnve(mode, file, args, env) -> integer
346
347Execute file with arguments from args in a subprocess with the
348specified environment.
349If mode == P_NOWAIT return the pid of the process.
350If mode == P_WAIT return the process's exit code if it exits normally;
351otherwise return -SIG, where SIG is the signal that killed it. """
352        return _spawnvef(mode, file, args, env, execve)
353
354    # Note: spawnvp[e] is't currently supported on Windows
355
356    def spawnvp(mode, file, args):
357        """spawnvp(mode, file, args) -> integer
358
359Execute file (which is looked for along $PATH) with arguments from
360args in a subprocess.
361If mode == P_NOWAIT return the pid of the process.
362If mode == P_WAIT return the process's exit code if it exits normally;
363otherwise return -SIG, where SIG is the signal that killed it. """
364        return _spawnvef(mode, file, args, None, execvp)
365
366    def spawnvpe(mode, file, args, env):
367        """spawnvpe(mode, file, args, env) -> integer
368
369Execute file (which is looked for along $PATH) with arguments from
370args in a subprocess with the supplied environment.
371If mode == P_NOWAIT return the pid of the process.
372If mode == P_WAIT return the process's exit code if it exits normally;
373otherwise return -SIG, where SIG is the signal that killed it. """
374        return _spawnvef(mode, file, args, env, execvpe)
375
376if _exists("spawnv"):
377    # These aren't supplied by the basic Windows code
378    # but can be easily implemented in Python
379
380    def spawnl(mode, file, *args):
381        """spawnl(mode, file, *args) -> integer
382
383Execute file with arguments from args in a subprocess.
384If mode == P_NOWAIT return the pid of the process.
385If mode == P_WAIT return the process's exit code if it exits normally;
386otherwise return -SIG, where SIG is the signal that killed it. """
387        return spawnv(mode, file, args)
388
389    def spawnle(mode, file, *args):
390        """spawnle(mode, file, *args, env) -> integer
391
392Execute file with arguments from args in a subprocess with the
393supplied environment.
394If mode == P_NOWAIT return the pid of the process.
395If mode == P_WAIT return the process's exit code if it exits normally;
396otherwise return -SIG, where SIG is the signal that killed it. """
397        env = args[-1]
398        return spawnve(mode, file, args[:-1], env)
399
400if _exists("spawnvp"):
401    # At the moment, Windows doesn't implement spawnvp[e],
402    # so it won't have spawnlp[e] either.
403    def spawnlp(mode, file, *args):
404        """spawnlp(mode, file, *args, env) -> integer
405
406Execute file (which is looked for along $PATH) with arguments from
407args in a subprocess with the supplied environment.
408If mode == P_NOWAIT return the pid of the process.
409If mode == P_WAIT return the process's exit code if it exits normally;
410otherwise return -SIG, where SIG is the signal that killed it. """
411        return spawnvp(mode, file, args)
412
413    def spawnlpe(mode, file, *args):
414        """spawnlpe(mode, file, *args, env) -> integer
415
416Execute file (which is looked for along $PATH) with arguments from
417args in a subprocess with the supplied environment.
418If mode == P_NOWAIT return the pid of the process.
419If mode == P_WAIT return the process's exit code if it exits normally;
420otherwise return -SIG, where SIG is the signal that killed it. """
421        env = args[-1]
422        return spawnvpe(mode, file, args[:-1], env)
423
424
425