Permalink
Browse files

Merge pull request #59 from pmcnr/master

Solve issue with Python 2.7.3 where 'os.path' functions on some platforms (e.g. 'isdir' on Windows) are implemented in C and don't get bound (fixes #53)
  • Loading branch information...
2 parents 20e36f8 + d885fb9 commit e16e035120415e12b7a30d2a9c16e319ca6ae541 @Almad Almad committed May 22, 2012
Showing with 91 additions and 39 deletions.
  1. +91 −39 paver/path.py
View
130 paver/path.py
@@ -1,9 +1,32 @@
+#
+# Copyright (c) 2010 Mikhail Gusarov
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+
""" path.py - An object representing a path to a file or directory.
-Authors:
+Original author:
Jason Orendorff <jason.orendorff\x40gmail\x2ecom>
+
+Contributors:
Mikhail Gusarov <dottedmag@dottedmag.net>
- Others - unfortunately attribution is lost
Example:
@@ -12,6 +35,7 @@
for f in d.files('*.py'):
f.chmod(0755)
+This module requires Python 2.3 or later.
This has been modified from the original to avoid dry run issues.
"""
@@ -33,7 +57,7 @@
import sys, warnings, os, fnmatch, glob, shutil, codecs, hashlib, errno
from paver.easy import dry
-__version__ = '2.2.2'
+__version__ = '2.2.2.990'
__all__ = ['path']
# Platform-specific support for path.owner
@@ -58,23 +82,16 @@
except AttributeError:
pass
-# Pre-2.3 workaround for booleans
-try:
- True, False
-except NameError:
- True, False = 1, 0
-
# Pre-2.3 workaround for basestring.
try:
basestring
except NameError:
basestring = (str, unicode)
# Universal newline support
-_textmode = 'r'
-if hasattr(file, 'newlines'):
- _textmode = 'U'
-
+_textmode = 'U'
+if hasattr(__builtins__, 'file') and not hasattr(file, 'newlines'):
+ _textmode = 'r'
class TreeWalkWarning(Warning):
pass
@@ -119,26 +136,29 @@ def __div__(self, rel):
# Make the / operator work even when true division is enabled.
__truediv__ = __div__
+ def __enter__(self):
+ self._old_dir = self.getcwd()
+ os.chdir(self)
+
+ def __exit__(self, *_):
+ os.chdir(self._old_dir)
+
def getcwd(cls):
""" Return the current working directory as a path object. """
return cls(_getcwd())
getcwd = classmethod(getcwd)
- def chdir(self):
- """Change current directory."""
- os.chdir(self)
# --- Operations on path strings.
- isabs = os.path.isabs
def abspath(self): return self.__class__(os.path.abspath(self))
def normcase(self): return self.__class__(os.path.normcase(self))
def normpath(self): return self.__class__(os.path.normpath(self))
def realpath(self): return self.__class__(os.path.realpath(self))
def expanduser(self): return self.__class__(os.path.expanduser(self))
def expandvars(self): return self.__class__(os.path.expandvars(self))
def dirname(self): return self.__class__(os.path.dirname(self))
- basename = os.path.basename
+ def basename(self): return self.__class__(os.path.basename(self))
def expand(self):
""" Clean up a filename by calling expandvars(),
@@ -359,7 +379,7 @@ def files(self, pattern=None):
whose names match the given pattern. For example::
d.files('*.pyc')
"""
-
+
return [p for p in self.listdir(pattern) if p.isfile()]
def walk(self, pattern=None, errors='strict'):
@@ -524,7 +544,7 @@ def glob(self, pattern):
# TODO: file writing should not occur during dry runs XXX
def open(self, mode='r'):
""" Open this file. Return a file object. """
- return file(self, mode)
+ return open(self, mode)
def bytes(self):
""" Open this file, read all bytes, return them as a string. """
@@ -635,7 +655,7 @@ def write_text(self, text, encoding=None, errors='strict', linesep=os.linesep, a
u'\x85', u'\r\x85', and u'\u2028'.
(This is slightly different from when you open a file for
- writing with fopen(filename, "w") in C or file(filename, 'w')
+ writing with fopen(filename, "w") in C or open(filename, 'w')
in Python.)
@@ -804,33 +824,37 @@ def read_hexhash(self, hash_name):
return self._hash(hash_name).hexdigest()
# --- Methods for querying the filesystem.
+ # N.B. On some platforms, the os.path functions may be implemented in C
+ # (e.g. isdir on Windows, Python 3.2.2), and compiled functions don't get
+ # bound. Playing it safe and wrapping them all in method calls.
- exists = os.path.exists
- isdir = os.path.isdir
- isfile = os.path.isfile
- islink = os.path.islink
- ismount = os.path.ismount
+ def isabs(self): return os.path.isabs(self)
+ def exists(self): return os.path.exists(self)
+ def isdir(self): return os.path.isdir(self)
+ def isfile(self): return os.path.isfile(self)
+ def islink(self): return os.path.islink(self)
+ def ismount(self): return os.path.ismount(self)
if hasattr(os.path, 'samefile'):
- samefile = os.path.samefile
+ def samefile(self): return os.path.samefile(self)
- getatime = os.path.getatime
+ def getatime(self): return os.path.getatime(self)
atime = property(
getatime, None, None,
""" Last access time of the file. """)
- getmtime = os.path.getmtime
+ def getmtime(self): return os.path.getmtime(self)
mtime = property(
getmtime, None, None,
""" Last-modified time of the file. """)
if hasattr(os.path, 'getctime'):
- getctime = os.path.getctime
+ def getctime(self): return os.path.getctime(self)
ctime = property(
getctime, None, None,
""" Creation time of the file. """)
- getsize = os.path.getsize
+ def getsize(self): return os.path.getsize(self)
size = property(
getsize, None, None,
""" Size of the file, in bytes. """)
@@ -933,11 +957,25 @@ def makedirs_p(self, mode=0777):
def rmdir(self):
if self.exists():
- dry("rmdir %s" % self, os.rmdir, self)
+ dry("rmdir %s" % (self), os.rmdir, self)
+
+ def rmdir_p(self):
+ try:
+ self.rmdir()
+ except OSError, e:
+ if e.errno != errno.ENOTEMPTY and e.errno != errno.EEXIST:
+ raise
def removedirs(self):
if self.exists():
- dry("removedirs %s" % self, os.removedirs, self)
+ dry("removedirs %s" % (self), os.removedirs, self)
+
+ def removedirs_p(self):
+ try:
+ self.removedirs()
+ except OSError, e:
+ if e.errno != errno.ENOTEMPTY and e.errno != errno.EEXIST:
+ raise
# --- Modifying operations on files
@@ -953,7 +991,7 @@ def do_touch():
def remove(self):
if self.exists():
- dry("remove %s" % self, os.remove, self)
+ dry("remove %s" % (self), os.remove, self)
def remove_p(self):
try:
@@ -970,15 +1008,16 @@ def unlink_p(self):
self.remove_p()
# --- Links
+
if hasattr(os, 'link'):
def link(self, newpath):
""" Create a hard link at 'newpath', pointing to this file. """
- dry("link %s" % self, os.link, self)
+ dry("link %s" % (self), os.link, self, newpath)
if hasattr(os, 'symlink'):
def symlink(self, newlink):
""" Create a symbolic link at 'newlink', pointing here. """
- dry("symlink %s" % self, os.symlink, self)
+ dry("symlink %s" % (self), os.symlink, self, newlink)
if hasattr(os, 'readlink'):
def readlink(self):
@@ -1001,21 +1040,34 @@ def readlinkabs(self):
# --- High-level functions from shutil
+
+ def copyfile(self, dst):
+ dry("copyfile %s %s" % (self, dst), shutil.copyfile, self, dst)
+
+ def copymode(self, dst):
+ dry("copymode %s %s" % (self, dst), shutil.copymode, self, dst)
+
+ def copystat(self, dst):
+ dry("copystat %s %s" % (self, dst), shutil.copystat, self, dst)
+
def copy(self, dst):
dry("copy %s %s" % (self, dst), shutil.copy, self, dst)
+ def copy2(self, dst):
+ dry("copy2 %s %s" % (self, dst), shutil.copy2, self, dst)
+
def copytree(self, dst, *args, **kw):
dry("copytree %s %s" % (self, dst), shutil.copytree,
- self, dst, *args, **kw)
+ self, dst, *args, **kw)
if hasattr(shutil, 'move'):
def move(self, dst):
dry("move %s %s" % (self, dst), shutil.move, self, dst)
-
+
def rmtree(self, *args, **kw):
if self.exists():
dry("rmtree %s %s %s" % (self, args, kw), shutil.rmtree,
- self, *args, **kw)
+ self, *args, **kw)
# --- Special stuff from os

0 comments on commit e16e035

Please sign in to comment.