os.py revision 117910dc445a2262bd96bbfefaf43714ae59c11b
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, os2, mac, or ce, e.g. unlink, stat, etc. 5 - os.path is one of the modules posixpath, ntpath, or macpath 6 - os.name is 'posix', 'nt', '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 29__all__ = ["altsep", "curdir", "pardir", "sep", "pathsep", "linesep", 30 "defpath", "name", "path"] 31 32def _get_exports_list(module): 33 try: 34 return list(module.__all__) 35 except AttributeError: 36 return [n for n in dir(module) if n[0] != '_'] 37 38if 'posix' in _names: 39 name = 'posix' 40 linesep = '\n' 41 from posix import * 42 try: 43 from posix import _exit 44 except ImportError: 45 pass 46 import posixpath as path 47 48 import posix 49 __all__.extend(_get_exports_list(posix)) 50 del posix 51 52elif 'nt' in _names: 53 name = 'nt' 54 linesep = '\r\n' 55 from nt import * 56 try: 57 from nt import _exit 58 except ImportError: 59 pass 60 import ntpath as path 61 62 import nt 63 __all__.extend(_get_exports_list(nt)) 64 del nt 65 66elif 'os2' in _names: 67 name = 'os2' 68 linesep = '\r\n' 69 from os2 import * 70 try: 71 from os2 import _exit 72 except ImportError: 73 pass 74 if sys.version.find('EMX GCC') == -1: 75 import ntpath as path 76 else: 77 import os2emxpath as path 78 79 import os2 80 __all__.extend(_get_exports_list(os2)) 81 del os2 82 83elif 'mac' in _names: 84 name = 'mac' 85 linesep = '\r' 86 from mac import * 87 try: 88 from mac import _exit 89 except ImportError: 90 pass 91 import macpath as path 92 93 import mac 94 __all__.extend(_get_exports_list(mac)) 95 del mac 96 97elif 'ce' in _names: 98 name = 'ce' 99 linesep = '\r\n' 100 from ce import * 101 try: 102 from ce import _exit 103 except ImportError: 104 pass 105 # We can use the standard Windows path. 106 import ntpath as path 107 108 import ce 109 __all__.extend(_get_exports_list(ce)) 110 del ce 111 112elif 'riscos' in _names: 113 name = 'riscos' 114 linesep = '\n' 115 from riscos import * 116 try: 117 from riscos import _exit 118 except ImportError: 119 pass 120 import riscospath as path 121 122 import riscos 123 __all__.extend(_get_exports_list(riscos)) 124 del riscos 125 126else: 127 raise ImportError, 'no os specific module found' 128 129sys.modules['os.path'] = path 130from os.path import curdir, pardir, sep, pathsep, defpath, extsep, altsep 131 132del _names 133 134#' 135 136# Super directory utilities. 137# (Inspired by Eric Raymond; the doc strings are mostly his) 138 139def makedirs(name, mode=0777): 140 """makedirs(path [, mode=0777]) 141 142 Super-mkdir; create a leaf directory and all intermediate ones. 143 Works like mkdir, except that any intermediate path segment (not 144 just the rightmost) will be created if it does not exist. This is 145 recursive. 146 147 """ 148 head, tail = path.split(name) 149 if not tail: 150 head, tail = path.split(head) 151 if head and tail and not path.exists(head): 152 makedirs(head, mode) 153 mkdir(name, mode) 154 155def removedirs(name): 156 """removedirs(path) 157 158 Super-rmdir; remove a leaf directory and empty all intermediate 159 ones. Works like rmdir except that, if the leaf directory is 160 successfully removed, directories corresponding to rightmost path 161 segments will be pruned way until either the whole path is 162 consumed or an error occurs. Errors during this latter phase are 163 ignored -- they generally mean that a directory was not empty. 164 165 """ 166 rmdir(name) 167 head, tail = path.split(name) 168 if not tail: 169 head, tail = path.split(head) 170 while head and tail: 171 try: 172 rmdir(head) 173 except error: 174 break 175 head, tail = path.split(head) 176 177def renames(old, new): 178 """renames(old, new) 179 180 Super-rename; create directories as necessary and delete any left 181 empty. Works like rename, except creation of any intermediate 182 directories needed to make the new pathname good is attempted 183 first. After the rename, directories corresponding to rightmost 184 path segments of the old name will be pruned way until either the 185 whole path is consumed or a nonempty directory is found. 186 187 Note: this function can fail with the new directory structure made 188 if you lack permissions needed to unlink the leaf directory or 189 file. 190 191 """ 192 head, tail = path.split(new) 193 if head and tail and not path.exists(head): 194 makedirs(head) 195 rename(old, new) 196 head, tail = path.split(old) 197 if head and tail: 198 try: 199 removedirs(head) 200 except error: 201 pass 202 203__all__.extend(["makedirs", "removedirs", "renames"]) 204 205# Make sure os.environ exists, at least 206try: 207 environ 208except NameError: 209 environ = {} 210 211def execl(file, *args): 212 """execl(file, *args) 213 214 Execute the executable file with argument list args, replacing the 215 current process. """ 216 execv(file, args) 217 218def execle(file, *args): 219 """execle(file, *args, env) 220 221 Execute the executable file with argument list args and 222 environment env, replacing the current process. """ 223 env = args[-1] 224 execve(file, args[:-1], env) 225 226def execlp(file, *args): 227 """execlp(file, *args) 228 229 Execute the executable file (which is searched for along $PATH) 230 with argument list args, replacing the current process. """ 231 execvp(file, args) 232 233def execlpe(file, *args): 234 """execlpe(file, *args, env) 235 236 Execute the executable file (which is searched for along $PATH) 237 with argument list args and environment env, replacing the current 238 process. """ 239 env = args[-1] 240 execvpe(file, args[:-1], env) 241 242def execvp(file, args): 243 """execp(file, args) 244 245 Execute the executable file (which is searched for along $PATH) 246 with argument list args, replacing the current process. 247 args may be a list or tuple of strings. """ 248 _execvpe(file, args) 249 250def execvpe(file, args, env): 251 """execvpe(file, args, env) 252 253 Execute the executable file (which is searched for along $PATH) 254 with argument list args and environment env , replacing the 255 current process. 256 args may be a list or tuple of strings. """ 257 _execvpe(file, args, env) 258 259__all__.extend(["execl","execle","execlp","execlpe","execvp","execvpe"]) 260 261def _execvpe(file, args, env=None): 262 from errno import ENOENT, ENOTDIR 263 264 if env is not None: 265 func = execve 266 argrest = (args, env) 267 else: 268 func = execv 269 argrest = (args,) 270 env = environ 271 272 head, tail = path.split(file) 273 if head: 274 apply(func, (file,) + argrest) 275 return 276 if 'PATH' in env: 277 envpath = env['PATH'] 278 else: 279 envpath = defpath 280 PATH = envpath.split(pathsep) 281 saved_exc = None 282 saved_tb = None 283 for dir in PATH: 284 fullname = path.join(dir, file) 285 try: 286 apply(func, (fullname,) + argrest) 287 except error, e: 288 tb = sys.exc_info()[2] 289 if (e.errno != ENOENT and e.errno != ENOTDIR 290 and saved_exc is None): 291 saved_exc = e 292 saved_tb = tb 293 if saved_exc: 294 raise error, saved_exc, saved_tb 295 raise error, e, tb 296 297# Change environ to automatically call putenv() if it exists 298try: 299 # This will fail if there's no putenv 300 putenv 301except NameError: 302 pass 303else: 304 import UserDict 305 306 # Fake unsetenv() for Windows 307 # not sure about os2 here but 308 # I'm guessing they are the same. 309 310 if name in ('os2', 'nt'): 311 def unsetenv(key): 312 putenv(key, "") 313 314 if name == "riscos": 315 # On RISC OS, all env access goes through getenv and putenv 316 from riscosenviron import _Environ 317 elif name in ('os2', 'nt'): # Where Env Var Names Must Be UPPERCASE 318 # But we store them as upper case 319 class _Environ(UserDict.IterableUserDict): 320 def __init__(self, environ): 321 UserDict.UserDict.__init__(self) 322 data = self.data 323 for k, v in environ.items(): 324 data[k.upper()] = v 325 def __setitem__(self, key, item): 326 putenv(key, item) 327 self.data[key.upper()] = item 328 def __getitem__(self, key): 329 return self.data[key.upper()] 330 try: 331 unsetenv 332 except NameError: 333 def __delitem__(self, key): 334 del self.data[key.upper()] 335 else: 336 def __delitem__(self, key): 337 unsetenv(key) 338 del self.data[key.upper()] 339 def has_key(self, key): 340 return key.upper() in self.data 341 def __contains__(self, key): 342 return key.upper() in self.data 343 def get(self, key, failobj=None): 344 return self.data.get(key.upper(), failobj) 345 def update(self, dict): 346 for k, v in dict.items(): 347 self[k] = v 348 def copy(self): 349 return dict(self) 350 351 else: # Where Env Var Names Can Be Mixed Case 352 class _Environ(UserDict.IterableUserDict): 353 def __init__(self, environ): 354 UserDict.UserDict.__init__(self) 355 self.data = environ 356 def __setitem__(self, key, item): 357 putenv(key, item) 358 self.data[key] = item 359 def update(self, dict): 360 for k, v in dict.items(): 361 self[k] = v 362 try: 363 unsetenv 364 except NameError: 365 pass 366 else: 367 def __delitem__(self, key): 368 unsetenv(key) 369 del self.data[key] 370 def copy(self): 371 return dict(self) 372 373 374 environ = _Environ(environ) 375 376def getenv(key, default=None): 377 """Get an environment variable, return None if it doesn't exist. 378 The optional second argument can specify an alternate default.""" 379 return environ.get(key, default) 380__all__.append("getenv") 381 382def _exists(name): 383 try: 384 eval(name) 385 return True 386 except NameError: 387 return False 388 389# Supply spawn*() (probably only for Unix) 390if _exists("fork") and not _exists("spawnv") and _exists("execv"): 391 392 P_WAIT = 0 393 P_NOWAIT = P_NOWAITO = 1 394 395 # XXX Should we support P_DETACH? I suppose it could fork()**2 396 # and close the std I/O streams. Also, P_OVERLAY is the same 397 # as execv*()? 398 399 def _spawnvef(mode, file, args, env, func): 400 # Internal helper; func is the exec*() function to use 401 pid = fork() 402 if not pid: 403 # Child 404 try: 405 if env is None: 406 func(file, args) 407 else: 408 func(file, args, env) 409 except: 410 _exit(127) 411 else: 412 # Parent 413 if mode == P_NOWAIT: 414 return pid # Caller is responsible for waiting! 415 while 1: 416 wpid, sts = waitpid(pid, 0) 417 if WIFSTOPPED(sts): 418 continue 419 elif WIFSIGNALED(sts): 420 return -WTERMSIG(sts) 421 elif WIFEXITED(sts): 422 return WEXITSTATUS(sts) 423 else: 424 raise error, "Not stopped, signaled or exited???" 425 426 def spawnv(mode, file, args): 427 """spawnv(mode, file, args) -> integer 428 429Execute file with arguments from args in a subprocess. 430If mode == P_NOWAIT return the pid of the process. 431If mode == P_WAIT return the process's exit code if it exits normally; 432otherwise return -SIG, where SIG is the signal that killed it. """ 433 return _spawnvef(mode, file, args, None, execv) 434 435 def spawnve(mode, file, args, env): 436 """spawnve(mode, file, args, env) -> integer 437 438Execute file with arguments from args in a subprocess with the 439specified environment. 440If mode == P_NOWAIT return the pid of the process. 441If mode == P_WAIT return the process's exit code if it exits normally; 442otherwise return -SIG, where SIG is the signal that killed it. """ 443 return _spawnvef(mode, file, args, env, execve) 444 445 # Note: spawnvp[e] is't currently supported on Windows 446 447 def spawnvp(mode, file, args): 448 """spawnvp(mode, file, args) -> integer 449 450Execute file (which is looked for along $PATH) with arguments from 451args in a subprocess. 452If mode == P_NOWAIT return the pid of the process. 453If mode == P_WAIT return the process's exit code if it exits normally; 454otherwise return -SIG, where SIG is the signal that killed it. """ 455 return _spawnvef(mode, file, args, None, execvp) 456 457 def spawnvpe(mode, file, args, env): 458 """spawnvpe(mode, file, args, env) -> integer 459 460Execute file (which is looked for along $PATH) with arguments from 461args in a subprocess with the supplied environment. 462If mode == P_NOWAIT return the pid of the process. 463If mode == P_WAIT return the process's exit code if it exits normally; 464otherwise return -SIG, where SIG is the signal that killed it. """ 465 return _spawnvef(mode, file, args, env, execvpe) 466 467if _exists("spawnv"): 468 # These aren't supplied by the basic Windows code 469 # but can be easily implemented in Python 470 471 def spawnl(mode, file, *args): 472 """spawnl(mode, file, *args) -> integer 473 474Execute file with arguments from args in a subprocess. 475If mode == P_NOWAIT return the pid of the process. 476If mode == P_WAIT return the process's exit code if it exits normally; 477otherwise return -SIG, where SIG is the signal that killed it. """ 478 return spawnv(mode, file, args) 479 480 def spawnle(mode, file, *args): 481 """spawnle(mode, file, *args, env) -> integer 482 483Execute file with arguments from args in a subprocess with the 484supplied environment. 485If mode == P_NOWAIT return the pid of the process. 486If mode == P_WAIT return the process's exit code if it exits normally; 487otherwise return -SIG, where SIG is the signal that killed it. """ 488 env = args[-1] 489 return spawnve(mode, file, args[:-1], env) 490 491if _exists("spawnvp"): 492 # At the moment, Windows doesn't implement spawnvp[e], 493 # so it won't have spawnlp[e] either. 494 def spawnlp(mode, file, *args): 495 """spawnlp(mode, file, *args, env) -> integer 496 497Execute file (which is looked for along $PATH) with arguments from 498args in a subprocess with the supplied environment. 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 spawnvp(mode, file, args) 503 504 def spawnlpe(mode, file, *args): 505 """spawnlpe(mode, file, *args, env) -> integer 506 507Execute file (which is looked for along $PATH) with arguments from 508args in a subprocess with the supplied 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 env = args[-1] 513 return spawnvpe(mode, file, args[:-1], env) 514 515 516 __all__.extend(["spawnlp","spawnlpe","spawnv", "spawnve","spawnvp", 517 "spawnvpe","spawnl","spawnle",]) 518 519 520# Supply popen2 etc. (for Unix) 521if _exists("fork"): 522 if not _exists("popen2"): 523 def popen2(cmd, mode="t", bufsize=-1): 524 import popen2 525 stdout, stdin = popen2.popen2(cmd, bufsize) 526 return stdin, stdout 527 __all__.append("popen2") 528 529 if not _exists("popen3"): 530 def popen3(cmd, mode="t", bufsize=-1): 531 import popen2 532 stdout, stdin, stderr = popen2.popen3(cmd, bufsize) 533 return stdin, stdout, stderr 534 __all__.append("popen3") 535 536 if not _exists("popen4"): 537 def popen4(cmd, mode="t", bufsize=-1): 538 import popen2 539 stdout, stdin = popen2.popen4(cmd, bufsize) 540 return stdin, stdout 541 __all__.append("popen4") 542 543import copy_reg as _copy_reg 544 545def _make_stat_result(tup, dict): 546 return stat_result(tup, dict) 547 548def _pickle_stat_result(sr): 549 (type, args) = sr.__reduce__() 550 return (_make_stat_result, args) 551 552try: 553 _copy_reg.pickle(stat_result, _pickle_stat_result, _make_stat_result) 554except NameError: # stat_result may not exist 555 pass 556 557def _make_statvfs_result(tup, dict): 558 return statvfs_result(tup, dict) 559 560def _pickle_statvfs_result(sr): 561 (type, args) = sr.__reduce__() 562 return (_make_statvfs_result, args) 563 564try: 565 _copy_reg.pickle(statvfs_result, _pickle_statvfs_result, 566 _make_statvfs_result) 567except NameError: # statvfs_result may not exist 568 pass 569