##// END OF EJS Templates
Added license statement to path.py, updated ChangeLog
vivainio -
Show More

The requested changes are too big and content was truncated. Show full diff

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