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