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.

This commit is contained in:
david-sarah 2010-07-21 16:15:07 -07:00
parent 5377d99cf3
commit 11b18824c7
3 changed files with 72 additions and 1 deletions

View File

@ -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()

View File

@ -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.

View File

@ -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)