_utils.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. from __future__ import absolute_import, division, unicode_literals
  2. from types import ModuleType
  3. from pip._vendor.six import text_type
  4. try:
  5. import xml.etree.cElementTree as default_etree
  6. except ImportError:
  7. import xml.etree.ElementTree as default_etree
  8. __all__ = ["default_etree", "MethodDispatcher", "isSurrogatePair",
  9. "surrogatePairToCodepoint", "moduleFactoryFactory",
  10. "supports_lone_surrogates"]
  11. # Platforms not supporting lone surrogates (\uD800-\uDFFF) should be
  12. # caught by the below test. In general this would be any platform
  13. # using UTF-16 as its encoding of unicode strings, such as
  14. # Jython. This is because UTF-16 itself is based on the use of such
  15. # surrogates, and there is no mechanism to further escape such
  16. # escapes.
  17. try:
  18. _x = eval('"\\uD800"') # pylint:disable=eval-used
  19. if not isinstance(_x, text_type):
  20. # We need this with u"" because of http://bugs.jython.org/issue2039
  21. _x = eval('u"\\uD800"') # pylint:disable=eval-used
  22. assert isinstance(_x, text_type)
  23. except: # pylint:disable=bare-except
  24. supports_lone_surrogates = False
  25. else:
  26. supports_lone_surrogates = True
  27. class MethodDispatcher(dict):
  28. """Dict with 2 special properties:
  29. On initiation, keys that are lists, sets or tuples are converted to
  30. multiple keys so accessing any one of the items in the original
  31. list-like object returns the matching value
  32. md = MethodDispatcher({("foo", "bar"):"baz"})
  33. md["foo"] == "baz"
  34. A default value which can be set through the default attribute.
  35. """
  36. def __init__(self, items=()):
  37. # Using _dictEntries instead of directly assigning to self is about
  38. # twice as fast. Please do careful performance testing before changing
  39. # anything here.
  40. _dictEntries = []
  41. for name, value in items:
  42. if isinstance(name, (list, tuple, frozenset, set)):
  43. for item in name:
  44. _dictEntries.append((item, value))
  45. else:
  46. _dictEntries.append((name, value))
  47. dict.__init__(self, _dictEntries)
  48. assert len(self) == len(_dictEntries)
  49. self.default = None
  50. def __getitem__(self, key):
  51. return dict.get(self, key, self.default)
  52. # Some utility functions to deal with weirdness around UCS2 vs UCS4
  53. # python builds
  54. def isSurrogatePair(data):
  55. return (len(data) == 2 and
  56. ord(data[0]) >= 0xD800 and ord(data[0]) <= 0xDBFF and
  57. ord(data[1]) >= 0xDC00 and ord(data[1]) <= 0xDFFF)
  58. def surrogatePairToCodepoint(data):
  59. char_val = (0x10000 + (ord(data[0]) - 0xD800) * 0x400 +
  60. (ord(data[1]) - 0xDC00))
  61. return char_val
  62. # Module Factory Factory (no, this isn't Java, I know)
  63. # Here to stop this being duplicated all over the place.
  64. def moduleFactoryFactory(factory):
  65. moduleCache = {}
  66. def moduleFactory(baseModule, *args, **kwargs):
  67. if isinstance(ModuleType.__name__, type("")):
  68. name = "_%s_factory" % baseModule.__name__
  69. else:
  70. name = b"_%s_factory" % baseModule.__name__
  71. kwargs_tuple = tuple(kwargs.items())
  72. try:
  73. return moduleCache[name][args][kwargs_tuple]
  74. except KeyError:
  75. mod = ModuleType(name)
  76. objs = factory(baseModule, *args, **kwargs)
  77. mod.__dict__.update(objs)
  78. if "name" not in moduleCache:
  79. moduleCache[name] = {}
  80. if "args" not in moduleCache[name]:
  81. moduleCache[name][args] = {}
  82. if "kwargs" not in moduleCache[name][args]:
  83. moduleCache[name][args][kwargs_tuple] = {}
  84. moduleCache[name][args][kwargs_tuple] = mod
  85. return mod
  86. return moduleFactory
  87. def memoize(func):
  88. cache = {}
  89. def wrapped(*args, **kwargs):
  90. key = (tuple(args), tuple(kwargs.items()))
  91. if key not in cache:
  92. cache[key] = func(*args, **kwargs)
  93. return cache[key]
  94. return wrapped