Package elisa :: Package extern :: Module path
[hide private]
[frames] | no frames]

Source Code for Module elisa.extern.path

  1  """ path.py - An object representing a path to a file or directory. 
  2   
  3  Example: 
  4   
  5  from path import path 
  6  d = path('/home/guido/bin') 
  7  for f in d.files('*.py'): 
  8      f.chmod(0755) 
  9   
 10  This module requires Python 2.2 or later. 
 11   
 12   
 13  URL:     http://www.jorendorff.com/articles/python/path 
 14  Author:  Jason Orendorff <jason.orendorff\x40gmail\x2ecom> (and others - see the url!) 
 15  Date:    7 Mar 2004 
 16  """ 
 17   
 18   
 19  # TODO 
 20  #   - Tree-walking functions don't avoid symlink loops.  Matt Harrison sent me a patch for this. 
 21  #   - Tree-walking functions can't ignore errors.  Matt Harrison asked for this. 
 22  # 
 23  #   - Two people asked for path.chdir().  This just seems wrong to me, 
 24  #     I dunno.  chdir() is moderately evil anyway. 
 25  # 
 26  #   - Bug in write_text().  It doesn't support Universal newline mode. 
 27  #   - Better error message in listdir() when self isn't a 
 28  #     directory. (On Windows, the error message really sucks.) 
 29  #   - Make sure everything has a good docstring. 
 30  #   - Add methods for regex find and replace. 
 31  #   - guess_content_type() method? 
 32  #   - Perhaps support arguments to touch(). 
 33  #   - Could add split() and join() methods that generate warnings. 
 34   
 35  from __future__ import generators 
 36   
 37  import sys, warnings, os, fnmatch, glob, shutil, codecs, md5 
 38   
 39  __version__ = '2.1' 
 40  __all__ = ['path'] 
 41   
 42  # Platform-specific support for path.owner 
 43  if os.name == 'nt': 
 44      try: 
 45          import win32security 
 46      except ImportError: 
 47          win32security = None 
 48  else: 
 49      try: 
 50          import pwd 
 51      except ImportError: 
 52          pwd = None 
 53   
 54  # Pre-2.3 support.  Are unicode filenames supported? 
 55  if sys.version_info[:2] < (2,3): 
 56      _base = str 
 57      _getcwd = os.getcwd 
 58  else: 
 59      _base = unicode 
 60      _getcwd = os.getcwdu 
 61   
 62  # Pre-2.3 workaround for booleans 
 63  try: 
 64      True, False 
 65  except NameError: 
 66      True, False = 1, 0 
 67   
 68  # Pre-2.3 workaround for basestring. 
 69  try: 
 70      basestring 
 71  except NameError: 
 72      basestring = (str, unicode) 
 73   
 74  # Universal newline support 
 75  _textmode = 'r' 
 76  if hasattr(file, 'newlines'): 
 77      _textmode = 'U' 
 78   
 79  import natural_sort 
 80   
81 -class TreeWalkWarning(Warning):
82 pass
83
84 -class path(_base):
85 """ Represents a filesystem path. 86 87 For documentation on individual methods, consult their 88 counterparts in os.path. 89 """ 90 91 # --- Special Python methods. 92 93 ## def __repr__(self): 94 ## return 'path(%s)' % _base.__repr__(self) 95 96 # Adding a path and a string yields a path.
97 - def __add__(self, more):
98 try: 99 resultStr = _base.__add__(self, more) 100 except TypeError: #Python bug 101 resultStr = NotImplemented 102 if resultStr is NotImplemented: 103 return resultStr 104 return self.__class__(resultStr)
105
106 - def __radd__(self, other):
107 if isinstance(other, basestring): 108 return self.__class__(other.__add__(self)) 109 else: 110 return NotImplemented
111 112 # The / operator joins paths.
113 - def __div__(self, rel):
114 """ fp.__div__(rel) == fp / rel == fp.joinpath(rel) 115 116 Join two path components, adding a separator character if 117 needed. 118 """ 119 return self.__class__(os.path.join(self, rel))
120 121 # Make the / operator work even when true division is enabled. 122 __truediv__ = __div__ 123
124 - def getcwd(cls):
125 """ Return the current working directory as a path object. """ 126 return cls(_getcwd())
127 getcwd = classmethod(getcwd) 128 129 130 # --- Operations on path strings. 131 132 isabs = os.path.isabs
133 - def abspath(self): return self.__class__(os.path.abspath(self))
134 - def normcase(self): return self.__class__(os.path.normcase(self))
135 - def normpath(self): return self.__class__(os.path.normpath(self))
136 - def realpath(self): return self.__class__(os.path.realpath(self))
137 - def expanduser(self): return self.__class__(os.path.expanduser(self))
138 - def expandvars(self): return self.__class__(os.path.expandvars(self))
139 - def dirname(self): return self.__class__(os.path.dirname(self))
140 basename = os.path.basename 141
142 - def expand(self):
143 """ Clean up a filename by calling expandvars(), 144 expanduser(), and normpath() on it. 145 146 This is commonly everything needed to clean up a filename 147 read from a configuration file, for example. 148 """ 149 return self.expandvars().expanduser().normpath()
150
151 - def _get_namebase(self):
152 base, ext = os.path.splitext(self.name) 153 return base
154
155 - def _get_ext(self):
156 f, ext = os.path.splitext(_base(self)) 157 return ext
158
159 - def _get_drive(self):
160 drive, r = os.path.splitdrive(self) 161 return self.__class__(drive)
162 163 parent = property( 164 dirname, None, None, 165 """ This path's parent directory, as a new path object. 166 167 For example, path('/usr/local/lib/libpython.so').parent == path('/usr/local/lib') 168 """) 169 170 name = property( 171 basename, None, None, 172 """ The name of this file or directory without the full path. 173 174 For example, path('/usr/local/lib/libpython.so').name == 'libpython.so' 175 """) 176 177 namebase = property( 178 _get_namebase, None, None, 179 """ The same as path.name, but with one file extension stripped off. 180 181 For example, path('/home/guido/python.tar.gz').name == 'python.tar.gz', 182 but path('/home/guido/python.tar.gz').namebase == 'python.tar' 183 """) 184 185 ext = property( 186 _get_ext, None, None, 187 """ The file extension, for example '.py'. """) 188 189 drive = property( 190 _get_drive, None, None, 191 """ The drive specifier, for example 'C:'. 192 This is always empty on systems that don't use drive specifiers. 193 """) 194
195 - def splitpath(self):
196 """ p.splitpath() -> Return (p.parent, p.name). """ 197 parent, child = os.path.split(self) 198 return self.__class__(parent), child
199
200 - def splitdrive(self):
201 """ p.splitdrive() -> Return (p.drive, <the rest of p>). 202 203 Split the drive specifier from this path. If there is 204 no drive specifier, p.drive is empty, so the return value 205 is simply (path(''), p). This is always the case on Unix. 206 """ 207 drive, rel = os.path.splitdrive(self) 208 return self.__class__(drive), rel
209
210 - def splitext(self):
211 """ p.splitext() -> Return (p.stripext(), p.ext). 212 213 Split the filename extension from this path and return 214 the two parts. Either part may be empty. 215 216 The extension is everything from '.' to the end of the 217 last path segment. This has the property that if 218 (a, b) == p.splitext(), then a + b == p. 219 """ 220 filename, ext = os.path.splitext(self) 221 return self.__class__(filename), ext
222
223 - def stripext(self):
224 """ p.stripext() -> Remove one file extension from the path. 225 226 For example, path('/home/guido/python.tar.gz').stripext() 227 returns path('/home/guido/python.tar'). 228 """ 229 return self.splitext()[0]
230 231 if hasattr(os.path, 'splitunc'):
232 - def splitunc(self):
233 unc, rest = os.path.splitunc(self) 234 return self.__class__(unc), rest
235
236 - def _get_uncshare(self):
237 unc, r = os.path.splitunc(self) 238 return self.__class__(unc)
239 240 uncshare = property( 241 _get_uncshare, None, None, 242 """ The UNC mount point for this path. 243 This is empty for paths on local drives. """) 244
245 - def joinpath(self, *args):
246 """ Join two or more path components, adding a separator 247 character (os.sep) if needed. Returns a new path 248 object. 249 """ 250 return self.__class__(os.path.join(self, *args))
251
252 - def splitall(self):
253 r""" Return a list of the path components in this path. 254 255 The first item in the list will be a path. Its value will be 256 either os.curdir, os.pardir, empty, or the root directory of 257 this path (for example, '/' or 'C:\\'). The other items in 258 the list will be strings. 259 260 path.path.joinpath(*result) will yield the original path. 261 """ 262 parts = [] 263 loc = self 264 while loc != os.curdir and loc != os.pardir: 265 prev = loc 266 loc, child = prev.splitpath() 267 if loc == prev: 268 break 269 parts.append(child) 270 parts.append(loc) 271 parts.reverse() 272 return parts
273
274 - def relpath(self):
275 """ Return this path as a relative path, 276 based from the current working directory. 277 """ 278 cwd = self.__class__(os.getcwd()) 279 return cwd.relpathto(self)
280
281 - def relpathto(self, dest):
282 """ Return a relative path from self to dest. 283 284 If there is no relative path from self to dest, for example if 285 they reside on different drives in Windows, then this returns 286 dest.abspath(). 287 """ 288 origin = self.abspath() 289 dest = self.__class__(dest).abspath() 290 291 orig_list = origin.normcase().splitall() 292 # Don't normcase dest! We want to preserve the case. 293 dest_list = dest.splitall() 294 295 if orig_list[0] != os.path.normcase(dest_list[0]): 296 # Can't get here from there. 297 return dest 298 299 # Find the location where the two paths start to differ. 300 i = 0 301 for start_seg, dest_seg in zip(orig_list, dest_list): 302 if start_seg != os.path.normcase(dest_seg): 303 break 304 i += 1 305 306 # Now i is the point where the two paths diverge. 307 # Need a certain number of "os.pardir"s to work up 308 # from the origin to the point of divergence. 309 segments = [os.pardir] * (len(orig_list) - i) 310 # Need to add the diverging part of dest_list. 311 segments += dest_list[i:] 312 if len(segments) == 0: 313 # If they happen to be identical, use os.curdir. 314 relpath = os.curdir 315 else: 316 relpath = os.path.join(*segments) 317 return self.__class__(relpath)
318 319 # --- Listing, searching, walking, and matching 320
321 - def listdir(self, pattern=None):
322 """ D.listdir() -> List of items in this directory. 323 324 Use D.files() or D.dirs() instead if you want a listing 325 of just files or just subdirectories. 326 327 The elements of the list are path objects. 328 329 With the optional 'pattern' argument, this only lists 330 items whose names match the given pattern. 331 """ 332 names = os.listdir(self) 333 if pattern is not None: 334 names = fnmatch.filter(names, pattern) 335 336 #return [ self / child for child in names ] 337 338 # alphanum sort folders and files separately and put the folders before 339 # the files 340 folders = [] 341 files = [] 342 for fname in names: 343 full_path = self / fname 344 if os.path.isdir(full_path): 345 folders.append(fname) 346 else: 347 files.append(fname) 348 349 key = lambda item: item.lower() 350 folders = natural_sort.obj_natsorted(folders, 351 natural_sort.natcasecmp, 352 key) 353 files = natural_sort.obj_natsorted(files, 354 natural_sort.natcasecmp, 355 key) 356 357 full_paths = [self / child for child in folders + files] 358 return full_paths
359
360 - def dirs(self, pattern=None):
361 """ D.dirs() -> List of this directory's subdirectories. 362 363 The elements of the list are path objects. 364 This does not walk recursively into subdirectories 365 (but see path.walkdirs). 366 367 With the optional 'pattern' argument, this only lists 368 directories whose names match the given pattern. For 369 example, d.dirs('build-*'). 370 """ 371 return [p for p in self.listdir(pattern) if p.isdir()]
372
373 - def files(self, pattern=None):
374 """ D.files() -> List of the files in this directory. 375 376 The elements of the list are path objects. 377 This does not walk into subdirectories (see path.walkfiles). 378 379 With the optional 'pattern' argument, this only lists files 380 whose names match the given pattern. For example, 381 d.files('*.pyc'). 382 """ 383 384 return [p for p in self.listdir(pattern) if p.isfile()]
385
386 - def walk(self, pattern=None, errors='strict'):
387 """ D.walk() -> iterator over files and subdirs, recursively. 388 389 The iterator yields path objects naming each child item of 390 this directory and its descendants. This requires that 391 D.isdir(). 392 393 This performs a depth-first traversal of the directory tree. 394 Each directory is returned just before all its children. 395 396 The errors= keyword argument controls behavior when an 397 error occurs. The default is 'strict', which causes an 398 exception. The other allowed values are 'warn', which 399 reports the error via warnings.warn(), and 'ignore'. 400 """ 401 if errors not in ('strict', 'warn', 'ignore'): 402 raise ValueError("invalid errors parameter") 403 404 try: 405 childList = self.listdir() 406 except Exception: 407 if errors == 'ignore': 408 return 409 elif errors == 'warn': 410 warnings.warn( 411 "Unable to list directory '%s': %s" 412 % (self, sys.exc_info()[1]), 413 TreeWalkWarning) 414 else: 415 raise 416 417 for child in childList: 418 ## if pattern is None or child.fnmatch(pattern): 419 ## yield child 420 if pattern: 421 if not child.fnmatch(pattern): 422 continue 423 else: 424 yield child 425 try: 426 isdir = child.isdir() 427 except Exception: 428 if errors == 'ignore': 429 isdir = False 430 elif errors == 'warn': 431 warnings.warn( 432 "Unable to access '%s': %s" 433 % (child, sys.exc_info()[1]), 434 TreeWalkWarning) 435 isdir = False 436 else: 437 raise 438 439 if isdir: 440 for item in child.walk(pattern, errors): 441 yield item
442
443 - def walkdirs(self, pattern=None, errors='strict'):
444 """ D.walkdirs() -> iterator over subdirs, recursively. 445 446 With the optional 'pattern' argument, this yields only 447 directories whose names match the given pattern. For 448 example, mydir.walkdirs('*test') yields only directories 449 with names ending in 'test'. 450 451 The errors= keyword argument controls behavior when an 452 error occurs. The default is 'strict', which causes an 453 exception. The other allowed values are 'warn', which 454 reports the error via warnings.warn(), and 'ignore'. 455 """ 456 if errors not in ('strict', 'warn', 'ignore'): 457 raise ValueError("invalid errors parameter") 458 459 try: 460 dirs = self.dirs() 461 except Exception: 462 if errors == 'ignore': 463 return 464 elif errors == 'warn': 465 warnings.warn( 466 "Unable to list directory '%s': %s" 467 % (self, sys.exc_info()[1]), 468 TreeWalkWarning) 469 else: 470 raise 471 472 for child in dirs: 473 if pattern is None or child.fnmatch(pattern): 474 yield child 475 for subsubdir in child.walkdirs(pattern, errors): 476 yield subsubdir
477
478 - def walkfiles(self, pattern=None, errors='strict'):
479 """ D.walkfiles() -> iterator over files in D, recursively. 480 481 The optional argument, pattern, limits the results to files 482 with names that match the pattern. For example, 483 mydir.walkfiles('*.tmp') yields only files with the .tmp 484 extension. 485 """ 486 if errors not in ('strict', 'warn', 'ignore'): 487 raise ValueError("invalid errors parameter") 488 489 try: 490 childList = self.listdir() 491 except Exception: 492 if errors == 'ignore': 493 return 494 elif errors == 'warn': 495 warnings.warn( 496 "Unable to list directory '%s': %s" 497 % (self, sys.exc_info()[1]), 498 TreeWalkWarning) 499 else: 500 raise 501 502 for child in childList: 503 try: 504 isfile = child.isfile() 505 isdir = not isfile and child.isdir() 506 except: 507 if errors == 'ignore': 508 return 509 elif errors == 'warn': 510 warnings.warn( 511 "Unable to access '%s': %s" 512 % (self, sys.exc_info()[1]), 513 TreeWalkWarning) 514 else: 515 raise 516 517 if isfile: 518 if pattern is None or child.fnmatch(pattern): 519 yield child 520 elif isdir: 521 for f in child.walkfiles(pattern, errors): 522 yield f
523
524 - def fnmatch(self, pattern):
525 """ Return True if self.name matches the given pattern. 526 527 pattern - A filename pattern with wildcards, 528 for example '*.py'. 529 """ 530 return fnmatch.fnmatch(self.name, pattern)
531
532 - def glob(self, pattern):
533 """ Return a list of path objects that match the pattern. 534 535 pattern - a path relative to this directory, with wildcards. 536 537 For example, path('/users').glob('*/bin/*') returns a list 538 of all the files users have in their bin directories. 539 """ 540 cls = self.__class__ 541 return [cls(s) for s in glob.glob(_base(self / pattern))]
542 543 544 # --- Reading or writing an entire file at once. 545
546 - def open(self, mode='r'):
547 """ Open this file. Return a file object. """ 548 return file(self, mode)
549
550 - def bytes(self):
551 """ Open this file, read all bytes, return them as a string. """ 552 f = self.open('rb') 553 try: 554 return f.read() 555 finally: 556 f.close()
557
558 - def write_bytes(self, bytes, append=False):
559 """ Open this file and write the given bytes to it. 560 561 Default behavior is to overwrite any existing file. 562 Call p.write_bytes(bytes, append=True) to append instead. 563 """ 564 if append: 565 mode = 'ab' 566 else: 567 mode = 'wb' 568 f = self.open(mode) 569 try: 570 f.write(bytes) 571 finally: 572 f.close()
573
574 - def text(self, encoding=None, errors='strict'):
575 r""" Open this file, read it in, return the content as a string. 576 577 This uses 'U' mode in Python 2.3 and later, so '\r\n' and '\r' 578 are automatically translated to '\n'. 579 580 Optional arguments: 581 582 encoding - The Unicode encoding (or character set) of 583 the file. If present, the content of the file is 584 decoded and returned as a unicode object; otherwise 585 it is returned as an 8-bit str. 586 errors - How to handle Unicode errors; see help(str.decode) 587 for the options. Default is 'strict'. 588 """ 589 if encoding is None: 590 # 8-bit 591 f = self.open(_textmode) 592 try: 593 return f.read() 594 finally: 595 f.close() 596 else: 597 # Unicode 598 f = codecs.open(self, 'r', encoding, errors) 599 # (Note - Can't use 'U' mode here, since codecs.open 600 # doesn't support 'U' mode, even in Python 2.3.) 601 try: 602 t = f.read() 603 finally: 604 f.close() 605 return (t.replace(u'\r\n', u'\n') 606 .replace(u'\r\x85', u'\n') 607 .replace(u'\r', u'\n') 608 .replace(u'\x85', u'\n') 609 .replace(u'\u2028', u'\n'))
610
611 - def write_text(self, text, encoding=None, errors='strict', linesep=os.linesep, append=False):
612 r""" Write the given text to this file. 613 614 The default behavior is to overwrite any existing file; 615 to append instead, use the 'append=True' keyword argument. 616 617 There are two differences between path.write_text() and 618 path.write_bytes(): newline handling and Unicode handling. 619 See below. 620 621 Parameters: 622 623 - text - str/unicode - The text to be written. 624 625 - encoding - str - The Unicode encoding that will be used. 626 This is ignored if 'text' isn't a Unicode string. 627 628 - errors - str - How to handle Unicode encoding errors. 629 Default is 'strict'. See help(unicode.encode) for the 630 options. This is ignored if 'text' isn't a Unicode 631 string. 632 633 - linesep - keyword argument - str/unicode - The sequence of 634 characters to be used to mark end-of-line. The default is 635 os.linesep. You can also specify None; this means to 636 leave all newlines as they are in 'text'. 637 638 - append - keyword argument - bool - Specifies what to do if 639 the file already exists (True: append to the end of it; 640 False: overwrite it.) The default is False. 641 642 643 --- Newline handling. 644 645 write_text() converts all standard end-of-line sequences 646 ('\n', '\r', and '\r\n') to your platform's default end-of-line 647 sequence (see os.linesep; on Windows, for example, the 648 end-of-line marker is '\r\n'). 649 650 If you don't like your platform's default, you can override it 651 using the 'linesep=' keyword argument. If you specifically want 652 write_text() to preserve the newlines as-is, use 'linesep=None'. 653 654 This applies to Unicode text the same as to 8-bit text, except 655 there are three additional standard Unicode end-of-line sequences: 656 u'\x85', u'\r\x85', and u'\u2028'. 657 658 (This is slightly different from when you open a file for 659 writing with fopen(filename, "w") in C or file(filename, 'w') 660 in Python.) 661 662 663 --- Unicode 664 665 If 'text' isn't Unicode, then apart from newline handling, the 666 bytes are written verbatim to the file. The 'encoding' and 667 'errors' arguments are not used and must be omitted. 668 669 If 'text' is Unicode, it is first converted to bytes using the 670 specified 'encoding' (or the default encoding if 'encoding' 671 isn't specified). The 'errors' argument applies only to this 672 conversion. 673 674 """ 675 if isinstance(text, unicode): 676 if linesep is not None: 677 # Convert all standard end-of-line sequences to 678 # ordinary newline characters. 679 text = (text.replace(u'\r\n', u'\n') 680 .replace(u'\r\x85', u'\n') 681 .replace(u'\r', u'\n') 682 .replace(u'\x85', u'\n') 683 .replace(u'\u2028', u'\n')) 684 text = text.replace(u'\n', linesep) 685 if encoding is None: 686 encoding = sys.getdefaultencoding() 687 bytes = text.encode(encoding, errors) 688 else: 689 # It is an error to specify an encoding if 'text' is 690 # an 8-bit string. 691 assert encoding is None 692 693 if linesep is not None: 694 text = (text.replace('\r\n', '\n') 695 .replace('\r', '\n')) 696 bytes = text.replace('\n', linesep) 697 698 self.write_bytes(bytes, append)
699
700 - def lines(self, encoding=None, errors='strict', retain=True):
701 r""" Open this file, read all lines, return them in a list. 702 703 Optional arguments: 704 encoding - The Unicode encoding (or character set) of 705 the file. The default is None, meaning the content 706 of the file is read as 8-bit characters and returned 707 as a list of (non-Unicode) str objects. 708 errors - How to handle Unicode errors; see help(str.decode) 709 for the options. Default is 'strict' 710 retain - If true, retain newline characters; but all newline 711 character combinations ('\r', '\n', '\r\n') are 712 translated to '\n'. If false, newline characters are 713 stripped off. Default is True. 714 715 This uses 'U' mode in Python 2.3 and later. 716 """ 717 if encoding is None and retain: 718 f = self.open(_textmode) 719 try: 720 return f.readlines() 721 finally: 722 f.close() 723 else: 724 return self.text(encoding, errors).splitlines(retain)
725
726 - def write_lines(self, lines, encoding=None, errors='strict', 727 linesep=os.linesep, append=False):
728 r""" Write the given lines of text to this file. 729 730 By default this overwrites any existing file at this path. 731 732 This puts a platform-specific newline sequence on every line. 733 See 'linesep' below. 734 735 lines - A list of strings. 736 737 encoding - A Unicode encoding to use. This applies only if 738 'lines' contains any Unicode strings. 739 740 errors - How to handle errors in Unicode encoding. This 741 also applies only to Unicode strings. 742 743 linesep - The desired line-ending. This line-ending is 744 applied to every line. If a line already has any 745 standard line ending ('\r', '\n', '\r\n', u'\x85', 746 u'\r\x85', u'\u2028'), that will be stripped off and 747 this will be used instead. The default is os.linesep, 748 which is platform-dependent ('\r\n' on Windows, '\n' on 749 Unix, etc.) Specify None to write the lines as-is, 750 like file.writelines(). 751 752 Use the keyword argument append=True to append lines to the 753 file. The default is to overwrite the file. Warning: 754 When you use this with Unicode data, if the encoding of the 755 existing data in the file is different from the encoding 756 you specify with the encoding= parameter, the result is 757 mixed-encoding data, which can really confuse someone trying 758 to read the file later. 759 """ 760 if append: 761 mode = 'ab' 762 else: 763 mode = 'wb' 764 f = self.open(mode) 765 try: 766 for line in lines: 767 isUnicode = isinstance(line, unicode) 768 if linesep is not None: 769 # Strip off any existing line-end and add the 770 # specified linesep string. 771 if isUnicode: 772 if line[-2:] in (u'\r\n', u'\x0d\x85'): 773 line = line[:-2] 774 elif line[-1:] in (u'\r', u'\n', 775 u'\x85', u'\u2028'): 776 line = line[:-1] 777 else: 778 if line[-2:] == '\r\n': 779 line = line[:-2] 780 elif line[-1:] in ('\r', '\n'): 781 line = line[:-1] 782 line += linesep 783 if isUnicode: 784 if encoding is None: 785 encoding = sys.getdefaultencoding() 786 line = line.encode(encoding, errors) 787 f.write(line) 788 finally: 789 f.close()
790
791 - def read_md5(self):
792 """ Calculate the md5 hash for this file. 793 794 This reads through the entire file. 795 """ 796 f = self.open('rb') 797 try: 798 m = md5.new() 799 while True: 800 d = f.read(8192) 801 if not d: 802 break 803 m.update(d) 804 finally: 805 f.close() 806 return m.digest()
807 808 # --- Methods for querying the filesystem. 809 810 exists = os.path.exists 811 isdir = os.path.isdir 812 isfile = os.path.isfile 813 islink = os.path.islink 814 ismount = os.path.ismount 815 816 if hasattr(os.path, 'samefile'): 817 samefile = os.path.samefile 818 819 getatime = os.path.getatime 820 atime = property( 821 getatime, None, None, 822 """ Last access time of the file. """) 823 824 getmtime = os.path.getmtime 825 mtime = property( 826 getmtime, None, None, 827 """ Last-modified time of the file. """) 828 829 if hasattr(os.path, 'getctime'): 830 getctime = os.path.getctime 831 ctime = property( 832 getctime, None, None, 833 """ Creation time of the file. """) 834 835 getsize = os.path.getsize 836 size = property( 837 getsize, None, None, 838 """ Size of the file, in bytes. """) 839 840 if hasattr(os, 'access'):
841 - def access(self, mode):
842 """ Return true if current user has access to this path. 843 844 mode - One of the constants os.F_OK, os.R_OK, os.W_OK, os.X_OK 845 """ 846 return os.access(self, mode)
847
848 - def stat(self):
849 """ Perform a stat() system call on this path. """ 850 return os.stat(self)
851
852 - def lstat(self):
853 """ Like path.stat(), but do not follow symbolic links. """ 854 return os.lstat(self)
855
856 - def get_owner(self):
857 r""" Return the name of the owner of this file or directory. 858 859 This follows symbolic links. 860 861 On Windows, this returns a name of the form ur'DOMAIN\User Name'. 862 On Windows, a group can own a file or directory. 863 """ 864 if os.name == 'nt': 865 if win32security is None: 866 raise Exception("path.owner requires win32all to be installed") 867 desc = win32security.GetFileSecurity( 868 self, win32security.OWNER_SECURITY_INFORMATION) 869 sid = desc.GetSecurityDescriptorOwner() 870 account, domain, typecode = win32security.LookupAccountSid(None, sid) 871 return domain + u'\\' + account 872 else: 873 if pwd is None: 874 raise NotImplementedError("path.owner is not implemented on this platform.") 875 st = self.stat() 876 return pwd.getpwuid(st.st_uid).pw_name
877 878 owner = property( 879 get_owner, None, None, 880 """ Name of the owner of this file or directory. """) 881 882 if hasattr(os, 'statvfs'):
883 - def statvfs(self):
884 """ Perform a statvfs() system call on this path. """ 885 return os.statvfs(self)
886 887 if hasattr(os, 'pathconf'):
888 - def pathconf(self, name):
889 return os.pathconf(self, name)
890 891 892 # --- Modifying operations on files and directories 893
894 - def utime(self, times):
895 """ Set the access and modified times of this file. """ 896 os.utime(self, times)
897
898 - def chmod(self, mode):
899 os.chmod(self, mode)
900 901 if hasattr(os, 'chown'):
902 - def chown(self, uid, gid):
903 os.chown(self, uid, gid)
904
905 - def rename(self, new):
906 os.rename(self, new)
907
908 - def renames(self, new):
909 os.renames(self, new)
910 911 912 # --- Create/delete operations on directories 913
914 - def mkdir(self, mode=0777):
915 os.mkdir(self, mode)
916
917 - def makedirs(self, mode=0777):
918 os.makedirs(self, mode)
919
920 - def rmdir(self):
921 os.rmdir(self)
922
923 - def removedirs(self):
924 os.removedirs(self)
925 926 927 # --- Modifying operations on files 928
929 - def touch(self):
930 """ Set the access/modified times of this file to the current time. 931 Create the file if it does not exist. 932 """ 933 fd = os.open(self, os.O_WRONLY | os.O_CREAT, 0666) 934 os.close(fd) 935 os.utime(self, None)
936
937 - def remove(self):
938 os.remove(self)
939 942 943 944 # --- Links 945 946 if hasattr(os, 'link'): 950 951 if hasattr(os, 'symlink'): 955 956 if hasattr(os, 'readlink'): 963
964 - def readlinkabs(self):
965 """ Return the path to which this symbolic link points. 966 967 The result is always an absolute path. 968 """ 969 p = self.readlink() 970 if p.isabs(): 971 return p 972 else: 973 return (self.parent / p).abspath()
974 975 976 # --- High-level functions from shutil 977 978 copyfile = shutil.copyfile 979 copymode = shutil.copymode 980 copystat = shutil.copystat 981 copy = shutil.copy 982 copy2 = shutil.copy2 983 copytree = shutil.copytree 984 if hasattr(shutil, 'move'): 985 move = shutil.move 986 rmtree = shutil.rmtree 987 988 989 # --- Special stuff from os 990 991 if hasattr(os, 'chroot'):
992 - def chroot(self):
993 os.chroot(self)
994 995 if hasattr(os, 'startfile'):
996 - def startfile(self):
997 os.startfile(self)
998