1 """ path.py - An object representing a path to a file or directory.
\r
5 from path import path
\r
6 d = path('/home/guido/bin')
\r
7 for f in d.files('*.py'):
\r
10 This module requires Python 2.2 or later.
\r
13 URL: http://www.jorendorff.com/articles/python/path
\r
14 Author: Jason Orendorff <jason.orendorff\x40gmail\x2ecom> (and others - see the url!)
\r
20 # - Tree-walking functions don't avoid symlink loops. Matt Harrison
\r
21 # sent me a patch for this.
\r
22 # - Bug in write_text(). It doesn't support Universal newline mode.
\r
23 # - Better error message in listdir() when self isn't a
\r
24 # directory. (On Windows, the error message really sucks.)
\r
25 # - Make sure everything has a good docstring.
\r
26 # - Add methods for regex find and replace.
\r
27 # - guess_content_type() method?
\r
28 # - Perhaps support arguments to touch().
\r
30 from __future__ import generators
\r
32 import sys, warnings, os, fnmatch, glob, shutil, codecs, md5
\r
37 # Platform-specific support for path.owner
\r
40 import win32security
\r
42 win32security = None
\r
49 # Pre-2.3 support. Are unicode filenames supported?
\r
53 if os.path.supports_unicode_filenames:
\r
55 _getcwd = os.getcwdu
\r
56 except AttributeError:
\r
59 # Pre-2.3 workaround for booleans
\r
65 # Pre-2.3 workaround for basestring.
\r
69 basestring = (str, unicode)
\r
71 # Universal newline support
\r
73 if hasattr(file, 'newlines'):
\r
77 class TreeWalkWarning(Warning):
\r
81 """ Represents a filesystem path.
\r
83 For documentation on individual methods, consult their
\r
84 counterparts in os.path.
\r
87 # --- Special Python methods.
\r
90 return 'path(%s)' % _base.__repr__(self)
\r
92 # Adding a path and a string yields a path.
\r
93 def __add__(self, more):
\r
95 resultStr = _base.__add__(self, more)
\r
96 except TypeError: #Python bug
\r
97 resultStr = NotImplemented
\r
98 if resultStr is NotImplemented:
\r
100 return self.__class__(resultStr)
\r
102 def __radd__(self, other):
\r
103 if isinstance(other, basestring):
\r
104 return self.__class__(other.__add__(self))
\r
106 return NotImplemented
\r
108 # The / operator joins paths.
\r
109 def __div__(self, rel):
\r
110 """ fp.__div__(rel) == fp / rel == fp.joinpath(rel)
\r
112 Join two path components, adding a separator character if
\r
115 return self.__class__(os.path.join(self, rel))
\r
117 # Make the / operator work even when true division is enabled.
\r
118 __truediv__ = __div__
\r
121 """ Return the current working directory as a path object. """
\r
122 return cls(_getcwd())
\r
123 getcwd = classmethod(getcwd)
\r
126 # --- Operations on path strings.
\r
128 isabs = os.path.isabs
\r
129 def abspath(self): return self.__class__(os.path.abspath(self))
\r
130 def normcase(self): return self.__class__(os.path.normcase(self))
\r
131 def normpath(self): return self.__class__(os.path.normpath(self))
\r
132 def realpath(self): return self.__class__(os.path.realpath(self))
\r
133 def expanduser(self): return self.__class__(os.path.expanduser(self))
\r
134 def expandvars(self): return self.__class__(os.path.expandvars(self))
\r
135 def dirname(self): return self.__class__(os.path.dirname(self))
\r
136 basename = os.path.basename
\r
139 """ Clean up a filename by calling expandvars(),
\r
140 expanduser(), and normpath() on it.
\r
142 This is commonly everything needed to clean up a filename
\r
143 read from a configuration file, for example.
\r
145 return self.expandvars().expanduser().normpath()
\r
147 def _get_namebase(self):
\r
148 base, ext = os.path.splitext(self.name)
\r
151 def _get_ext(self):
\r
152 f, ext = os.path.splitext(_base(self))
\r
155 def _get_drive(self):
\r
156 drive, r = os.path.splitdrive(self)
\r
157 return self.__class__(drive)
\r
160 dirname, None, None,
\r
161 """ This path's parent directory, as a new path object.
\r
163 For example, path('/usr/local/lib/libpython.so').parent == path('/usr/local/lib')
\r
167 basename, None, None,
\r
168 """ The name of this file or directory without the full path.
\r
170 For example, path('/usr/local/lib/libpython.so').name == 'libpython.so'
\r
173 namebase = property(
\r
174 _get_namebase, None, None,
\r
175 """ The same as path.name, but with one file extension stripped off.
\r
177 For example, path('/home/guido/python.tar.gz').name == 'python.tar.gz',
\r
178 but path('/home/guido/python.tar.gz').namebase == 'python.tar'
\r
182 _get_ext, None, None,
\r
183 """ The file extension, for example '.py'. """)
\r
186 _get_drive, None, None,
\r
187 """ The drive specifier, for example 'C:'.
\r
188 This is always empty on systems that don't use drive specifiers.
\r
191 def splitpath(self):
\r
192 """ p.splitpath() -> Return (p.parent, p.name). """
\r
193 parent, child = os.path.split(self)
\r
194 return self.__class__(parent), child
\r
196 def splitdrive(self):
\r
197 """ p.splitdrive() -> Return (p.drive, <the rest of p>).
\r
199 Split the drive specifier from this path. If there is
\r
200 no drive specifier, p.drive is empty, so the return value
\r
201 is simply (path(''), p). This is always the case on Unix.
\r
203 drive, rel = os.path.splitdrive(self)
\r
204 return self.__class__(drive), rel
\r
206 def splitext(self):
\r
207 """ p.splitext() -> Return (p.stripext(), p.ext).
\r
209 Split the filename extension from this path and return
\r
210 the two parts. Either part may be empty.
\r
212 The extension is everything from '.' to the end of the
\r
213 last path segment. This has the property that if
\r
214 (a, b) == p.splitext(), then a + b == p.
\r
216 filename, ext = os.path.splitext(self)
\r
217 return self.__class__(filename), ext
\r
219 def stripext(self):
\r
220 """ p.stripext() -> Remove one file extension from the path.
\r
222 For example, path('/home/guido/python.tar.gz').stripext()
\r
223 returns path('/home/guido/python.tar').
\r
225 return self.splitext()[0]
\r
227 if hasattr(os.path, 'splitunc'):
\r
228 def splitunc(self):
\r
229 unc, rest = os.path.splitunc(self)
\r
230 return self.__class__(unc), rest
\r
232 def _get_uncshare(self):
\r
233 unc, r = os.path.splitunc(self)
\r
234 return self.__class__(unc)
\r
236 uncshare = property(
\r
237 _get_uncshare, None, None,
\r
238 """ The UNC mount point for this path.
\r
239 This is empty for paths on local drives. """)
\r
241 def joinpath(self, *args):
\r
242 """ Join two or more path components, adding a separator
\r
243 character (os.sep) if needed. Returns a new path
\r
246 return self.__class__(os.path.join(self, *args))
\r
248 def splitall(self):
\r
249 r""" Return a list of the path components in this path.
\r
251 The first item in the list will be a path. Its value will be
\r
252 either os.curdir, os.pardir, empty, or the root directory of
\r
253 this path (for example, '/' or 'C:\\'). The other items in
\r
254 the list will be strings.
\r
256 path.path.joinpath(*result) will yield the original path.
\r
260 while loc != os.curdir and loc != os.pardir:
\r
262 loc, child = prev.splitpath()
\r
265 parts.append(child)
\r
271 """ Return this path as a relative path,
\r
272 based from the current working directory.
\r
274 cwd = self.__class__(os.getcwd())
\r
275 return cwd.relpathto(self)
\r
277 def relpathto(self, dest):
\r
278 """ Return a relative path from self to dest.
\r
280 If there is no relative path from self to dest, for example if
\r
281 they reside on different drives in Windows, then this returns
\r
284 origin = self.abspath()
\r
285 dest = self.__class__(dest).abspath()
\r
287 orig_list = origin.normcase().splitall()
\r
288 # Don't normcase dest! We want to preserve the case.
\r
289 dest_list = dest.splitall()
\r
291 if orig_list[0] != os.path.normcase(dest_list[0]):
\r
292 # Can't get here from there.
\r
295 # Find the location where the two paths start to differ.
\r
297 for start_seg, dest_seg in zip(orig_list, dest_list):
\r
298 if start_seg != os.path.normcase(dest_seg):
\r
302 # Now i is the point where the two paths diverge.
\r
303 # Need a certain number of "os.pardir"s to work up
\r
304 # from the origin to the point of divergence.
\r
305 segments = [os.pardir] * (len(orig_list) - i)
\r
306 # Need to add the diverging part of dest_list.
\r
307 segments += dest_list[i:]
\r
308 if len(segments) == 0:
\r
309 # If they happen to be identical, use os.curdir.
\r
310 relpath = os.curdir
\r
312 relpath = os.path.join(*segments)
\r
313 return self.__class__(relpath)
\r
315 # --- Listing, searching, walking, and matching
\r
317 def listdir(self, pattern=None):
\r
318 """ D.listdir() -> List of items in this directory.
\r
320 Use D.files() or D.dirs() instead if you want a listing
\r
321 of just files or just subdirectories.
\r
323 The elements of the list are path objects.
\r
325 With the optional 'pattern' argument, this only lists
\r
326 items whose names match the given pattern.
\r
328 names = os.listdir(self)
\r
329 if pattern is not None:
\r
330 names = fnmatch.filter(names, pattern)
\r
331 return [self / child for child in names]
\r
333 def dirs(self, pattern=None):
\r
334 """ D.dirs() -> List of this directory's subdirectories.
\r
336 The elements of the list are path objects.
\r
337 This does not walk recursively into subdirectories
\r
338 (but see path.walkdirs).
\r
340 With the optional 'pattern' argument, this only lists
\r
341 directories whose names match the given pattern. For
\r
342 example, d.dirs('build-*').
\r
344 return [p for p in self.listdir(pattern) if p.isdir()]
\r
346 def files(self, pattern=None):
\r
347 """ D.files() -> List of the files in this directory.
\r
349 The elements of the list are path objects.
\r
350 This does not walk into subdirectories (see path.walkfiles).
\r
352 With the optional 'pattern' argument, this only lists files
\r
353 whose names match the given pattern. For example,
\r
357 return [p for p in self.listdir(pattern) if p.isfile()]
\r
359 def walk(self, pattern=None, errors='strict'):
\r
360 """ D.walk() -> iterator over files and subdirs, recursively.
\r
362 The iterator yields path objects naming each child item of
\r
363 this directory and its descendants. This requires that
\r
366 This performs a depth-first traversal of the directory tree.
\r
367 Each directory is returned just before all its children.
\r
369 The errors= keyword argument controls behavior when an
\r
370 error occurs. The default is 'strict', which causes an
\r
371 exception. The other allowed values are 'warn', which
\r
372 reports the error via warnings.warn(), and 'ignore'.
\r
374 if errors not in ('strict', 'warn', 'ignore'):
\r
375 raise ValueError("invalid errors parameter")
\r
378 childList = self.listdir()
\r
380 if errors == 'ignore':
\r
382 elif errors == 'warn':
\r
384 "Unable to list directory '%s': %s"
\r
385 % (self, sys.exc_info()[1]),
\r
391 for child in childList:
\r
392 if pattern is None or child.fnmatch(pattern):
\r
395 isdir = child.isdir()
\r
397 if errors == 'ignore':
\r
399 elif errors == 'warn':
\r
401 "Unable to access '%s': %s"
\r
402 % (child, sys.exc_info()[1]),
\r
409 for item in child.walk(pattern, errors):
\r
412 def walkdirs(self, pattern=None, errors='strict'):
\r
413 """ D.walkdirs() -> iterator over subdirs, recursively.
\r
415 With the optional 'pattern' argument, this yields only
\r
416 directories whose names match the given pattern. For
\r
417 example, mydir.walkdirs('*test') yields only directories
\r
418 with names ending in 'test'.
\r
420 The errors= keyword argument controls behavior when an
\r
421 error occurs. The default is 'strict', which causes an
\r
422 exception. The other allowed values are 'warn', which
\r
423 reports the error via warnings.warn(), and 'ignore'.
\r
425 if errors not in ('strict', 'warn', 'ignore'):
\r
426 raise ValueError("invalid errors parameter")
\r
431 if errors == 'ignore':
\r
433 elif errors == 'warn':
\r
435 "Unable to list directory '%s': %s"
\r
436 % (self, sys.exc_info()[1]),
\r
443 if pattern is None or child.fnmatch(pattern):
\r
445 for subsubdir in child.walkdirs(pattern, errors):
\r
448 def walkfiles(self, pattern=None, errors='strict'):
\r
449 """ D.walkfiles() -> iterator over files in D, recursively.
\r
451 The optional argument, pattern, limits the results to files
\r
452 with names that match the pattern. For example,
\r
453 mydir.walkfiles('*.tmp') yields only files with the .tmp
\r
456 if errors not in ('strict', 'warn', 'ignore'):
\r
457 raise ValueError("invalid errors parameter")
\r
460 childList = self.listdir()
\r
462 if errors == 'ignore':
\r
464 elif errors == 'warn':
\r
466 "Unable to list directory '%s': %s"
\r
467 % (self, sys.exc_info()[1]),
\r
473 for child in childList:
\r
475 isfile = child.isfile()
\r
476 isdir = not isfile and child.isdir()
\r
478 if errors == 'ignore':
\r
480 elif errors == 'warn':
\r
482 "Unable to access '%s': %s"
\r
483 % (self, sys.exc_info()[1]),
\r
490 if pattern is None or child.fnmatch(pattern):
\r
493 for f in child.walkfiles(pattern, errors):
\r
496 def fnmatch(self, pattern):
\r
497 """ Return True if self.name matches the given pattern.
\r
499 pattern - A filename pattern with wildcards,
\r
500 for example '*.py'.
\r
502 return fnmatch.fnmatch(self.name, pattern)
\r
504 def glob(self, pattern):
\r
505 """ Return a list of path objects that match the pattern.
\r
507 pattern - a path relative to this directory, with wildcards.
\r
509 For example, path('/users').glob('*/bin/*') returns a list
\r
510 of all the files users have in their bin directories.
\r
512 cls = self.__class__
\r
513 return [cls(s) for s in glob.glob(_base(self / pattern))]
\r
516 # --- Reading or writing an entire file at once.
\r
518 def open(self, mode='r'):
\r
519 """ Open this file. Return a file object. """
\r
520 return file(self, mode)
\r
523 """ Open this file, read all bytes, return them as a string. """
\r
524 f = self.open('rb')
\r
530 def write_bytes(self, bytes, append=False):
\r
531 """ Open this file and write the given bytes to it.
\r
533 Default behavior is to overwrite any existing file.
\r
534 Call p.write_bytes(bytes, append=True) to append instead.
\r
540 f = self.open(mode)
\r
546 def text(self, encoding=None, errors='strict'):
\r
547 r""" Open this file, read it in, return the content as a string.
\r
549 This uses 'U' mode in Python 2.3 and later, so '\r\n' and '\r'
\r
550 are automatically translated to '\n'.
\r
552 Optional arguments:
\r
554 encoding - The Unicode encoding (or character set) of
\r
555 the file. If present, the content of the file is
\r
556 decoded and returned as a unicode object; otherwise
\r
557 it is returned as an 8-bit str.
\r
558 errors - How to handle Unicode errors; see help(str.decode)
\r
559 for the options. Default is 'strict'.
\r
561 if encoding is None:
\r
563 f = self.open(_textmode)
\r
570 f = codecs.open(self, 'r', encoding, errors)
\r
571 # (Note - Can't use 'U' mode here, since codecs.open
\r
572 # doesn't support 'U' mode, even in Python 2.3.)
\r
577 return (t.replace(u'\r\n', u'\n')
\r
578 .replace(u'\r\x85', u'\n')
\r
579 .replace(u'\r', u'\n')
\r
580 .replace(u'\x85', u'\n')
\r
581 .replace(u'\u2028', u'\n'))
\r
583 def write_text(self, text, encoding=None, errors='strict', linesep=os.linesep, append=False):
\r
584 r""" Write the given text to this file.
\r
586 The default behavior is to overwrite any existing file;
\r
587 to append instead, use the 'append=True' keyword argument.
\r
589 There are two differences between path.write_text() and
\r
590 path.write_bytes(): newline handling and Unicode handling.
\r
595 - text - str/unicode - The text to be written.
\r
597 - encoding - str - The Unicode encoding that will be used.
\r
598 This is ignored if 'text' isn't a Unicode string.
\r
600 - errors - str - How to handle Unicode encoding errors.
\r
601 Default is 'strict'. See help(unicode.encode) for the
\r
602 options. This is ignored if 'text' isn't a Unicode
\r
605 - linesep - keyword argument - str/unicode - The sequence of
\r
606 characters to be used to mark end-of-line. The default is
\r
607 os.linesep. You can also specify None; this means to
\r
608 leave all newlines as they are in 'text'.
\r
610 - append - keyword argument - bool - Specifies what to do if
\r
611 the file already exists (True: append to the end of it;
\r
612 False: overwrite it.) The default is False.
\r
615 --- Newline handling.
\r
617 write_text() converts all standard end-of-line sequences
\r
618 ('\n', '\r', and '\r\n') to your platform's default end-of-line
\r
619 sequence (see os.linesep; on Windows, for example, the
\r
620 end-of-line marker is '\r\n').
\r
622 If you don't like your platform's default, you can override it
\r
623 using the 'linesep=' keyword argument. If you specifically want
\r
624 write_text() to preserve the newlines as-is, use 'linesep=None'.
\r
626 This applies to Unicode text the same as to 8-bit text, except
\r
627 there are three additional standard Unicode end-of-line sequences:
\r
628 u'\x85', u'\r\x85', and u'\u2028'.
\r
630 (This is slightly different from when you open a file for
\r
631 writing with fopen(filename, "w") in C or file(filename, 'w')
\r
637 If 'text' isn't Unicode, then apart from newline handling, the
\r
638 bytes are written verbatim to the file. The 'encoding' and
\r
639 'errors' arguments are not used and must be omitted.
\r
641 If 'text' is Unicode, it is first converted to bytes using the
\r
642 specified 'encoding' (or the default encoding if 'encoding'
\r
643 isn't specified). The 'errors' argument applies only to this
\r
647 if isinstance(text, unicode):
\r
648 if linesep is not None:
\r
649 # Convert all standard end-of-line sequences to
\r
650 # ordinary newline characters.
\r
651 text = (text.replace(u'\r\n', u'\n')
\r
652 .replace(u'\r\x85', u'\n')
\r
653 .replace(u'\r', u'\n')
\r
654 .replace(u'\x85', u'\n')
\r
655 .replace(u'\u2028', u'\n'))
\r
656 text = text.replace(u'\n', linesep)
\r
657 if encoding is None:
\r
658 encoding = sys.getdefaultencoding()
\r
659 bytes = text.encode(encoding, errors)
\r
661 # It is an error to specify an encoding if 'text' is
\r
663 assert encoding is None
\r
665 if linesep is not None:
\r
666 text = (text.replace('\r\n', '\n')
\r
667 .replace('\r', '\n'))
\r
668 bytes = text.replace('\n', linesep)
\r
670 self.write_bytes(bytes, append)
\r
672 def lines(self, encoding=None, errors='strict', retain=True):
\r
673 r""" Open this file, read all lines, return them in a list.
\r
675 Optional arguments:
\r
676 encoding - The Unicode encoding (or character set) of
\r
677 the file. The default is None, meaning the content
\r
678 of the file is read as 8-bit characters and returned
\r
679 as a list of (non-Unicode) str objects.
\r
680 errors - How to handle Unicode errors; see help(str.decode)
\r
681 for the options. Default is 'strict'
\r
682 retain - If true, retain newline characters; but all newline
\r
683 character combinations ('\r', '\n', '\r\n') are
\r
684 translated to '\n'. If false, newline characters are
\r
685 stripped off. Default is True.
\r
687 This uses 'U' mode in Python 2.3 and later.
\r
689 if encoding is None and retain:
\r
690 f = self.open(_textmode)
\r
692 return f.readlines()
\r
696 return self.text(encoding, errors).splitlines(retain)
\r
698 def write_lines(self, lines, encoding=None, errors='strict',
\r
699 linesep=os.linesep, append=False):
\r
700 r""" Write the given lines of text to this file.
\r
702 By default this overwrites any existing file at this path.
\r
704 This puts a platform-specific newline sequence on every line.
\r
705 See 'linesep' below.
\r
707 lines - A list of strings.
\r
709 encoding - A Unicode encoding to use. This applies only if
\r
710 'lines' contains any Unicode strings.
\r
712 errors - How to handle errors in Unicode encoding. This
\r
713 also applies only to Unicode strings.
\r
715 linesep - The desired line-ending. This line-ending is
\r
716 applied to every line. If a line already has any
\r
717 standard line ending ('\r', '\n', '\r\n', u'\x85',
\r
718 u'\r\x85', u'\u2028'), that will be stripped off and
\r
719 this will be used instead. The default is os.linesep,
\r
720 which is platform-dependent ('\r\n' on Windows, '\n' on
\r
721 Unix, etc.) Specify None to write the lines as-is,
\r
722 like file.writelines().
\r
724 Use the keyword argument append=True to append lines to the
\r
725 file. The default is to overwrite the file. Warning:
\r
726 When you use this with Unicode data, if the encoding of the
\r
727 existing data in the file is different from the encoding
\r
728 you specify with the encoding= parameter, the result is
\r
729 mixed-encoding data, which can really confuse someone trying
\r
730 to read the file later.
\r
736 f = self.open(mode)
\r
739 isUnicode = isinstance(line, unicode)
\r
740 if linesep is not None:
\r
741 # Strip off any existing line-end and add the
\r
742 # specified linesep string.
\r
744 if line[-2:] in (u'\r\n', u'\x0d\x85'):
\r
746 elif line[-1:] in (u'\r', u'\n',
\r
747 u'\x85', u'\u2028'):
\r
750 if line[-2:] == '\r\n':
\r
752 elif line[-1:] in ('\r', '\n'):
\r
756 if encoding is None:
\r
757 encoding = sys.getdefaultencoding()
\r
758 line = line.encode(encoding, errors)
\r
763 def read_md5(self):
\r
764 """ Calculate the md5 hash for this file.
\r
766 This reads through the entire file.
\r
768 f = self.open('rb')
\r
780 # --- Methods for querying the filesystem.
\r
782 exists = os.path.exists
\r
783 isdir = os.path.isdir
\r
784 isfile = os.path.isfile
\r
785 islink = os.path.islink
\r
786 ismount = os.path.ismount
\r
788 if hasattr(os.path, 'samefile'):
\r
789 samefile = os.path.samefile
\r
791 getatime = os.path.getatime
\r
793 getatime, None, None,
\r
794 """ Last access time of the file. """)
\r
796 getmtime = os.path.getmtime
\r
798 getmtime, None, None,
\r
799 """ Last-modified time of the file. """)
\r
801 if hasattr(os.path, 'getctime'):
\r
802 getctime = os.path.getctime
\r
804 getctime, None, None,
\r
805 """ Creation time of the file. """)
\r
807 getsize = os.path.getsize
\r
809 getsize, None, None,
\r
810 """ Size of the file, in bytes. """)
\r
812 if hasattr(os, 'access'):
\r
813 def access(self, mode):
\r
814 """ Return true if current user has access to this path.
\r
816 mode - One of the constants os.F_OK, os.R_OK, os.W_OK, os.X_OK
\r
818 return os.access(self, mode)
\r
821 """ Perform a stat() system call on this path. """
\r
822 return os.stat(self)
\r
825 """ Like path.stat(), but do not follow symbolic links. """
\r
826 return os.lstat(self)
\r
828 def get_owner(self):
\r
829 r""" Return the name of the owner of this file or directory.
\r
831 This follows symbolic links.
\r
833 On Windows, this returns a name of the form ur'DOMAIN\User Name'.
\r
834 On Windows, a group can own a file or directory.
\r
836 if os.name == 'nt':
\r
837 if win32security is None:
\r
838 raise Exception("path.owner requires win32all to be installed")
\r
839 desc = win32security.GetFileSecurity(
\r
840 self, win32security.OWNER_SECURITY_INFORMATION)
\r
841 sid = desc.GetSecurityDescriptorOwner()
\r
842 account, domain, typecode = win32security.LookupAccountSid(None, sid)
\r
843 return domain + u'\\' + account
\r
846 raise NotImplementedError("path.owner is not implemented on this platform.")
\r
848 return pwd.getpwuid(st.st_uid).pw_name
\r
851 get_owner, None, None,
\r
852 """ Name of the owner of this file or directory. """)
\r
854 if hasattr(os, 'statvfs'):
\r
856 """ Perform a statvfs() system call on this path. """
\r
857 return os.statvfs(self)
\r
859 if hasattr(os, 'pathconf'):
\r
860 def pathconf(self, name):
\r
861 return os.pathconf(self, name)
\r
864 # --- Modifying operations on files and directories
\r
866 def utime(self, times):
\r
867 """ Set the access and modified times of this file. """
\r
868 os.utime(self, times)
\r
870 def chmod(self, mode):
\r
871 os.chmod(self, mode)
\r
873 if hasattr(os, 'chown'):
\r
874 def chown(self, uid, gid):
\r
875 os.chown(self, uid, gid)
\r
877 def rename(self, new):
\r
878 os.rename(self, new)
\r
880 def renames(self, new):
\r
881 os.renames(self, new)
\r
884 # --- Create/delete operations on directories
\r
886 def mkdir(self, mode=0777):
\r
887 os.mkdir(self, mode)
\r
889 def makedirs(self, mode=0777):
\r
890 os.makedirs(self, mode)
\r
895 def removedirs(self):
\r
896 os.removedirs(self)
\r
899 # --- Modifying operations on files
\r
902 """ Set the access/modified times of this file to the current time.
\r
903 Create the file if it does not exist.
\r
905 fd = os.open(self, os.O_WRONLY | os.O_CREAT, 0666)
\r
907 os.utime(self, None)
\r
918 if hasattr(os, 'link'):
\r
919 def link(self, newpath):
\r
920 """ Create a hard link at 'newpath', pointing to this file. """
\r
921 os.link(self, newpath)
\r
923 if hasattr(os, 'symlink'):
\r
924 def symlink(self, newlink):
\r
925 """ Create a symbolic link at 'newlink', pointing here. """
\r
926 os.symlink(self, newlink)
\r
928 if hasattr(os, 'readlink'):
\r
929 def readlink(self):
\r
930 """ Return the path to which this symbolic link points.
\r
932 The result may be an absolute or a relative path.
\r
934 return self.__class__(os.readlink(self))
\r
936 def readlinkabs(self):
\r
937 """ Return the path to which this symbolic link points.
\r
939 The result is always an absolute path.
\r
941 p = self.readlink()
\r
945 return (self.parent / p).abspath()
\r
948 # --- High-level functions from shutil
\r
950 copyfile = shutil.copyfile
\r
951 copymode = shutil.copymode
\r
952 copystat = shutil.copystat
\r
954 copy2 = shutil.copy2
\r
955 copytree = shutil.copytree
\r
956 if hasattr(shutil, 'move'):
\r
958 rmtree = shutil.rmtree
\r
961 # --- Special stuff from os
\r
963 if hasattr(os, 'chroot'):
\r
967 if hasattr(os, 'startfile'):
\r
968 def startfile(self):
\r