Rev 6369: (gz) Add path_from_environ and clean ups to osutils and win32utils (Martin in file:///srv/pqm.bazaar-vcs.org/archives/thelove/bzr/%2Btrunk/
Patch Queue Manager
pqm at pqm.ubuntu.com
Wed Dec 14 19:31:25 UTC 2011
At file:///srv/pqm.bazaar-vcs.org/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 6369 [merge]
revision-id: pqm at pqm.ubuntu.com-20111214193125-xip8b3k8mplpq8ur
parent: pqm at pqm.ubuntu.com-20111214184202-r0x5y7oe5h6rz72w
parent: martin.packman at canonical.com-20111214182744-my73qn3nkrxspyel
committer: Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Wed 2011-12-14 19:31:25 +0000
message:
(gz) Add path_from_environ and clean ups to osutils and win32utils (Martin
Packman)
modified:
bzrlib/osutils.py osutils.py-20050309040759-eeaff12fbf77ac86
bzrlib/tests/test_lockdir.py test_lockdir.py-20060220222025-33d4221569a3d600
bzrlib/tests/test_osutils.py test_osutils.py-20051201224856-e48ee24c12182989
bzrlib/win32utils.py win32console.py-20051021033308-123c6c929d04973d
=== modified file 'bzrlib/osutils.py'
--- a/bzrlib/osutils.py 2011-12-13 17:10:47 +0000
+++ b/bzrlib/osutils.py 2011-12-14 19:31:25 +0000
@@ -320,6 +320,33 @@
return path
+def _posix_path_from_environ(key):
+ """Get unicode path from `key` in environment or None if not present
+
+ Note that posix systems use arbitrary byte strings for filesystem objects,
+ so a path that raises BadFilenameEncoding here may still be accessible.
+ """
+ val = os.environ.get(key, None)
+ if val is None:
+ return val
+ try:
+ return val.decode(_fs_enc)
+ except UnicodeDecodeError:
+ # GZ 2011-12-12:Ideally want to include `key` in the exception message
+ raise errors.BadFilenameEncoding(val, _fs_enc)
+
+
+def _posix_getuser_unicode():
+ """Get username from environment or password database as unicode"""
+ name = getpass.getuser()
+ user_encoding = get_user_encoding()
+ try:
+ return name.decode(user_encoding)
+ except UnicodeDecodeError:
+ raise errors.BzrError("Encoding of username %r is unsupported by %s "
+ "application locale." % (name, user_encoding))
+
+
def _win32_fixdrive(path):
"""Force drive letters to be consistent.
@@ -414,6 +441,8 @@
realpath = _posix_realpath
pathjoin = os.path.join
normpath = _posix_normpath
+path_from_environ = _posix_path_from_environ
+getuser_unicode = _posix_getuser_unicode
getcwd = os.getcwdu
rename = os.rename
dirname = os.path.dirname
@@ -475,6 +504,8 @@
f = win32utils.get_unicode_argv # special function or None
if f is not None:
get_unicode_argv = f
+ path_from_environ = win32utils.get_environ_unicode
+ getuser_unicode = win32utils.get_user_name
elif sys.platform == 'darwin':
getcwd = _mac_getcwd
@@ -2431,30 +2462,6 @@
open_file = open
-def getuser_unicode():
- """Return the username as unicode.
- """
- try:
- user_encoding = get_user_encoding()
- username = getpass.getuser().decode(user_encoding)
- except UnicodeDecodeError:
- raise errors.BzrError("Can't decode username as %s." % \
- user_encoding)
- except ImportError, e:
- if sys.platform != 'win32':
- raise
- if str(e) != 'No module named pwd':
- raise
- # https://bugs.launchpad.net/bzr/+bug/660174
- # getpass.getuser() is unable to return username on Windows
- # if there is no USERNAME environment variable set.
- # That could be true if bzr is running as a service,
- # e.g. running `bzr serve` as a service on Windows.
- # We should not fail with traceback in this case.
- username = u'UNKNOWN'
- return username
-
-
def available_backup_name(base, exists):
"""Find a non-existing backup file name.
=== modified file 'bzrlib/tests/test_lockdir.py'
--- a/bzrlib/tests/test_lockdir.py 2011-08-19 22:34:02 +0000
+++ b/bzrlib/tests/test_lockdir.py 2011-12-14 18:27:44 +0000
@@ -43,6 +43,7 @@
from bzrlib.tests import (
features,
TestCase,
+ TestCaseInTempDir,
TestCaseWithTransport,
)
@@ -654,7 +655,7 @@
self.assertEqual([], self._calls)
-class TestLockHeldInfo(TestCase):
+class TestLockHeldInfo(TestCaseInTempDir):
"""Can get information about the lock holder, and detect whether they're
still alive."""
=== modified file 'bzrlib/tests/test_osutils.py'
--- a/bzrlib/tests/test_osutils.py 2011-12-14 17:07:11 +0000
+++ b/bzrlib/tests/test_osutils.py 2011-12-14 19:31:25 +0000
@@ -2115,12 +2115,6 @@
self.overrideEnv('LOGNAME', u'jrandom\xb6'.encode(ue))
self.assertEqual(u'jrandom\xb6', osutils.getuser_unicode())
- def test_no_username_bug_660174(self):
- self.requireFeature(features.win32_feature)
- for name in ('LOGNAME', 'USER', 'LNAME', 'USERNAME'):
- self.overrideEnv(name, None)
- self.assertEqual(u'UNKNOWN', osutils.getuser_unicode())
-
class TestBackupNames(tests.TestCase):
=== modified file 'bzrlib/win32utils.py'
--- a/bzrlib/win32utils.py 2011-12-12 13:31:08 +0000
+++ b/bzrlib/win32utils.py 2011-12-14 18:27:44 +0000
@@ -20,11 +20,15 @@
"""
import glob
+import operator
import os
import struct
import sys
-from bzrlib import cmdline
+from bzrlib import (
+ cmdline,
+ symbol_versioning,
+ )
from bzrlib.i18n import gettext
# Windows version
@@ -63,9 +67,12 @@
else:
if winver == 'Windows 98':
create_buffer = ctypes.create_string_buffer
+ def extract_buffer(buf):
+ return buf.value.decode("mbcs")
suffix = 'A'
else:
create_buffer = ctypes.create_unicode_buffer
+ extract_buffer = operator.attrgetter("value")
suffix = 'W'
try:
import pywintypes
@@ -248,28 +255,12 @@
one that moves with the user as they logon to different machines, and
a 'local' one that stays local to the machine. This returns the 'roaming'
directory, and thus is suitable for storing user-preferences, etc.
-
- Returned value can be unicode or plain string.
- To convert plain string to unicode use
- s.decode(osutils.get_user_encoding())
- (XXX - but see bug 262874, which asserts the correct encoding is 'mbcs')
"""
appdata = _get_sh_special_folder_path(CSIDL_APPDATA)
if appdata:
return appdata
- # from env variable
- appdata = os.environ.get('APPDATA')
- if appdata:
- return appdata
- # if we fall to this point we on win98
- # at least try C:/WINDOWS/Application Data
- windir = os.environ.get('windir')
- if windir:
- appdata = os.path.join(windir, 'Application Data')
- if os.path.isdir(appdata):
- return appdata
- # did not find anything
- return None
+ # Use APPDATA if defined, will return None if not
+ return get_environ_unicode('APPDATA')
def get_local_appdata_location():
@@ -281,17 +272,12 @@
a 'local' one that stays local to the machine. This returns the 'local'
directory, and thus is suitable for caches, temp files and other things
which don't need to move with the user.
-
- Returned value can be unicode or plain string.
- To convert plain string to unicode use
- s.decode(osutils.get_user_encoding())
- (XXX - but see bug 262874, which asserts the correct encoding is 'mbcs')
"""
local = _get_sh_special_folder_path(CSIDL_LOCAL_APPDATA)
if local:
return local
# Vista supplies LOCALAPPDATA, but XP and earlier do not.
- local = os.environ.get('LOCALAPPDATA')
+ local = get_environ_unicode('LOCALAPPDATA')
if local:
return local
return get_appdata_location()
@@ -302,33 +288,27 @@
Assume on win32 it's the <My Documents> folder.
If location cannot be obtained return system drive root,
i.e. C:\
-
- Returned value can be unicode or plain string.
- To convert plain string to unicode use
- s.decode(osutils.get_user_encoding())
"""
home = _get_sh_special_folder_path(CSIDL_PERSONAL)
if home:
return home
- # try for HOME env variable
- home = os.path.expanduser('~')
- if home != '~':
+ home = get_environ_unicode('HOME')
+ if home is not None:
return home
+ homepath = get_environ_unicode('HOMEPATH')
+ if homepath is not None:
+ return os.path.join(get_environ_unicode('HOMEDIR', ''), home)
# at least return windows root directory
- windir = os.environ.get('windir')
+ windir = get_environ_unicode('WINDIR')
if windir:
return os.path.splitdrive(windir)[0] + '/'
# otherwise C:\ is good enough for 98% users
- return 'C:/'
+ return unicode('C:/')
def get_user_name():
"""Return user name as login name.
If name cannot be obtained return None.
-
- Returned value can be unicode or plain string.
- To convert plain string to unicode use
- s.decode(osutils.get_user_encoding())
"""
if has_ctypes:
try:
@@ -340,9 +320,9 @@
buf = create_buffer(UNLEN+1)
n = ctypes.c_int(UNLEN+1)
if GetUserName(buf, ctypes.byref(n)):
- return buf.value
+ return extract_buffer(buf)
# otherwise try env variables
- return os.environ.get('USERNAME', None)
+ return get_environ_unicode('USERNAME')
# 1 == ComputerNameDnsHostname, which returns "The DNS host name of the local
@@ -353,8 +333,7 @@
"""Return host machine name.
If name cannot be obtained return None.
- :return: A unicode string representing the host name. On win98, this may be
- a plain string as win32 api doesn't support unicode.
+ :return: A unicode string representing the host name.
"""
if has_win32api:
try:
@@ -377,7 +356,7 @@
if (GetComputerNameEx is not None
and GetComputerNameEx(_WIN32_ComputerNameDnsHostname,
buf, ctypes.byref(n))):
- return buf.value
+ return extract_buffer(buf)
# Try GetComputerName in case GetComputerNameEx wasn't found
# It returns the NETBIOS name, which isn't as good, but still ok.
@@ -387,18 +366,12 @@
None)
if (GetComputerName is not None
and GetComputerName(buf, ctypes.byref(n))):
- return buf.value
- # otherwise try env variables, which will be 'mbcs' encoded
- # on Windows (Python doesn't expose the native win32 unicode environment)
- # According to this:
- # http://msdn.microsoft.com/en-us/library/aa246807.aspx
- # environment variables should always be encoded in 'mbcs'.
- try:
- return os.environ['COMPUTERNAME'].decode("mbcs")
- except KeyError:
- return None
-
-
+ return extract_buffer(buf)
+ return get_environ_unicode('COMPUTERNAME')
+
+
+ at symbol_versioning.deprecated_method(
+ symbol_versioning.deprecated_in((2, 5, 0)))
def _ensure_unicode(s):
if s and type(s) != unicode:
from bzrlib import osutils
@@ -406,17 +379,17 @@
return s
-def get_appdata_location_unicode():
- return _ensure_unicode(get_appdata_location())
-
-def get_home_location_unicode():
- return _ensure_unicode(get_home_location())
-
-def get_user_name_unicode():
- return _ensure_unicode(get_user_name())
-
-def get_host_name_unicode():
- return _ensure_unicode(get_host_name())
+get_appdata_location_unicode = symbol_versioning.deprecated_method(
+ symbol_versioning.deprecated_in((2, 5, 0)))(get_appdata_location)
+
+get_home_location_unicode = symbol_versioning.deprecated_method(
+ symbol_versioning.deprecated_in((2, 5, 0)))(get_home_location)
+
+get_user_name_unicode = symbol_versioning.deprecated_method(
+ symbol_versioning.deprecated_in((2, 5, 0)))(get_user_name)
+
+get_host_name_unicode = symbol_versioning.deprecated_method(
+ symbol_versioning.deprecated_in((2, 5, 0)))(get_host_name)
def _ensure_with_dir(path):
@@ -433,7 +406,6 @@
return path
-
def glob_one(possible_glob):
"""Same as glob.glob().
@@ -585,6 +557,11 @@
def get_environ_unicode(key, default=None):
"""Get `key` from environment as unicode or `default` if unset
+ The environment is natively unicode on modern windows versions but
+ Python 2 only accesses it through the legacy bytestring api.
+
+ Environmental variable names are case insenstive on Windows.
+
A large enough buffer will be allocated to retrieve the value, though
it may take two calls to the underlying library function.
@@ -609,7 +586,16 @@
return buffer[:length]
buffer_size = length
else:
- get_unicode_argv = get_environ_unicode = None
+ get_unicode_argv = None
+ def get_environ_unicode(key, default=None):
+ """Get `key` from environment as unicode or `default` if unset
+
+ Fallback version that should basically never be needed.
+ """
+ try:
+ return os.environ[key].decode("mbcs")
+ except KeyError:
+ return default
if has_win32api:
More information about the bazaar-commits
mailing list