os.py revision 54f0222547b1e92cd018ef132307a6f793dc9505
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]) -> None 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) -> None 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) -> None 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 """execv(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 322_notfound = None 323def _execvpe(file, args, env=None): 324 if env is not None: 325 func = execve 326 argrest = (args, env) 327 else: 328 func = execv 329 argrest = (args,) 330 env = environ 331 global _notfound 332 head, tail = path.split(file) 333 if head: 334 apply(func, (file,) + argrest) 335 return 336 if 'PATH' in env: 337 envpath = env['PATH'] 338 else: 339 envpath = defpath 340 PATH = envpath.split(pathsep) 341 if not _notfound: 342 if sys.platform[:4] == 'beos': 343 # Process handling (fork, wait) under BeOS (up to 5.0) 344 # doesn't interoperate reliably with the thread interlocking 345 # that happens during an import. The actual error we need 346 # is the same on BeOS for posix.open() et al., ENOENT. 347 try: unlink('/_#.# ## #.#') 348 except error, _notfound: pass 349 else: 350 import tempfile 351 t = tempfile.mktemp() 352 # Exec a file that is guaranteed not to exist 353 try: execv(t, ('blah',)) 354 except error, _notfound: pass 355 exc, arg = error, _notfound 356 for dir in PATH: 357 fullname = path.join(dir, file) 358 try: 359 apply(func, (fullname,) + argrest) 360 except error, (errno, msg): 361 if errno != arg[0]: 362 exc, arg = error, (errno, msg) 363 raise exc, arg 364 365 366# Change environ to automatically call putenv() if it exists 367try: 368 # This will fail if there's no putenv 369 putenv 370except NameError: 371 pass 372else: 373 import UserDict 374 375 # Fake unsetenv() for Windows 376 # not sure about os2 and dos here but 377 # I'm guessing they are the same. 378 379 if name in ('os2', 'nt', 'dos'): 380 def unsetenv(key): 381 putenv(key, "") 382 383 if name == "riscos": 384 # On RISC OS, all env access goes through getenv and putenv 385 from riscosenviron import _Environ 386 elif name in ('os2', 'nt', 'dos'): # Where Env Var Names Must Be UPPERCASE 387 # But we store them as upper case 388 class _Environ(UserDict.UserDict): 389 def __init__(self, environ): 390 UserDict.UserDict.__init__(self) 391 data = self.data 392 for k, v in environ.items(): 393 data[k.upper()] = v 394 def __setitem__(self, key, item): 395 putenv(key, item) 396 self.data[key.upper()] = item 397 def __getitem__(self, key): 398 return self.data[key.upper()] 399 try: 400 unsetenv 401 except NameError: 402 def __delitem__(self, key): 403 del self.data[key.upper()] 404 else: 405 def __delitem__(self, key): 406 unsetenv(key) 407 del self.data[key.upper()] 408 def has_key(self, key): 409 return key.upper() in self.data 410 def __contains__(self, key): 411 return key.upper() in self.data 412 def get(self, key, failobj=None): 413 return self.data.get(key.upper(), failobj) 414 def update(self, dict): 415 for k, v in dict.items(): 416 self[k] = v 417 def copy(self): 418 return dict(self) 419 420 else: # Where Env Var Names Can Be Mixed Case 421 class _Environ(UserDict.UserDict): 422 def __init__(self, environ): 423 UserDict.UserDict.__init__(self) 424 self.data = environ 425 def __setitem__(self, key, item): 426 putenv(key, item) 427 self.data[key] = item 428 def update(self, dict): 429 for k, v in dict.items(): 430 self[k] = v 431 try: 432 unsetenv 433 except NameError: 434 pass 435 else: 436 def __delitem__(self, key): 437 unsetenv(key) 438 del self.data[key] 439 def copy(self): 440 return dict(self) 441 442 443 environ = _Environ(environ) 444 445 def getenv(key, default=None): 446 """Get an environment variable, return None if it doesn't exist. 447 The optional second argument can specify an alternate default.""" 448 return environ.get(key, default) 449 __all__.append("getenv") 450 451def _exists(name): 452 try: 453 eval(name) 454 return True 455 except NameError: 456 return False 457 458# Supply spawn*() (probably only for Unix) 459if _exists("fork") and not _exists("spawnv") and _exists("execv"): 460 461 P_WAIT = 0 462 P_NOWAIT = P_NOWAITO = 1 463 464 # XXX Should we support P_DETACH? I suppose it could fork()**2 465 # and close the std I/O streams. Also, P_OVERLAY is the same 466 # as execv*()? 467 468 def _spawnvef(mode, file, args, env, func): 469 # Internal helper; func is the exec*() function to use 470 pid = fork() 471 if not pid: 472 # Child 473 try: 474 if env is None: 475 func(file, args) 476 else: 477 func(file, args, env) 478 except: 479 _exit(127) 480 else: 481 # Parent 482 if mode == P_NOWAIT: 483 return pid # Caller is responsible for waiting! 484 while 1: 485 wpid, sts = waitpid(pid, 0) 486 if WIFSTOPPED(sts): 487 continue 488 elif WIFSIGNALED(sts): 489 return -WTERMSIG(sts) 490 elif WIFEXITED(sts): 491 return WEXITSTATUS(sts) 492 else: 493 raise error, "Not stopped, signaled or exited???" 494 495 def spawnv(mode, file, args): 496 """spawnv(mode, file, args) -> integer 497 498Execute file with arguments from args in a subprocess. 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 _spawnvef(mode, file, args, None, execv) 503 504 def spawnve(mode, file, args, env): 505 """spawnve(mode, file, args, env) -> integer 506 507Execute file with arguments from args in a subprocess with the 508specified 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 return _spawnvef(mode, file, args, env, execve) 513 514 # Note: spawnvp[e] is't currently supported on Windows 515 516 def spawnvp(mode, file, args): 517 """spawnvp(mode, file, args) -> integer 518 519Execute file (which is looked for along $PATH) with arguments from 520args in a subprocess. 521If mode == P_NOWAIT return the pid of the process. 522If mode == P_WAIT return the process's exit code if it exits normally; 523otherwise return -SIG, where SIG is the signal that killed it. """ 524 return _spawnvef(mode, file, args, None, execvp) 525 526 def spawnvpe(mode, file, args, env): 527 """spawnvpe(mode, file, args, env) -> integer 528 529Execute file (which is looked for along $PATH) with arguments from 530args in a subprocess with the supplied environment. 531If mode == P_NOWAIT return the pid of the process. 532If mode == P_WAIT return the process's exit code if it exits normally; 533otherwise return -SIG, where SIG is the signal that killed it. """ 534 return _spawnvef(mode, file, args, env, execvpe) 535 536if _exists("spawnv"): 537 # These aren't supplied by the basic Windows code 538 # but can be easily implemented in Python 539 540 def spawnl(mode, file, *args): 541 """spawnl(mode, file, *args) -> integer 542 543Execute file with arguments from args in a subprocess. 544If mode == P_NOWAIT return the pid of the process. 545If mode == P_WAIT return the process's exit code if it exits normally; 546otherwise return -SIG, where SIG is the signal that killed it. """ 547 return spawnv(mode, file, args) 548 549 def spawnle(mode, file, *args): 550 """spawnle(mode, file, *args, env) -> integer 551 552Execute file with arguments from args in a subprocess with the 553supplied environment. 554If mode == P_NOWAIT return the pid of the process. 555If mode == P_WAIT return the process's exit code if it exits normally; 556otherwise return -SIG, where SIG is the signal that killed it. """ 557 env = args[-1] 558 return spawnve(mode, file, args[:-1], env) 559 560if _exists("spawnvp"): 561 # At the moment, Windows doesn't implement spawnvp[e], 562 # so it won't have spawnlp[e] either. 563 def spawnlp(mode, file, *args): 564 """spawnlp(mode, file, *args, env) -> integer 565 566Execute file (which is looked for along $PATH) with arguments from 567args in a subprocess with the supplied environment. 568If mode == P_NOWAIT return the pid of the process. 569If mode == P_WAIT return the process's exit code if it exits normally; 570otherwise return -SIG, where SIG is the signal that killed it. """ 571 return spawnvp(mode, file, args) 572 573 def spawnlpe(mode, file, *args): 574 """spawnlpe(mode, file, *args, env) -> integer 575 576Execute file (which is looked for along $PATH) with arguments from 577args in a subprocess with the supplied environment. 578If mode == P_NOWAIT return the pid of the process. 579If mode == P_WAIT return the process's exit code if it exits normally; 580otherwise return -SIG, where SIG is the signal that killed it. """ 581 env = args[-1] 582 return spawnvpe(mode, file, args[:-1], env) 583 584 585 __all__.extend(["spawnlp","spawnlpe","spawnv", "spawnve","spawnvp", 586 "spawnvpe","spawnl","spawnle",]) 587 588 589# Supply popen2 etc. (for Unix) 590if _exists("fork"): 591 if not _exists("popen2"): 592 def popen2(cmd, mode="t", bufsize=-1): 593 import popen2 594 stdout, stdin = popen2.popen2(cmd, bufsize) 595 return stdin, stdout 596 __all__.append("popen2") 597 598 if not _exists("popen3"): 599 def popen3(cmd, mode="t", bufsize=-1): 600 import popen2 601 stdout, stdin, stderr = popen2.popen3(cmd, bufsize) 602 return stdin, stdout, stderr 603 __all__.append("popen3") 604 605 if not _exists("popen4"): 606 def popen4(cmd, mode="t", bufsize=-1): 607 import popen2 608 stdout, stdin = popen2.popen4(cmd, bufsize) 609 return stdin, stdout 610 __all__.append("popen4") 611 612import copy_reg as _copy_reg 613 614def _make_stat_result(tup, dict): 615 return stat_result(tup, dict) 616 617def _pickle_stat_result(sr): 618 (type, args) = sr.__reduce__() 619 return (_make_stat_result, args) 620 621try: 622 _copy_reg.pickle(stat_result, _pickle_stat_result, _make_stat_result) 623except NameError: # stat_result may not exist 624 pass 625 626def _make_statvfs_result(tup, dict): 627 return statvfs_result(tup, dict) 628 629def _pickle_statvfs_result(sr): 630 (type, args) = sr.__reduce__() 631 return (_make_statvfs_result, args) 632 633try: 634 _copy_reg.pickle(statvfs_result, _pickle_statvfs_result, 635 _make_statvfs_result) 636except NameError: # statvfs_result may not exist 637 pass 638