Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decode popen output using the system locale if UTF-8 decoding fails. #380

Merged
merged 11 commits into from
Feb 11, 2021
33 changes: 32 additions & 1 deletion nox/popen.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,42 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import locale
import subprocess
import sys
from typing import IO, Mapping, Sequence, Tuple, Union


def decode_output(output: bytes) -> str:
"""Try to decode the given bytes with encodings from the system.

:param output: output to decode
:raises UnicodeDecodeError: if all encodings fail
:return: decoded string
"""
decoded_output = ""
encodings = {
"utf8",
sys.stdout.encoding or "utf8",
sys.getdefaultencoding() or "utf8",
locale.getpreferredencoding() or "utf8",
}

for idx, encoding in enumerate(encodings):
try:
print(encoding)
decoded_output = output.decode(encoding)
except UnicodeDecodeError as exc:
if idx + 1 < len(encodings):
continue
exc.encoding = str(encodings).replace("'", "")
raise
else:
break

return decoded_output


def popen(
args: Sequence[str],
env: Mapping[str, str] = None,
Expand Down Expand Up @@ -45,4 +76,4 @@ def popen(

return_code = proc.wait()

return return_code, out.decode("utf-8") if out else ""
return return_code, decode_output(out) if out else ""