123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- from __future__ import absolute_import, division, unicode_literals
- from types import ModuleType
- try:
- from collections.abc import Mapping
- except ImportError:
- from collections import Mapping
- from pip._vendor.six import text_type, PY3
- if PY3:
- import xml.etree.ElementTree as default_etree
- else:
- try:
- import xml.etree.cElementTree as default_etree
- except ImportError:
- import xml.etree.ElementTree as default_etree
- __all__ = ["default_etree", "MethodDispatcher", "isSurrogatePair",
- "surrogatePairToCodepoint", "moduleFactoryFactory",
- "supports_lone_surrogates"]
- # Platforms not supporting lone surrogates (\uD800-\uDFFF) should be
- # caught by the below test. In general this would be any platform
- # using UTF-16 as its encoding of unicode strings, such as
- # Jython. This is because UTF-16 itself is based on the use of such
- # surrogates, and there is no mechanism to further escape such
- # escapes.
- try:
- _x = eval('"\\uD800"') # pylint:disable=eval-used
- if not isinstance(_x, text_type):
- # We need this with u"" because of http://bugs.jython.org/issue2039
- _x = eval('u"\\uD800"') # pylint:disable=eval-used
- assert isinstance(_x, text_type)
- except Exception:
- supports_lone_surrogates = False
- else:
- supports_lone_surrogates = True
- class MethodDispatcher(dict):
- """Dict with 2 special properties:
- On initiation, keys that are lists, sets or tuples are converted to
- multiple keys so accessing any one of the items in the original
- list-like object returns the matching value
- md = MethodDispatcher({("foo", "bar"):"baz"})
- md["foo"] == "baz"
- A default value which can be set through the default attribute.
- """
- def __init__(self, items=()):
- _dictEntries = []
- for name, value in items:
- if isinstance(name, (list, tuple, frozenset, set)):
- for item in name:
- _dictEntries.append((item, value))
- else:
- _dictEntries.append((name, value))
- dict.__init__(self, _dictEntries)
- assert len(self) == len(_dictEntries)
- self.default = None
- def __getitem__(self, key):
- return dict.get(self, key, self.default)
- def __get__(self, instance, owner=None):
- return BoundMethodDispatcher(instance, self)
- class BoundMethodDispatcher(Mapping):
- """Wraps a MethodDispatcher, binding its return values to `instance`"""
- def __init__(self, instance, dispatcher):
- self.instance = instance
- self.dispatcher = dispatcher
- def __getitem__(self, key):
- # see https://docs.python.org/3/reference/datamodel.html#object.__get__
- # on a function, __get__ is used to bind a function to an instance as a bound method
- return self.dispatcher[key].__get__(self.instance)
- def get(self, key, default):
- if key in self.dispatcher:
- return self[key]
- else:
- return default
- def __iter__(self):
- return iter(self.dispatcher)
- def __len__(self):
- return len(self.dispatcher)
- def __contains__(self, key):
- return key in self.dispatcher
- # Some utility functions to deal with weirdness around UCS2 vs UCS4
- # python builds
- def isSurrogatePair(data):
- return (len(data) == 2 and
- ord(data[0]) >= 0xD800 and ord(data[0]) <= 0xDBFF and
- ord(data[1]) >= 0xDC00 and ord(data[1]) <= 0xDFFF)
- def surrogatePairToCodepoint(data):
- char_val = (0x10000 + (ord(data[0]) - 0xD800) * 0x400 +
- (ord(data[1]) - 0xDC00))
- return char_val
- # Module Factory Factory (no, this isn't Java, I know)
- # Here to stop this being duplicated all over the place.
- def moduleFactoryFactory(factory):
- moduleCache = {}
- def moduleFactory(baseModule, *args, **kwargs):
- if isinstance(ModuleType.__name__, type("")):
- name = "_%s_factory" % baseModule.__name__
- else:
- name = b"_%s_factory" % baseModule.__name__
- kwargs_tuple = tuple(kwargs.items())
- try:
- return moduleCache[name][args][kwargs_tuple]
- except KeyError:
- mod = ModuleType(name)
- objs = factory(baseModule, *args, **kwargs)
- mod.__dict__.update(objs)
- if "name" not in moduleCache:
- moduleCache[name] = {}
- if "args" not in moduleCache[name]:
- moduleCache[name][args] = {}
- if "kwargs" not in moduleCache[name][args]:
- moduleCache[name][args][kwargs_tuple] = {}
- moduleCache[name][args][kwargs_tuple] = mod
- return mod
- return moduleFactory
- def memoize(func):
- cache = {}
- def wrapped(*args, **kwargs):
- key = (tuple(args), tuple(kwargs.items()))
- if key not in cache:
- cache[key] = func(*args, **kwargs)
- return cache[key]
- return wrapped
|