diff --git a/CHANGELOG b/CHANGELOG index e3360318a..d3478b8af 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -48,6 +48,8 @@ Bug fixes / Maintenance - don't print empty lines when showing junitxml-filename - add optional boolean ignore_errors parameter to py.path.local.remove - fix terminal writing on win32/python2.4 +- py.process.cmdexec() now tries harder to return properly encoded unicode objects + on all python versions Changes between 1.3.0 and 1.3.1 ================================================== diff --git a/py/_process/cmdexec.py b/py/_process/cmdexec.py index 0f38822d5..43c71629c 100644 --- a/py/_process/cmdexec.py +++ b/py/_process/cmdexec.py @@ -8,18 +8,25 @@ import py from subprocess import Popen, PIPE def cmdexec(cmd): - """ return output of executing 'cmd' in a separate process. + """ return unicode output of executing 'cmd' in a separate process. raise cmdexec.ExecutionFailed exeception if the command failed. the exception will provide an 'err' attribute containing the error-output from the command. + if the subprocess module does not provide a proper encoding/unicode strings + sys.getdefaultencoding() will be used, if that does not exist, 'UTF-8'. """ process = subprocess.Popen(cmd, shell=True, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = process.communicate() - out = py.builtin._totext(out, sys.stdout.encoding) - err = py.builtin._totext(err, sys.stderr.encoding) + if sys.version_info[0] < 3: # on py3 we get unicode strings, on py2 not + try: + default_encoding = sys.getdefaultencoding() # jython may not have it + except AttributeError: + default_encoding = sys.stdout.encoding or 'UTF-8' + out = unicode(out, process.stdout.encoding or default_encoding) + err = unicode(err, process.stderr.encoding or default_encoding) status = process.poll() if status: raise ExecutionFailed(status, status, cmd, out, err) diff --git a/testing/process/test_cmdexec.py b/testing/process/test_cmdexec.py index 79629d886..b539e0af3 100644 --- a/testing/process/test_cmdexec.py +++ b/testing/process/test_cmdexec.py @@ -8,11 +8,13 @@ class Test_exec_cmd: def test_simple(self): out = cmdexec('echo hallo') assert out.strip() == 'hallo' + assert py.builtin._istext(out) def test_simple_newline(self): import sys out = cmdexec(r"""%s -c "print ('hello')" """ % sys.executable) assert out == 'hello\n' + assert py.builtin._istext(out) def test_simple_error(self): py.test.raises (cmdexec.Error, cmdexec, 'exit 1')