1 2# Module 'os' -- OS routines for NT, Posix, or UEFI depending on what system we're on. 3# 4# Copyright (c) 2015, Daryl McDaniel. All rights reserved.<BR> 5# Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR> 6# This program and the accompanying materials are licensed and made available under 7# the terms and conditions of the BSD License that accompanies this distribution. 8# The full text of the license may be found at 9# http://opensource.org/licenses/bsd-license. 10# 11# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 14r"""OS routines for NT, Posix, or UEFI depending on what system we're on. 15 16This exports: 17 - all functions from edk2, posix, nt, os2, or ce, e.g. unlink, stat, etc. 18 - os.path is one of the modules uefipath, posixpath, or ntpath 19 - os.name is 'edk2', 'posix', 'nt', 'os2', 'ce' or 'riscos' 20 - os.curdir is a string representing the current directory ('.' or ':') 21 - os.pardir is a string representing the parent directory ('..' or '::') 22 - os.sep is the (or a most common) pathname separator ('/' or ':' or '\\') 23 - os.extsep is the extension separator ('.' or '/') 24 - os.altsep is the alternate pathname separator (None or '/') 25 - os.pathsep is the component separator used in $PATH etc 26 - os.linesep is the line separator in text files ('\r' or '\n' or '\r\n') 27 - os.defpath is the default search path for executables 28 - os.devnull is the file path of the null device ('/dev/null', etc.) 29 30Programs that import and use 'os' stand a better chance of being 31portable between different platforms. Of course, they must then 32only use functions that are defined by all platforms (e.g., unlink 33and opendir), and leave all pathname manipulation to os.path 34(e.g., split and join). 35""" 36 37#' 38 39import sys, errno 40 41_names = sys.builtin_module_names 42 43# Note: more names are added to __all__ later. 44__all__ = ["altsep", "curdir", "pardir", "sep", "extsep", "pathsep", "linesep", 45 "defpath", "name", "path", "devnull", 46 "SEEK_SET", "SEEK_CUR", "SEEK_END"] 47 48def _get_exports_list(module): 49 try: 50 return list(module.__all__) 51 except AttributeError: 52 return [n for n in dir(module) if n[0] != '_'] 53 54if 'posix' in _names: 55 name = 'posix' 56 linesep = '\n' 57 from posix import * 58 try: 59 from posix import _exit 60 except ImportError: 61 pass 62 import posixpath as path 63 64 import posix 65 __all__.extend(_get_exports_list(posix)) 66 del posix 67 68elif 'nt' in _names: 69 name = 'nt' 70 linesep = '\r\n' 71 from nt import * 72 try: 73 from nt import _exit 74 except ImportError: 75 pass 76 import ntpath as path 77 78 import nt 79 __all__.extend(_get_exports_list(nt)) 80 del nt 81 82elif 'os2' in _names: 83 name = 'os2' 84 linesep = '\r\n' 85 from os2 import * 86 try: 87 from os2 import _exit 88 except ImportError: 89 pass 90 if sys.version.find('EMX GCC') == -1: 91 import ntpath as path 92 else: 93 import os2emxpath as path 94 from _emx_link import link 95 96 import os2 97 __all__.extend(_get_exports_list(os2)) 98 del os2 99 100elif 'ce' in _names: 101 name = 'ce' 102 linesep = '\r\n' 103 from ce import * 104 try: 105 from ce import _exit 106 except ImportError: 107 pass 108 # We can use the standard Windows path. 109 import ntpath as path 110 111 import ce 112 __all__.extend(_get_exports_list(ce)) 113 del ce 114 115elif 'riscos' in _names: 116 name = 'riscos' 117 linesep = '\n' 118 from riscos import * 119 try: 120 from riscos import _exit 121 except ImportError: 122 pass 123 import riscospath as path 124 125 import riscos 126 __all__.extend(_get_exports_list(riscos)) 127 del riscos 128 129elif 'edk2' in _names: 130 name = 'edk2' 131 linesep = '\n' 132 from edk2 import * 133 try: 134 from edk2 import _exit 135 except ImportError: 136 pass 137 import ntpath as path 138 139 import edk2 140 __all__.extend(_get_exports_list(edk2)) 141 del edk2 142 143else: 144 raise ImportError, 'no os specific module found' 145 146sys.modules['os.path'] = path 147from os.path import (curdir, pardir, sep, pathsep, defpath, extsep, altsep, 148 devnull) 149 150del _names 151 152# Python uses fixed values for the SEEK_ constants; they are mapped 153# to native constants if necessary in posixmodule.c 154SEEK_SET = 0 155SEEK_CUR = 1 156SEEK_END = 2 157 158#' 159 160# Super directory utilities. 161# (Inspired by Eric Raymond; the doc strings are mostly his) 162 163def makedirs(name, mode=0777): 164 """makedirs(path [, mode=0777]) 165 166 Super-mkdir; create a leaf directory and all intermediate ones. 167 Works like mkdir, except that any intermediate path segment (not 168 just the rightmost) will be created if it does not exist. This is 169 recursive. 170 171 """ 172 head, tail = path.split(name) 173 if not tail: 174 head, tail = path.split(head) 175 if head and tail and not path.exists(head): 176 try: 177 makedirs(head, mode) 178 except OSError, e: 179 # be happy if someone already created the path 180 if e.errno != errno.EEXIST: 181 raise 182 if tail == curdir: # xxx/newdir/. exists if xxx/newdir exists 183 return 184 mkdir(name, mode) 185 186def removedirs(name): 187 """removedirs(path) 188 189 Super-rmdir; remove a leaf directory and all empty intermediate 190 ones. Works like rmdir except that, if the leaf directory is 191 successfully removed, directories corresponding to rightmost path 192 segments will be pruned away until either the whole path is 193 consumed or an error occurs. Errors during this latter phase are 194 ignored -- they generally mean that a directory was not empty. 195 196 """ 197 rmdir(name) 198 head, tail = path.split(name) 199 if not tail: 200 head, tail = path.split(head) 201 while head and tail: 202 try: 203 rmdir(head) 204 except error: 205 break 206 head, tail = path.split(head) 207 208def renames(old, new): 209 """renames(old, new) 210 211 Super-rename; create directories as necessary and delete any left 212 empty. Works like rename, except creation of any intermediate 213 directories needed to make the new pathname good is attempted 214 first. After the rename, directories corresponding to rightmost 215 path segments of the old name will be pruned until either the 216 whole path is consumed or a nonempty directory is found. 217 218 Note: this function can fail with the new directory structure made 219 if you lack permissions needed to unlink the leaf directory or 220 file. 221 222 """ 223 head, tail = path.split(new) 224 if head and tail and not path.exists(head): 225 makedirs(head) 226 rename(old, new) 227 head, tail = path.split(old) 228 if head and tail: 229 try: 230 removedirs(head) 231 except error: 232 pass 233 234__all__.extend(["makedirs", "removedirs", "renames"]) 235 236def walk(top, topdown=True, onerror=None, followlinks=False): 237 """Directory tree generator. 238 239 For each directory in the directory tree rooted at top (including top 240 itself, but excluding '.' and '..'), yields a 3-tuple 241 242 dirpath, dirnames, filenames 243 244 dirpath is a string, the path to the directory. dirnames is a list of 245 the names of the subdirectories in dirpath (excluding '.' and '..'). 246 filenames is a list of the names of the non-directory files in dirpath. 247 Note that the names in the lists are just names, with no path components. 248 To get a full path (which begins with top) to a file or directory in 249 dirpath, do os.path.join(dirpath, name). 250 251 If optional arg 'topdown' is true or not specified, the triple for a 252 directory is generated before the triples for any of its subdirectories 253 (directories are generated top down). If topdown is false, the triple 254 for a directory is generated after the triples for all of its 255 subdirectories (directories are generated bottom up). 256 257 When topdown is true, the caller can modify the dirnames list in-place 258 (e.g., via del or slice assignment), and walk will only recurse into the 259 subdirectories whose names remain in dirnames; this can be used to prune the 260 search, or to impose a specific order of visiting. Modifying dirnames when 261 topdown is false is ineffective, since the directories in dirnames have 262 already been generated by the time dirnames itself is generated. No matter 263 the value of topdown, the list of subdirectories is retrieved before the 264 tuples for the directory and its subdirectories are generated. 265 266 By default errors from the os.listdir() call are ignored. If 267 optional arg 'onerror' is specified, it should be a function; it 268 will be called with one argument, an os.error instance. It can 269 report the error to continue with the walk, or raise the exception 270 to abort the walk. Note that the filename is available as the 271 filename attribute of the exception object. 272 273 By default, os.walk does not follow symbolic links to subdirectories on 274 systems that support them. In order to get this functionality, set the 275 optional argument 'followlinks' to true. 276 277 Caution: if you pass a relative pathname for top, don't change the 278 current working directory between resumptions of walk. walk never 279 changes the current directory, and assumes that the client doesn't 280 either. 281 282 Example: 283 284 import os 285 from os.path import join, getsize 286 for root, dirs, files in os.walk('python/Lib/email'): 287 print root, "consumes", 288 print sum([getsize(join(root, name)) for name in files]), 289 print "bytes in", len(files), "non-directory files" 290 if 'CVS' in dirs: 291 dirs.remove('CVS') # don't visit CVS directories 292 293 """ 294 295 islink, join, isdir = path.islink, path.join, path.isdir 296 297 # We may not have read permission for top, in which case we can't 298 # get a list of the files the directory contains. os.path.walk 299 # always suppressed the exception then, rather than blow up for a 300 # minor reason when (say) a thousand readable directories are still 301 # left to visit. That logic is copied here. 302 try: 303 # Note that listdir and error are globals in this module due 304 # to earlier import-*. 305 names = listdir(top) 306 except error, err: 307 if onerror is not None: 308 onerror(err) 309 return 310 311 dirs, nondirs = [], [] 312 for name in names: 313 if isdir(join(top, name)): 314 dirs.append(name) 315 else: 316 nondirs.append(name) 317 318 if topdown: 319 yield top, dirs, nondirs 320 for name in dirs: 321 new_path = join(top, name) 322 if followlinks or not islink(new_path): 323 for x in walk(new_path, topdown, onerror, followlinks): 324 yield x 325 if not topdown: 326 yield top, dirs, nondirs 327 328__all__.append("walk") 329 330# Make sure os.environ exists, at least 331try: 332 environ 333except NameError: 334 environ = {} 335 336def execl(file, *args): 337 """execl(file, *args) 338 339 Execute the executable file with argument list args, replacing the 340 current process. """ 341 execv(file, args) 342 343def execle(file, *args): 344 """execle(file, *args, env) 345 346 Execute the executable file with argument list args and 347 environment env, replacing the current process. """ 348 env = args[-1] 349 execve(file, args[:-1], env) 350 351def execlp(file, *args): 352 """execlp(file, *args) 353 354 Execute the executable file (which is searched for along $PATH) 355 with argument list args, replacing the current process. """ 356 execvp(file, args) 357 358def execlpe(file, *args): 359 """execlpe(file, *args, env) 360 361 Execute the executable file (which is searched for along $PATH) 362 with argument list args and environment env, replacing the current 363 process. """ 364 env = args[-1] 365 execvpe(file, args[:-1], env) 366 367def execvp(file, args): 368 """execvp(file, args) 369 370 Execute the executable file (which is searched for along $PATH) 371 with argument list args, replacing the current process. 372 args may be a list or tuple of strings. """ 373 _execvpe(file, args) 374 375def execvpe(file, args, env): 376 """execvpe(file, args, env) 377 378 Execute the executable file (which is searched for along $PATH) 379 with argument list args and environment env , replacing the 380 current process. 381 args may be a list or tuple of strings. """ 382 _execvpe(file, args, env) 383 384__all__.extend(["execl","execle","execlp","execlpe","execvp","execvpe"]) 385 386def _execvpe(file, args, env=None): 387 if env is not None: 388 func = execve 389 argrest = (args, env) 390 else: 391 func = execv 392 argrest = (args,) 393 env = environ 394 395 head, tail = path.split(file) 396 if head: 397 func(file, *argrest) 398 return 399 if 'PATH' in env: 400 envpath = env['PATH'] 401 else: 402 envpath = defpath 403 PATH = envpath.split(pathsep) 404 saved_exc = None 405 saved_tb = None 406 for dir in PATH: 407 fullname = path.join(dir, file) 408 try: 409 func(fullname, *argrest) 410 except error, e: 411 tb = sys.exc_info()[2] 412 if (e.errno != errno.ENOENT and e.errno != errno.ENOTDIR 413 and saved_exc is None): 414 saved_exc = e 415 saved_tb = tb 416 if saved_exc: 417 raise error, saved_exc, saved_tb 418 raise error, e, tb 419 420# Change environ to automatically call putenv() if it exists 421try: 422 # This will fail if there's no putenv 423 putenv 424except NameError: 425 pass 426else: 427 import UserDict 428 429 # Fake unsetenv() for Windows 430 # not sure about os2 here but 431 # I'm guessing they are the same. 432 433 if name in ('os2', 'nt'): 434 def unsetenv(key): 435 putenv(key, "") 436 437 if name == "riscos": 438 # On RISC OS, all env access goes through getenv and putenv 439 from riscosenviron import _Environ 440 elif name in ('os2', 'nt'): # Where Env Var Names Must Be UPPERCASE 441 # But we store them as upper case 442 class _Environ(UserDict.IterableUserDict): 443 def __init__(self, environ): 444 UserDict.UserDict.__init__(self) 445 data = self.data 446 for k, v in environ.items(): 447 data[k.upper()] = v 448 def __setitem__(self, key, item): 449 putenv(key, item) 450 self.data[key.upper()] = item 451 def __getitem__(self, key): 452 return self.data[key.upper()] 453 try: 454 unsetenv 455 except NameError: 456 def __delitem__(self, key): 457 del self.data[key.upper()] 458 else: 459 def __delitem__(self, key): 460 unsetenv(key) 461 del self.data[key.upper()] 462 def clear(self): 463 for key in self.data.keys(): 464 unsetenv(key) 465 del self.data[key] 466 def pop(self, key, *args): 467 unsetenv(key) 468 return self.data.pop(key.upper(), *args) 469 def has_key(self, key): 470 return key.upper() in self.data 471 def __contains__(self, key): 472 return key.upper() in self.data 473 def get(self, key, failobj=None): 474 return self.data.get(key.upper(), failobj) 475 def update(self, dict=None, **kwargs): 476 if dict: 477 try: 478 keys = dict.keys() 479 except AttributeError: 480 # List of (key, value) 481 for k, v in dict: 482 self[k] = v 483 else: 484 # got keys 485 # cannot use items(), since mappings 486 # may not have them. 487 for k in keys: 488 self[k] = dict[k] 489 if kwargs: 490 self.update(kwargs) 491 def copy(self): 492 return dict(self) 493 494 else: # Where Env Var Names Can Be Mixed Case 495 class _Environ(UserDict.IterableUserDict): 496 def __init__(self, environ): 497 UserDict.UserDict.__init__(self) 498 self.data = environ 499 def __setitem__(self, key, item): 500 putenv(key, item) 501 self.data[key] = item 502 def update(self, dict=None, **kwargs): 503 if dict: 504 try: 505 keys = dict.keys() 506 except AttributeError: 507 # List of (key, value) 508 for k, v in dict: 509 self[k] = v 510 else: 511 # got keys 512 # cannot use items(), since mappings 513 # may not have them. 514 for k in keys: 515 self[k] = dict[k] 516 if kwargs: 517 self.update(kwargs) 518 try: 519 unsetenv 520 except NameError: 521 pass 522 else: 523 def __delitem__(self, key): 524 unsetenv(key) 525 del self.data[key] 526 def clear(self): 527 for key in self.data.keys(): 528 unsetenv(key) 529 del self.data[key] 530 def pop(self, key, *args): 531 unsetenv(key) 532 return self.data.pop(key, *args) 533 def copy(self): 534 return dict(self) 535 536 537 environ = _Environ(environ) 538 539def getenv(key, default=None): 540 """Get an environment variable, return None if it doesn't exist. 541 The optional second argument can specify an alternate default.""" 542 return environ.get(key, default) 543__all__.append("getenv") 544 545def _exists(name): 546 return name in globals() 547 548# Supply spawn*() (probably only for Unix) 549if _exists("fork") and not _exists("spawnv") and _exists("execv"): 550 551 P_WAIT = 0 552 P_NOWAIT = P_NOWAITO = 1 553 554 # XXX Should we support P_DETACH? I suppose it could fork()**2 555 # and close the std I/O streams. Also, P_OVERLAY is the same 556 # as execv*()? 557 558 def _spawnvef(mode, file, args, env, func): 559 # Internal helper; func is the exec*() function to use 560 pid = fork() 561 if not pid: 562 # Child 563 try: 564 if env is None: 565 func(file, args) 566 else: 567 func(file, args, env) 568 except: 569 _exit(127) 570 else: 571 # Parent 572 if mode == P_NOWAIT: 573 return pid # Caller is responsible for waiting! 574 while 1: 575 wpid, sts = waitpid(pid, 0) 576 if WIFSTOPPED(sts): 577 continue 578 elif WIFSIGNALED(sts): 579 return -WTERMSIG(sts) 580 elif WIFEXITED(sts): 581 return WEXITSTATUS(sts) 582 else: 583 raise error, "Not stopped, signaled or exited???" 584 585 def spawnv(mode, file, args): 586 """spawnv(mode, file, args) -> integer 587 588Execute file with arguments from args in a subprocess. 589If mode == P_NOWAIT return the pid of the process. 590If mode == P_WAIT return the process's exit code if it exits normally; 591otherwise return -SIG, where SIG is the signal that killed it. """ 592 return _spawnvef(mode, file, args, None, execv) 593 594 def spawnve(mode, file, args, env): 595 """spawnve(mode, file, args, env) -> integer 596 597Execute file with arguments from args in a subprocess with the 598specified environment. 599If mode == P_NOWAIT return the pid of the process. 600If mode == P_WAIT return the process's exit code if it exits normally; 601otherwise return -SIG, where SIG is the signal that killed it. """ 602 return _spawnvef(mode, file, args, env, execve) 603 604 # Note: spawnvp[e] is't currently supported on Windows 605 606 def spawnvp(mode, file, args): 607 """spawnvp(mode, file, args) -> integer 608 609Execute file (which is looked for along $PATH) with arguments from 610args in a subprocess. 611If mode == P_NOWAIT return the pid of the process. 612If mode == P_WAIT return the process's exit code if it exits normally; 613otherwise return -SIG, where SIG is the signal that killed it. """ 614 return _spawnvef(mode, file, args, None, execvp) 615 616 def spawnvpe(mode, file, args, env): 617 """spawnvpe(mode, file, args, env) -> integer 618 619Execute file (which is looked for along $PATH) with arguments from 620args in a subprocess with the supplied environment. 621If mode == P_NOWAIT return the pid of the process. 622If mode == P_WAIT return the process's exit code if it exits normally; 623otherwise return -SIG, where SIG is the signal that killed it. """ 624 return _spawnvef(mode, file, args, env, execvpe) 625 626if _exists("spawnv"): 627 # These aren't supplied by the basic Windows code 628 # but can be easily implemented in Python 629 630 def spawnl(mode, file, *args): 631 """spawnl(mode, file, *args) -> integer 632 633Execute file with arguments from args in a subprocess. 634If mode == P_NOWAIT return the pid of the process. 635If mode == P_WAIT return the process's exit code if it exits normally; 636otherwise return -SIG, where SIG is the signal that killed it. """ 637 return spawnv(mode, file, args) 638 639 def spawnle(mode, file, *args): 640 """spawnle(mode, file, *args, env) -> integer 641 642Execute file with arguments from args in a subprocess with the 643supplied environment. 644If mode == P_NOWAIT return the pid of the process. 645If mode == P_WAIT return the process's exit code if it exits normally; 646otherwise return -SIG, where SIG is the signal that killed it. """ 647 env = args[-1] 648 return spawnve(mode, file, args[:-1], env) 649 650 651 __all__.extend(["spawnv", "spawnve", "spawnl", "spawnle",]) 652 653 654if _exists("spawnvp"): 655 # At the moment, Windows doesn't implement spawnvp[e], 656 # so it won't have spawnlp[e] either. 657 def spawnlp(mode, file, *args): 658 """spawnlp(mode, file, *args) -> integer 659 660Execute file (which is looked for along $PATH) with arguments from 661args in a subprocess with the supplied environment. 662If mode == P_NOWAIT return the pid of the process. 663If mode == P_WAIT return the process's exit code if it exits normally; 664otherwise return -SIG, where SIG is the signal that killed it. """ 665 return spawnvp(mode, file, args) 666 667 def spawnlpe(mode, file, *args): 668 """spawnlpe(mode, file, *args, env) -> integer 669 670Execute file (which is looked for along $PATH) with arguments from 671args in a subprocess with the supplied environment. 672If mode == P_NOWAIT return the pid of the process. 673If mode == P_WAIT return the process's exit code if it exits normally; 674otherwise return -SIG, where SIG is the signal that killed it. """ 675 env = args[-1] 676 return spawnvpe(mode, file, args[:-1], env) 677 678 679 __all__.extend(["spawnvp", "spawnvpe", "spawnlp", "spawnlpe",]) 680 681 682# Supply popen2 etc. (for Unix) 683if _exists("fork"): 684 if not _exists("popen2"): 685 def popen2(cmd, mode="t", bufsize=-1): 686 """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' 687 may be a sequence, in which case arguments will be passed directly to 688 the program without shell intervention (as with os.spawnv()). If 'cmd' 689 is a string it will be passed to the shell (as with os.system()). If 690 'bufsize' is specified, it sets the buffer size for the I/O pipes. The 691 file objects (child_stdin, child_stdout) are returned.""" 692 import warnings 693 msg = "os.popen2 is deprecated. Use the subprocess module." 694 warnings.warn(msg, DeprecationWarning, stacklevel=2) 695 696 import subprocess 697 PIPE = subprocess.PIPE 698 p = subprocess.Popen(cmd, shell=isinstance(cmd, basestring), 699 bufsize=bufsize, stdin=PIPE, stdout=PIPE, 700 close_fds=True) 701 return p.stdin, p.stdout 702 __all__.append("popen2") 703 704 if not _exists("popen3"): 705 def popen3(cmd, mode="t", bufsize=-1): 706 """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' 707 may be a sequence, in which case arguments will be passed directly to 708 the program without shell intervention (as with os.spawnv()). If 'cmd' 709 is a string it will be passed to the shell (as with os.system()). If 710 'bufsize' is specified, it sets the buffer size for the I/O pipes. The 711 file objects (child_stdin, child_stdout, child_stderr) are returned.""" 712 import warnings 713 msg = "os.popen3 is deprecated. Use the subprocess module." 714 warnings.warn(msg, DeprecationWarning, stacklevel=2) 715 716 import subprocess 717 PIPE = subprocess.PIPE 718 p = subprocess.Popen(cmd, shell=isinstance(cmd, basestring), 719 bufsize=bufsize, stdin=PIPE, stdout=PIPE, 720 stderr=PIPE, close_fds=True) 721 return p.stdin, p.stdout, p.stderr 722 __all__.append("popen3") 723 724 if not _exists("popen4"): 725 def popen4(cmd, mode="t", bufsize=-1): 726 """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' 727 may be a sequence, in which case arguments will be passed directly to 728 the program without shell intervention (as with os.spawnv()). If 'cmd' 729 is a string it will be passed to the shell (as with os.system()). If 730 'bufsize' is specified, it sets the buffer size for the I/O pipes. The 731 file objects (child_stdin, child_stdout_stderr) are returned.""" 732 import warnings 733 msg = "os.popen4 is deprecated. Use the subprocess module." 734 warnings.warn(msg, DeprecationWarning, stacklevel=2) 735 736 import subprocess 737 PIPE = subprocess.PIPE 738 p = subprocess.Popen(cmd, shell=isinstance(cmd, basestring), 739 bufsize=bufsize, stdin=PIPE, stdout=PIPE, 740 stderr=subprocess.STDOUT, close_fds=True) 741 return p.stdin, p.stdout 742 __all__.append("popen4") 743 744import copy_reg as _copy_reg 745 746def _make_stat_result(tup, dict): 747 return stat_result(tup, dict) 748 749def _pickle_stat_result(sr): 750 (type, args) = sr.__reduce__() 751 return (_make_stat_result, args) 752 753try: 754 _copy_reg.pickle(stat_result, _pickle_stat_result, _make_stat_result) 755except NameError: # stat_result may not exist 756 pass 757 758def _make_statvfs_result(tup, dict): 759 return statvfs_result(tup, dict) 760 761def _pickle_statvfs_result(sr): 762 (type, args) = sr.__reduce__() 763 return (_make_statvfs_result, args) 764 765try: 766 _copy_reg.pickle(statvfs_result, _pickle_statvfs_result, 767 _make_statvfs_result) 768except NameError: # statvfs_result may not exist 769 pass 770