py-cvs-rel2_1 (Rev 1.2) merge
[python/dscho.git] / Lib / os.py
blob64caee6efae0186c1522a5b2adbe23a927b762be
1 r"""OS routines for Mac, DOS, NT, or Posix depending on what system we're on.
3 This 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.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
15 Programs that import and use 'os' stand a better chance of being
16 portable between different platforms. Of course, they must then
17 only use functions that are defined by all platforms (e.g., unlink
18 and opendir), and leave all pathname manipulation to os.path
19 (e.g., split and join).
20 """
24 import sys
26 _names = sys.builtin_module_names
28 altsep = None
30 __all__ = ["altsep", "curdir", "pardir", "sep", "pathsep", "linesep",
31 "defpath", "name"]
33 def _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] != '_']
39 if 'posix' in _names:
40 name = 'posix'
41 linesep = '\n'
42 curdir = '.'; pardir = '..'; sep = '/'; pathsep = ':'
43 defpath = ':/bin:/usr/bin'
44 from posix import *
45 try:
46 from posix import _exit
47 except ImportError:
48 pass
49 import posixpath
50 path = posixpath
51 del posixpath
53 import posix
54 __all__.extend(_get_exports_list(posix))
55 del posix
57 elif 'nt' in _names:
58 name = 'nt'
59 linesep = '\r\n'
60 curdir = '.'; pardir = '..'; sep = '\\'; pathsep = ';'
61 defpath = '.;C:\\bin'
62 from nt import *
63 for i in ['_exit']:
64 try:
65 exec "from nt import " + i
66 except ImportError:
67 pass
68 import ntpath
69 path = ntpath
70 del ntpath
72 import nt
73 __all__.extend(_get_exports_list(nt))
74 del nt
76 elif 'dos' in _names:
77 name = 'dos'
78 linesep = '\r\n'
79 curdir = '.'; pardir = '..'; sep = '\\'; pathsep = ';'
80 defpath = '.;C:\\bin'
81 from dos import *
82 try:
83 from dos import _exit
84 except ImportError:
85 pass
86 import dospath
87 path = dospath
88 del dospath
90 import dos
91 __all__.extend(_get_exports_list(dos))
92 del dos
94 elif 'os2' in _names:
95 name = 'os2'
96 linesep = '\r\n'
97 curdir = '.'; pardir = '..'; sep = '\\'; pathsep = ';'
98 defpath = '.;C:\\bin'
99 from os2 import *
100 try:
101 from os2 import _exit
102 except ImportError:
103 pass
104 import ntpath
105 path = ntpath
106 del ntpath
108 import os2
109 __all__.extend(_get_exports_list(os2))
110 del os2
112 elif 'mac' in _names:
113 name = 'mac'
114 linesep = '\r'
115 curdir = ':'; pardir = '::'; sep = ':'; pathsep = '\n'
116 defpath = ':'
117 from mac import *
118 try:
119 from mac import _exit
120 except ImportError:
121 pass
122 import macpath
123 path = macpath
124 del macpath
126 import mac
127 __all__.extend(_get_exports_list(mac))
128 del mac
130 elif 'ce' in _names:
131 name = 'ce'
132 linesep = '\r\n'
133 curdir = '.'; pardir = '..'; sep = '\\'; pathsep = ';'
134 defpath = '\\Windows'
135 from ce import *
136 for i in ['_exit']:
137 try:
138 exec "from ce import " + i
139 except ImportError:
140 pass
141 # We can use the standard Windows path.
142 import ntpath
143 path = ntpath
144 del ntpath
146 import ce
147 __all__.extend(_get_exports_list(ce))
148 del ce
150 elif 'riscos' in _names:
151 name = 'riscos'
152 linesep = '\n'
153 curdir = '@'; pardir = '^'; sep = '.'; pathsep = ','
154 defpath = '<Run$Dir>'
155 from riscos import *
156 try:
157 from riscos import _exit
158 except ImportError:
159 pass
160 import riscospath
161 path = riscospath
162 del riscospath
164 import riscos
165 __all__.extend(_get_exports_list(riscos))
166 del riscos
168 else:
169 raise ImportError, 'no os specific module found'
171 __all__.append("path")
173 del _names
175 sys.modules['os.path'] = path
179 # Super directory utilities.
180 # (Inspired by Eric Raymond; the doc strings are mostly his)
182 def makedirs(name, mode=0777):
183 """makedirs(path [, mode=0777]) -> None
185 Super-mkdir; create a leaf directory and all intermediate ones.
186 Works like mkdir, except that any intermediate path segment (not
187 just the rightmost) will be created if it does not exist. This is
188 recursive.
191 head, tail = path.split(name)
192 if not tail:
193 head, tail = path.split(head)
194 if head and tail and not path.exists(head):
195 makedirs(head, mode)
196 mkdir(name, mode)
198 def removedirs(name):
199 """removedirs(path) -> None
201 Super-rmdir; remove a leaf directory and empty all intermediate
202 ones. Works like rmdir except that, if the leaf directory is
203 successfully removed, directories corresponding to rightmost path
204 segments will be pruned way until either the whole path is
205 consumed or an error occurs. Errors during this latter phase are
206 ignored -- they generally mean that a directory was not empty.
209 rmdir(name)
210 head, tail = path.split(name)
211 if not tail:
212 head, tail = path.split(head)
213 while head and tail:
214 try:
215 rmdir(head)
216 except error:
217 break
218 head, tail = path.split(head)
220 def renames(old, new):
221 """renames(old, new) -> None
223 Super-rename; create directories as necessary and delete any left
224 empty. Works like rename, except creation of any intermediate
225 directories needed to make the new pathname good is attempted
226 first. After the rename, directories corresponding to rightmost
227 path segments of the old name will be pruned way until either the
228 whole path is consumed or a nonempty directory is found.
230 Note: this function can fail with the new directory structure made
231 if you lack permissions needed to unlink the leaf directory or
232 file.
235 head, tail = path.split(new)
236 if head and tail and not path.exists(head):
237 makedirs(head)
238 rename(old, new)
239 head, tail = path.split(old)
240 if head and tail:
241 try:
242 removedirs(head)
243 except error:
244 pass
246 __all__.extend(["makedirs", "removedirs", "renames"])
248 # Make sure os.environ exists, at least
249 try:
250 environ
251 except NameError:
252 environ = {}
254 def execl(file, *args):
255 """execl(file, *args)
257 Execute the executable file with argument list args, replacing the
258 current process. """
259 execv(file, args)
261 def execle(file, *args):
262 """execle(file, *args, env)
264 Execute the executable file with argument list args and
265 environment env, replacing the current process. """
266 env = args[-1]
267 execve(file, args[:-1], env)
269 def execlp(file, *args):
270 """execlp(file, *args)
272 Execute the executable file (which is searched for along $PATH)
273 with argument list args, replacing the current process. """
274 execvp(file, args)
276 def execlpe(file, *args):
277 """execlpe(file, *args, env)
279 Execute the executable file (which is searched for along $PATH)
280 with argument list args and environment env, replacing the current
281 process. """
282 env = args[-1]
283 execvpe(file, args[:-1], env)
285 def execvp(file, args):
286 """execp(file, args)
288 Execute the executable file (which is searched for along $PATH)
289 with argument list args, replacing the current process.
290 args may be a list or tuple of strings. """
291 _execvpe(file, args)
293 def execvpe(file, args, env):
294 """execv(file, args, env)
296 Execute the executable file (which is searched for along $PATH)
297 with argument list args and environment env , replacing the
298 current process.
299 args may be a list or tuple of strings. """
300 _execvpe(file, args, env)
302 __all__.extend(["execl","execle","execlp","execlpe","execvp","execvpe"])
304 _notfound = None
305 def _execvpe(file, args, env=None):
306 if env is not None:
307 func = execve
308 argrest = (args, env)
309 else:
310 func = execv
311 argrest = (args,)
312 env = environ
313 global _notfound
314 head, tail = path.split(file)
315 if head:
316 apply(func, (file,) + argrest)
317 return
318 if env.has_key('PATH'):
319 envpath = env['PATH']
320 else:
321 envpath = defpath
322 PATH = envpath.split(pathsep)
323 if not _notfound:
324 if sys.platform[:4] == 'beos':
325 # Process handling (fork, wait) under BeOS (up to 5.0)
326 # doesn't interoperate reliably with the thread interlocking
327 # that happens during an import. The actual error we need
328 # is the same on BeOS for posix.open() et al., ENOENT.
329 try: unlink('/_#.# ## #.#')
330 except error, _notfound: pass
331 else:
332 import tempfile
333 t = tempfile.mktemp()
334 # Exec a file that is guaranteed not to exist
335 try: execv(t, ('blah',))
336 except error, _notfound: pass
337 exc, arg = error, _notfound
338 for dir in PATH:
339 fullname = path.join(dir, file)
340 try:
341 apply(func, (fullname,) + argrest)
342 except error, (errno, msg):
343 if errno != arg[0]:
344 exc, arg = error, (errno, msg)
345 raise exc, arg
348 # Change environ to automatically call putenv() if it exists
349 try:
350 # This will fail if there's no putenv
351 putenv
352 except NameError:
353 pass
354 else:
355 import UserDict
357 if name == "riscos":
358 # On RISC OS, all env access goes through getenv and putenv
359 from riscosenviron import _Environ
360 elif name in ('os2', 'nt', 'dos'): # Where Env Var Names Must Be UPPERCASE
361 # But we store them as upper case
362 class _Environ(UserDict.UserDict):
363 def __init__(self, environ):
364 UserDict.UserDict.__init__(self)
365 data = self.data
366 for k, v in environ.items():
367 data[k.upper()] = v
368 def __setitem__(self, key, item):
369 putenv(key, item)
370 self.data[key.upper()] = item
371 def __getitem__(self, key):
372 return self.data[key.upper()]
373 def __delitem__(self, key):
374 del self.data[key.upper()]
375 def has_key(self, key):
376 return self.data.has_key(key.upper())
377 def get(self, key, failobj=None):
378 return self.data.get(key.upper(), failobj)
379 def update(self, dict):
380 for k, v in dict.items():
381 self[k] = v
383 else: # Where Env Var Names Can Be Mixed Case
384 class _Environ(UserDict.UserDict):
385 def __init__(self, environ):
386 UserDict.UserDict.__init__(self)
387 self.data = environ
388 def __setitem__(self, key, item):
389 putenv(key, item)
390 self.data[key] = item
391 def update(self, dict):
392 for k, v in dict.items():
393 self[k] = v
395 environ = _Environ(environ)
397 def getenv(key, default=None):
398 """Get an environment variable, return None if it doesn't exist.
399 The optional second argument can specify an alternate default."""
400 return environ.get(key, default)
401 __all__.append("getenv")
403 def _exists(name):
404 try:
405 eval(name)
406 return 1
407 except NameError:
408 return 0
410 # Supply spawn*() (probably only for Unix)
411 if _exists("fork") and not _exists("spawnv") and _exists("execv"):
413 P_WAIT = 0
414 P_NOWAIT = P_NOWAITO = 1
416 # XXX Should we support P_DETACH? I suppose it could fork()**2
417 # and close the std I/O streams. Also, P_OVERLAY is the same
418 # as execv*()?
420 def _spawnvef(mode, file, args, env, func):
421 # Internal helper; func is the exec*() function to use
422 pid = fork()
423 if not pid:
424 # Child
425 try:
426 if env is None:
427 func(file, args)
428 else:
429 func(file, args, env)
430 except:
431 _exit(127)
432 else:
433 # Parent
434 if mode == P_NOWAIT:
435 return pid # Caller is responsible for waiting!
436 while 1:
437 wpid, sts = waitpid(pid, 0)
438 if WIFSTOPPED(sts):
439 continue
440 elif WIFSIGNALED(sts):
441 return -WTERMSIG(sts)
442 elif WIFEXITED(sts):
443 return WEXITSTATUS(sts)
444 else:
445 raise error, "Not stopped, signaled or exited???"
447 def spawnv(mode, file, args):
448 """spawnv(mode, file, args) -> integer
450 Execute file with arguments from args in a subprocess.
451 If mode == P_NOWAIT return the pid of the process.
452 If mode == P_WAIT return the process's exit code if it exits normally;
453 otherwise return -SIG, where SIG is the signal that killed it. """
454 return _spawnvef(mode, file, args, None, execv)
456 def spawnve(mode, file, args, env):
457 """spawnve(mode, file, args, env) -> integer
459 Execute file with arguments from args in a subprocess with the
460 specified environment.
461 If mode == P_NOWAIT return the pid of the process.
462 If mode == P_WAIT return the process's exit code if it exits normally;
463 otherwise return -SIG, where SIG is the signal that killed it. """
464 return _spawnvef(mode, file, args, env, execve)
466 # Note: spawnvp[e] is't currently supported on Windows
468 def spawnvp(mode, file, args):
469 """spawnvp(mode, file, args) -> integer
471 Execute file (which is looked for along $PATH) with arguments from
472 args in a subprocess.
473 If mode == P_NOWAIT return the pid of the process.
474 If mode == P_WAIT return the process's exit code if it exits normally;
475 otherwise return -SIG, where SIG is the signal that killed it. """
476 return _spawnvef(mode, file, args, None, execvp)
478 def spawnvpe(mode, file, args, env):
479 """spawnvpe(mode, file, args, env) -> integer
481 Execute file (which is looked for along $PATH) with arguments from
482 args in a subprocess with the supplied environment.
483 If mode == P_NOWAIT return the pid of the process.
484 If mode == P_WAIT return the process's exit code if it exits normally;
485 otherwise return -SIG, where SIG is the signal that killed it. """
486 return _spawnvef(mode, file, args, env, execvpe)
488 if _exists("spawnv"):
489 # These aren't supplied by the basic Windows code
490 # but can be easily implemented in Python
492 def spawnl(mode, file, *args):
493 """spawnl(mode, file, *args) -> integer
495 Execute file with arguments from args in a subprocess.
496 If mode == P_NOWAIT return the pid of the process.
497 If mode == P_WAIT return the process's exit code if it exits normally;
498 otherwise return -SIG, where SIG is the signal that killed it. """
499 return spawnv(mode, file, args)
501 def spawnle(mode, file, *args):
502 """spawnle(mode, file, *args, env) -> integer
504 Execute file with arguments from args in a subprocess with the
505 supplied environment.
506 If mode == P_NOWAIT return the pid of the process.
507 If mode == P_WAIT return the process's exit code if it exits normally;
508 otherwise return -SIG, where SIG is the signal that killed it. """
509 env = args[-1]
510 return spawnve(mode, file, args[:-1], env)
512 if _exists("spawnvp"):
513 # At the moment, Windows doesn't implement spawnvp[e],
514 # so it won't have spawnlp[e] either.
515 def spawnlp(mode, file, *args):
516 """spawnlp(mode, file, *args, env) -> integer
518 Execute file (which is looked for along $PATH) with arguments from
519 args in a subprocess with the supplied environment.
520 If mode == P_NOWAIT return the pid of the process.
521 If mode == P_WAIT return the process's exit code if it exits normally;
522 otherwise return -SIG, where SIG is the signal that killed it. """
523 return spawnvp(mode, file, args)
525 def spawnlpe(mode, file, *args):
526 """spawnlpe(mode, file, *args, env) -> integer
528 Execute file (which is looked for along $PATH) with arguments from
529 args in a subprocess with the supplied environment.
530 If mode == P_NOWAIT return the pid of the process.
531 If mode == P_WAIT return the process's exit code if it exits normally;
532 otherwise return -SIG, where SIG is the signal that killed it. """
533 env = args[-1]
534 return spawnvpe(mode, file, args[:-1], env)
537 __all__.extend(["spawnlp","spawnlpe","spawnv", "spawnve","spawnvp",
538 "spawnvpe","spawnl","spawnle",])
541 # Supply popen2 etc. (for Unix)
542 if _exists("fork"):
543 if not _exists("popen2"):
544 def popen2(cmd, mode="t", bufsize=-1):
545 import popen2
546 stdout, stdin = popen2.popen2(cmd, bufsize)
547 return stdin, stdout
548 __all__.append("popen2")
550 if not _exists("popen3"):
551 def popen3(cmd, mode="t", bufsize=-1):
552 import popen2
553 stdout, stdin, stderr = popen2.popen3(cmd, bufsize)
554 return stdin, stdout, stderr
555 __all__.append("popen3")
557 if not _exists("popen4"):
558 def popen4(cmd, mode="t", bufsize=-1):
559 import popen2
560 stdout, stdin = popen2.popen4(cmd, bufsize)
561 return stdin, stdout
562 __all__.append("popen4")