# -*- 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 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), # noqa 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) # noqa return text