From 6aea8d06b637ea55a2fa7d2949863adae5310ce2 Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Sat, 11 Aug 2018 02:54:27 +0200 Subject: Don't pass encoding= to Popen() Popen()'s 'encoding' parameter is Python 3.6+ only. Unfortunately, Popen()'s universal_newlines=True without 'encoding' will use the encoding from the environment. Do a manual version instead, so that we can still use the user-specified encoding (usually UTF-8). That might prevent problems on systems that are (poorly) configured to use the C locale. --- kconfiglib.py | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) (limited to 'kconfiglib.py') diff --git a/kconfiglib.py b/kconfiglib.py index f9c1a46..0f98fa5 100644 --- a/kconfiglib.py +++ b/kconfiglib.py @@ -5689,35 +5689,31 @@ def _error_if_fn(kconf, args): return "" def _shell_fn(kconf, args): - # Use universal newlines mode to prevent e.g. stray \r's in command output - # on Windows + stdout, stderr = subprocess.Popen( + args[1], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE + ).communicate() - if _IS_PY2: - # No decoding on Python 2 - stdout, stderr = subprocess.Popen( - args[1], shell=True, - stdout=subprocess.PIPE, stderr=subprocess.PIPE, - universal_newlines=True - ).communicate() - - else: - # Passing universal_newlines=True and/or 'encoding' on Python 3 turns - # on decoding of the output (bytes -> str), which might fail + if not _IS_PY2: try: - stdout, stderr = subprocess.Popen( - args[1], shell=True, - stdout=subprocess.PIPE, stderr=subprocess.PIPE, - universal_newlines=True, encoding=kconf._encoding - ).communicate() + stdout = stdout.decode(kconf._encoding) + stderr = stderr.decode(kconf._encoding) except UnicodeDecodeError as e: _decoding_error(e, kconf._filename, kconf._linenr) if stderr: - kconf._warn( - "'{}' wrote to stderr: {}".format(args[1], stderr.rstrip("\n")), - kconf._filename, kconf._linenr) + kconf._warn("'{}' wrote to stderr: {}".format( + args[1], "\n".join(stderr.splitlines())), + kconf._filename, kconf._linenr) + + # Manual universal newlines with splitlines() (to prevent e.g. stray \r's + # in command output on Windows), trailing newline removal, and + # newline-to-space conversion. + # + # On Python 3 versions before 3.6, it's not possible to specify the + # encoding when passing universal_newlines=True to Popen() (the 'encoding' + # parameter was added in 3.6), so we do this manual version instead. + return "\n".join(stdout.splitlines()).rstrip("\n").replace("\n", " ") - return stdout.rstrip("\n").replace("\n", " ") # # Public global constants -- cgit v1.2.3