_compat.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. # flake8: noqa
  2. # This whole file is full of lint errors
  3. import functools
  4. import operator
  5. import sys
  6. try:
  7. import builtins
  8. except ImportError:
  9. import __builtin__ as builtins
  10. PY2 = sys.version_info[0] == 2
  11. WIN = sys.platform.startswith("win")
  12. _identity = lambda x: x
  13. if PY2:
  14. unichr = unichr
  15. text_type = unicode
  16. string_types = (str, unicode)
  17. integer_types = (int, long)
  18. iterkeys = lambda d, *args, **kwargs: d.iterkeys(*args, **kwargs)
  19. itervalues = lambda d, *args, **kwargs: d.itervalues(*args, **kwargs)
  20. iteritems = lambda d, *args, **kwargs: d.iteritems(*args, **kwargs)
  21. iterlists = lambda d, *args, **kwargs: d.iterlists(*args, **kwargs)
  22. iterlistvalues = lambda d, *args, **kwargs: d.iterlistvalues(*args, **kwargs)
  23. int_to_byte = chr
  24. iter_bytes = iter
  25. import collections as collections_abc
  26. exec("def reraise(tp, value, tb=None):\n raise tp, value, tb")
  27. def fix_tuple_repr(obj):
  28. def __repr__(self):
  29. cls = self.__class__
  30. return "%s(%s)" % (
  31. cls.__name__,
  32. ", ".join(
  33. "%s=%r" % (field, self[index])
  34. for index, field in enumerate(cls._fields)
  35. ),
  36. )
  37. obj.__repr__ = __repr__
  38. return obj
  39. def implements_iterator(cls):
  40. cls.next = cls.__next__
  41. del cls.__next__
  42. return cls
  43. def implements_to_string(cls):
  44. cls.__unicode__ = cls.__str__
  45. cls.__str__ = lambda x: x.__unicode__().encode("utf-8")
  46. return cls
  47. def native_string_result(func):
  48. def wrapper(*args, **kwargs):
  49. return func(*args, **kwargs).encode("utf-8")
  50. return functools.update_wrapper(wrapper, func)
  51. def implements_bool(cls):
  52. cls.__nonzero__ = cls.__bool__
  53. del cls.__bool__
  54. return cls
  55. from itertools import imap, izip, ifilter
  56. range_type = xrange
  57. from StringIO import StringIO
  58. from cStringIO import StringIO as BytesIO
  59. NativeStringIO = BytesIO
  60. def make_literal_wrapper(reference):
  61. return _identity
  62. def normalize_string_tuple(tup):
  63. """Normalizes a string tuple to a common type. Following Python 2
  64. rules, upgrades to unicode are implicit.
  65. """
  66. if any(isinstance(x, text_type) for x in tup):
  67. return tuple(to_unicode(x) for x in tup)
  68. return tup
  69. def try_coerce_native(s):
  70. """Try to coerce a unicode string to native if possible. Otherwise,
  71. leave it as unicode.
  72. """
  73. try:
  74. return to_native(s)
  75. except UnicodeError:
  76. return s
  77. wsgi_get_bytes = _identity
  78. def wsgi_decoding_dance(s, charset="utf-8", errors="replace"):
  79. return s.decode(charset, errors)
  80. def wsgi_encoding_dance(s, charset="utf-8", errors="replace"):
  81. if isinstance(s, bytes):
  82. return s
  83. return s.encode(charset, errors)
  84. def to_bytes(x, charset=sys.getdefaultencoding(), errors="strict"):
  85. if x is None:
  86. return None
  87. if isinstance(x, (bytes, bytearray, buffer)):
  88. return bytes(x)
  89. if isinstance(x, unicode):
  90. return x.encode(charset, errors)
  91. raise TypeError("Expected bytes")
  92. def to_native(x, charset=sys.getdefaultencoding(), errors="strict"):
  93. if x is None or isinstance(x, str):
  94. return x
  95. return x.encode(charset, errors)
  96. else:
  97. unichr = chr
  98. text_type = str
  99. string_types = (str,)
  100. integer_types = (int,)
  101. iterkeys = lambda d, *args, **kwargs: iter(d.keys(*args, **kwargs))
  102. itervalues = lambda d, *args, **kwargs: iter(d.values(*args, **kwargs))
  103. iteritems = lambda d, *args, **kwargs: iter(d.items(*args, **kwargs))
  104. iterlists = lambda d, *args, **kwargs: iter(d.lists(*args, **kwargs))
  105. iterlistvalues = lambda d, *args, **kwargs: iter(d.listvalues(*args, **kwargs))
  106. int_to_byte = operator.methodcaller("to_bytes", 1, "big")
  107. iter_bytes = functools.partial(map, int_to_byte)
  108. import collections.abc as collections_abc
  109. def reraise(tp, value, tb=None):
  110. if value.__traceback__ is not tb:
  111. raise value.with_traceback(tb)
  112. raise value
  113. fix_tuple_repr = _identity
  114. implements_iterator = _identity
  115. implements_to_string = _identity
  116. implements_bool = _identity
  117. native_string_result = _identity
  118. imap = map
  119. izip = zip
  120. ifilter = filter
  121. range_type = range
  122. from io import StringIO, BytesIO
  123. NativeStringIO = StringIO
  124. _latin1_encode = operator.methodcaller("encode", "latin1")
  125. def make_literal_wrapper(reference):
  126. if isinstance(reference, text_type):
  127. return _identity
  128. return _latin1_encode
  129. def normalize_string_tuple(tup):
  130. """Ensures that all types in the tuple are either strings
  131. or bytes.
  132. """
  133. tupiter = iter(tup)
  134. is_text = isinstance(next(tupiter, None), text_type)
  135. for arg in tupiter:
  136. if isinstance(arg, text_type) != is_text:
  137. raise TypeError(
  138. "Cannot mix str and bytes arguments (got %s)" % repr(tup)
  139. )
  140. return tup
  141. try_coerce_native = _identity
  142. wsgi_get_bytes = _latin1_encode
  143. def wsgi_decoding_dance(s, charset="utf-8", errors="replace"):
  144. return s.encode("latin1").decode(charset, errors)
  145. def wsgi_encoding_dance(s, charset="utf-8", errors="replace"):
  146. if isinstance(s, text_type):
  147. s = s.encode(charset)
  148. return s.decode("latin1", errors)
  149. def to_bytes(x, charset=sys.getdefaultencoding(), errors="strict"):
  150. if x is None:
  151. return None
  152. if isinstance(x, (bytes, bytearray, memoryview)): # noqa
  153. return bytes(x)
  154. if isinstance(x, str):
  155. return x.encode(charset, errors)
  156. raise TypeError("Expected bytes")
  157. def to_native(x, charset=sys.getdefaultencoding(), errors="strict"):
  158. if x is None or isinstance(x, str):
  159. return x
  160. return x.decode(charset, errors)
  161. def to_unicode(
  162. x, charset=sys.getdefaultencoding(), errors="strict", allow_none_charset=False
  163. ):
  164. if x is None:
  165. return None
  166. if not isinstance(x, bytes):
  167. return text_type(x)
  168. if charset is None and allow_none_charset:
  169. return x
  170. return x.decode(charset, errors)
  171. try:
  172. from os import fspath
  173. except ImportError:
  174. # Python < 3.6
  175. # https://www.python.org/dev/peps/pep-0519/#backwards-compatibility
  176. def fspath(path):
  177. return path.__fspath__() if hasattr(path, "__fspath__") else path