Files
pipenv/pipenv/_compat.py
T
Dan Ryan 222eb50b18 Fix buggy pep517 implementation
- Fix resolution for pre-40.6.0 setuptools releases by auto-detecting
  installed setuptools version before calculating default backend

Signed-off-by: Dan Ryan <dan@danryan.co>
2019-02-17 02:28:33 -05:00

155 lines
4.6 KiB
Python

# -*- coding=utf-8 -*-
"""A compatibility module for pipenv's backports and manipulations.
Exposes a standard API that enables compatibility across python versions,
operating systems, etc.
"""
import functools
import importlib
import io
import os
import sys
import warnings
import six
import vistir
from .vendor.vistir.compat import (
NamedTemporaryFile, Path, ResourceWarning, TemporaryDirectory
)
# Backport required for earlier versions of Python.
if sys.version_info < (3, 3):
from .vendor.backports.shutil_get_terminal_size import get_terminal_size
else:
from shutil import get_terminal_size
warnings.filterwarnings("ignore", category=ResourceWarning)
__all__ = [
"NamedTemporaryFile", "Path", "ResourceWarning", "TemporaryDirectory",
"get_terminal_size", "getpreferredencoding", "DEFAULT_ENCODING", "canonical_encoding_name",
"force_encoding", "UNICODE_TO_ASCII_TRANSLATION_MAP", "decode_output", "fix_utf8"
]
def getpreferredencoding():
import locale
# Borrowed from Invoke
# (see https://github.com/pyinvoke/invoke/blob/93af29d/invoke/runners.py#L881)
_encoding = locale.getpreferredencoding(False)
if six.PY2 and not sys.platform == "win32":
_default_encoding = locale.getdefaultlocale()[1]
if _default_encoding is not None:
_encoding = _default_encoding
return _encoding
DEFAULT_ENCODING = getpreferredencoding()
def canonical_encoding_name(name):
import codecs
try:
codec = codecs.lookup(name)
except LookupError:
return name
else:
return codec.name
# From https://github.com/CarlFK/veyepar/blob/5c5de47/dj/scripts/fixunicode.py
# MIT LIcensed, thanks Carl!
def force_encoding():
try:
stdout_isatty = sys.stdout.isatty
stderr_isatty = sys.stderr.isatty
except AttributeError:
return DEFAULT_ENCODING, DEFAULT_ENCODING
else:
if not (stdout_isatty() and stderr_isatty()):
return DEFAULT_ENCODING, DEFAULT_ENCODING
stdout_encoding = canonical_encoding_name(sys.stdout.encoding)
stderr_encoding = canonical_encoding_name(sys.stderr.encoding)
if sys.platform == "win32" and sys.version_info >= (3, 1):
return DEFAULT_ENCODING, DEFAULT_ENCODING
if stdout_encoding != "utf-8" or stderr_encoding != "utf-8":
try:
from ctypes import pythonapi, py_object, c_char_p
except ImportError:
return DEFAULT_ENCODING, DEFAULT_ENCODING
try:
PyFile_SetEncoding = pythonapi.PyFile_SetEncoding
except AttributeError:
return DEFAULT_ENCODING, DEFAULT_ENCODING
else:
PyFile_SetEncoding.argtypes = (py_object, c_char_p)
if stdout_encoding != "utf-8":
try:
was_set = PyFile_SetEncoding(sys.stdout, "utf-8")
except OSError:
was_set = False
if not was_set:
stdout_encoding = DEFAULT_ENCODING
else:
stdout_encoding = "utf-8"
if stderr_encoding != "utf-8":
try:
was_set = PyFile_SetEncoding(sys.stderr, "utf-8")
except OSError:
was_set = False
if not was_set:
stderr_encoding = DEFAULT_ENCODING
else:
stderr_encoding = "utf-8"
return stdout_encoding, stderr_encoding
OUT_ENCODING, ERR_ENCODING = force_encoding()
UNICODE_TO_ASCII_TRANSLATION_MAP = {
8230: u"...",
8211: u"-",
10004: u"OK",
10008: u"x",
}
def decode_for_output(output, target=sys.stdout):
return vistir.misc.decode_for_output(
output, sys.stdout, translation_map=UNICODE_TO_ASCII_TRANSLATION_MAP
)
def decode_output(output):
if not isinstance(output, six.string_types):
return output
try:
output = output.encode(DEFAULT_ENCODING)
except (AttributeError, UnicodeDecodeError, UnicodeEncodeError):
if six.PY2:
output = unicode.translate(vistir.misc.to_text(output),
UNICODE_TO_ASCII_TRANSLATION_MAP)
else:
output = output.translate(UNICODE_TO_ASCII_TRANSLATION_MAP)
output = output.encode(DEFAULT_ENCODING, "replace")
return vistir.misc.to_text(output, encoding=DEFAULT_ENCODING, errors="replace")
def fix_utf8(text):
if not isinstance(text, six.string_types):
return text
try:
text = decode_output(text)
except UnicodeDecodeError:
if six.PY2:
text = unicode.translate(vistir.misc.to_text(text), UNICODE_TO_ASCII_TRANSLATION_MAP)
return text