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