summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2015-08-30 04:29:11 -0700
committerGiampaolo Rodola <g.rodola@gmail.com>2015-08-30 04:29:11 -0700
commit5176c50dc4b67de5d760636a70444ed21c807dc4 (patch)
treea66b5f5693a6ed2bc760bc9eebbe359debdc7c6c
parentb9823dbb3071d902753e713b0c32d027e73a7946 (diff)
downloadpsutil-5176c50dc4b67de5d760636a70444ed21c807dc4.tar.gz
always return encoded strings instead of unicode
-rw-r--r--HISTORY.rst18
-rw-r--r--docs/index.rst13
-rw-r--r--psutil/_pswindows.py37
-rw-r--r--test/_windows.py26
4 files changed, 38 insertions, 56 deletions
diff --git a/HISTORY.rst b/HISTORY.rst
index 9e7188b4..f283932a 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -7,14 +7,16 @@ Bug tracker at https://github.com/giampaolo/psutil/issues
- #648: CI test integration for OSX. (patch by Jeff Tang)
- #663: net_if_addrs() now returns point-to-point addresses (for VPNs).
-- #655: [Windows] str/uniocde unification. Different methods returning a string
- now return unicode on both Python 2 and 3:
- - net_if_stats
- - net_io_counters
- - users
- - Process.username
- - Process.name
- - Process.cmdline
+- #655: [Windows] different issues regarding unicode handling were fixed. On
+ Python 2 all APIs returning a string will now return an encoded version of it
+ by using sys.getfilesystemencoding() codec. The APIs involved are:
+ - psutil.net_if_stats
+ - psutil.net_if_addrs
+ - psutil.net_io_counters
+ - psutil.users
+ - psutil.Process.username
+ - psutil.Process.name
+ - psutil.Process.cmdline
**Bug fixes**
diff --git a/docs/index.rst b/docs/index.rst
index f7dad748..4a2a5b94 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -681,26 +681,16 @@ Process class
The process name. The return value is cached after first call.
- *Changed in 3.2.0:* (Windows, Python 2) in case of non ASCII name the
- returned type is unicode instead of str.
-
.. method:: exe()
The process executable as an absolute path.
On some systems this may also be an empty string.
The return value is cached after first call.
- *Changed in 3.2.0:* (Windows, Python 2) in case of non ASCII path the
- returned type is unicode instead of str.
-
.. method:: cmdline()
The command line this process has been called with.
- *Changed in 3.2.0:* (Windows, Python 2) in case one or more parts of the
- cmdline contains non ASCII characters the returned type is a list of
- unicode strings.
-
.. method:: create_time()
The process creation time as a floating point number expressed in seconds
@@ -748,9 +738,6 @@ Process class
The process current working directory as an absolute path.
- *Changed in 3.2.0:* (Windows, Python 2) in case of non ASCII path the
- returned type is unicode instead of str.
-
.. method:: username()
The name of the user that owns the process. On UNIX this is calculated by
diff --git a/psutil/_pswindows.py b/psutil/_pswindows.py
index 3c86d994..3e20d3be 100644
--- a/psutil/_pswindows.py
+++ b/psutil/_pswindows.py
@@ -234,13 +234,15 @@ def users():
return retlist
-def py2_stringify(s):
- if PY3:
+def py2_strencode(s, encoding=sys.getfilesystemencoding()):
+ if PY3 or isinstance(s, str):
return s
else:
try:
- return str(s)
+ return s.encode(encoding)
except UnicodeEncodeError:
+ # Filesystem codec failed, return the plain unicode
+ # string (this should never happen).
return s
@@ -297,9 +299,9 @@ class Process(object):
try:
# Note: this will fail with AD for most PIDs owned
# by another user but it's faster.
- return py2_stringify(os.path.basename(self.exe()))
+ return py2_strencode(os.path.basename(self.exe()))
except AccessDenied:
- return py2_stringify(cext.proc_name(self.pid))
+ return py2_strencode(cext.proc_name(self.pid))
@wrap_exceptions
def exe(self):
@@ -311,7 +313,7 @@ class Process(object):
# see https://github.com/giampaolo/psutil/issues/528
if self.pid in (0, 4):
raise AccessDenied(self.pid, self._name)
- return py2_stringify(_convert_raw_path(cext.proc_exe(self.pid)))
+ return py2_strencode(_convert_raw_path(cext.proc_exe(self.pid)))
@wrap_exceptions
def cmdline(self):
@@ -319,16 +321,7 @@ class Process(object):
if PY3:
return ret
else:
- # On Python 2, if one or more bits of the cmdline is unicode
- # we return a list of unicode strings.
- new = []
- for x in ret:
- x = py2_stringify(x)
- if isinstance(x, unicode):
- return ret
- else:
- new.append(x)
- return new
+ return [py2_strencode(s) for s in ret]
def ppid(self):
try:
@@ -453,13 +446,13 @@ class Process(object):
# return a normalized pathname since the native C function appends
# "\\" at the and of the path
path = cext.proc_cwd(self.pid)
- return py2_stringify(os.path.normpath(path))
+ return py2_strencode(os.path.normpath(path))
@wrap_exceptions
def open_files(self):
if self.pid in (0, 4):
return []
- retlist = []
+ ret = set()
# Filenames come in in native format like:
# "\Device\HarddiskVolume1\Windows\systemew\file.txt"
# Convert the first part in the corresponding drive letter
@@ -467,10 +460,12 @@ class Process(object):
raw_file_names = cext.proc_open_files(self.pid)
for _file in raw_file_names:
_file = _convert_raw_path(_file)
- if isfile_strict(_file) and _file not in retlist:
+ if isfile_strict(_file):
+ if not PY3:
+ _file = py2_strencode(_file)
ntuple = _common.popenfile(_file, -1)
- retlist.append(ntuple)
- return retlist
+ ret.add(ntuple)
+ return list(ret)
@wrap_exceptions
def connections(self, kind='inet'):
diff --git a/test/_windows.py b/test/_windows.py
index 70101726..0d2b2e15 100644
--- a/test/_windows.py
+++ b/test/_windows.py
@@ -476,32 +476,30 @@ class TestUnicode(unittest.TestCase):
shutil.copyfile(sys.executable, self.uexe)
subp = get_test_subprocess(cmd=[self.uexe])
p = psutil.Process(subp.pid)
- self.assertIsInstance(p.name(), unicode)
- self.assertEqual(os.path.basename(p.name()), u("psutil-è.exe"))
+ self.assertIsInstance(p.name(), str)
+ self.assertEqual(os.path.basename(p.name()), "psutil-è.exe")
def test_proc_name(self):
+ from psutil._pswindows import py2_strencode
shutil.copyfile(sys.executable, self.uexe)
subp = get_test_subprocess(cmd=[self.uexe])
- self.assertIsInstance(psutil._psplatform.cext.proc_name(subp.pid),
- unicode)
- self.assertEqual(psutil._psplatform.cext.proc_name(subp.pid),
- u("psutil-è.exe"))
+ self.assertEqual(
+ py2_strencode(psutil._psplatform.cext.proc_name(subp.pid)),
+ "psutil-è.exe")
def test_proc_cmdline(self):
shutil.copyfile(sys.executable, self.uexe)
subp = get_test_subprocess(cmd=[self.uexe])
p = psutil.Process(subp.pid)
- self.assertIsInstance(u("").join(p.cmdline()), unicode)
- uexe = self.uexe if PY3 else \
- unicode(self.uexe, sys.getfilesystemencoding())
- self.assertEqual(p.cmdline(), [uexe])
+ self.assertIsInstance("".join(p.cmdline()), str)
+ self.assertEqual(p.cmdline(), [self.uexe])
def test_proc_cwd(self):
- tdir = tempfile.mkdtemp(prefix=u("psutil-è-"))
+ tdir = tempfile.mkdtemp(prefix="psutil-è-")
self.addCleanup(safe_rmdir, tdir)
with chdir(tdir):
p = psutil.Process()
- self.assertIsInstance(p.cwd(), unicode)
+ self.assertIsInstance(p.cwd(), str)
self.assertEqual(p.cwd(), tdir)
def test_proc_open_files(self):
@@ -510,8 +508,8 @@ class TestUnicode(unittest.TestCase):
with open(self.uexe, 'w'):
new = set(p.open_files())
path = (new - start).pop().path
- self.assertIsInstance(path, unicode)
- self.assertEqual(path, self.uexe)
+ self.assertIsInstance(path, str)
+ self.assertEqual(path.lower(), self.uexe.lower())
def main():