From: david-sarah <david-sarah@jacaranda.org> Date: Wed, 21 Jul 2010 23:15:07 +0000 (-0700) Subject: util.fileutil, test.test_util: add abspath_expanduser_unicode function, to work aroun... X-Git-Tag: allmydata-tahoe-1.8.0b2~71 X-Git-Url: https://git.rkrishnan.org/%5B/%5D%20/uri/%22doc.html/install.html?a=commitdiff_plain;h=11b18824c7ff3237f4ed0122bcb24fe10b076be0;p=tahoe-lafs%2Ftahoe-lafs.git util.fileutil, test.test_util: add abspath_expanduser_unicode function, to work around <http://bugs.python.org/issue3426>. util.encodingutil: add a convenience function argv_to_abspath. --- diff --git a/src/allmydata/test/test_util.py b/src/allmydata/test/test_util.py index 0a326b36..6ba9ff66 100644 --- a/src/allmydata/test/test_util.py +++ b/src/allmydata/test/test_util.py @@ -1,7 +1,7 @@ def foo(): pass # keep the line number constant -import os, time +import os, time, sys from StringIO import StringIO from twisted.trial import unittest from twisted.internet import defer, reactor @@ -470,6 +470,37 @@ class FileUtil(unittest.TestCase): used = fileutil.du(basedir) self.failUnlessEqual(10+11+12+13, used) + def test_abspath_expanduser_unicode(self): + self.failUnlessRaises(AssertionError, fileutil.abspath_expanduser_unicode, "bytestring") + + saved_cwd = os.path.normpath(os.getcwdu()) + abspath_cwd = fileutil.abspath_expanduser_unicode(u".") + self.failUnless(isinstance(saved_cwd, unicode), saved_cwd) + self.failUnless(isinstance(abspath_cwd, unicode), abspath_cwd) + self.failUnlessEqual(abspath_cwd, saved_cwd) + + # adapted from <http://svn.python.org/view/python/branches/release26-maint/Lib/test/test_posixpath.py?view=markup&pathrev=78279#test_abspath> + + self.failUnlessIn(u"foo", fileutil.abspath_expanduser_unicode(u"foo")) + self.failIfIn(u"~", fileutil.abspath_expanduser_unicode(u"~")) + + cwds = ['cwd'] + try: + cwds.append(u'\xe7w\xf0'.encode(sys.getfilesystemencoding() + or 'ascii')) + except UnicodeEncodeError: + pass # the cwd can't be encoded -- test with ascii cwd only + + for cwd in cwds: + try: + os.mkdir(cwd) + os.chdir(cwd) + for upath in (u'', u'fuu', u'f\xf9\xf9', u'/fuu', u'U:\\', u'~'): + uabspath = fileutil.abspath_expanduser_unicode(upath) + self.failUnless(isinstance(uabspath, unicode), uabspath) + finally: + os.chdir(saved_cwd) + class PollMixinTests(unittest.TestCase): def setUp(self): self.pm = pollmixin.PollMixin() diff --git a/src/allmydata/util/encodingutil.py b/src/allmydata/util/encodingutil.py index e5787851..d2a65852 100644 --- a/src/allmydata/util/encodingutil.py +++ b/src/allmydata/util/encodingutil.py @@ -10,6 +10,7 @@ from allmydata.util.assertutil import precondition from twisted.python import usage import locale from allmydata.util import log +from allmydata.util.fileutil import abspath_expanduser_unicode def _canonical_encoding(encoding): @@ -91,6 +92,13 @@ def argv_to_unicode(s): raise usage.UsageError("Argument %s cannot be decoded as %s." % (quote_output(s), argv_encoding)) +def argv_to_abspath(s): + """ + Convenience function to decode an argv element to an absolute path, with ~ expanded. + If this fails, raise a UsageError. + """ + return abspath_expanduser_unicode(argv_to_unicode(s)) + def unicode_to_url(s): """ Encode an unicode object used in an URL. diff --git a/src/allmydata/util/fileutil.py b/src/allmydata/util/fileutil.py index cf0cb66a..a6b59bc8 100644 --- a/src/allmydata/util/fileutil.py +++ b/src/allmydata/util/fileutil.py @@ -272,3 +272,35 @@ def put_file(pathname, inf): outf.write(data) finally: outf.close() + + +# Work around <http://bugs.python.org/issue3426>. This code is adapted from +# <http://svn.python.org/view/python/trunk/Lib/ntpath.py?revision=78247&view=markup> +# with some simplifications. + +_getfullpathname = None +try: + from nt import _getfullpathname +except ImportError: + pass + +def abspath_expanduser_unicode(path): + """Return the absolute version of a path.""" + assert isinstance(path, unicode), path + + path = os.path.expanduser(path) + + if _getfullpathname: + # On Windows, os.path.isabs will return True for paths without a drive letter, + # e.g. "\\". See <http://bugs.python.org/issue1669539>. + try: + path = _getfullpathname(path or u".") + except WindowsError: + pass + + if not os.path.isabs(path): + path = os.path.join(os.getcwdu(), path) + + # We won't hit <http://bugs.python.org/issue5827> because + # there is always at least one Unicode path component. + return os.path.normpath(path)