123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- from __future__ import absolute_import, division, print_function
- import platform
- import sys
- import types
- import warnings
- PY2 = sys.version_info[0] == 2
- PYPY = platform.python_implementation() == "PyPy"
- if PYPY or sys.version_info[:2] >= (3, 6):
- ordered_dict = dict
- else:
- from collections import OrderedDict
- ordered_dict = OrderedDict
- if PY2:
- from UserDict import IterableUserDict
- # We 'bundle' isclass instead of using inspect as importing inspect is
- # fairly expensive (order of 10-15 ms for a modern machine in 2016)
- def isclass(klass):
- return isinstance(klass, (type, types.ClassType))
- # TYPE is used in exceptions, repr(int) is different on Python 2 and 3.
- TYPE = "type"
- def iteritems(d):
- return d.iteritems()
- # Python 2 is bereft of a read-only dict proxy, so we make one!
- class ReadOnlyDict(IterableUserDict):
- """
- Best-effort read-only dict wrapper.
- """
- def __setitem__(self, key, val):
- # We gently pretend we're a Python 3 mappingproxy.
- raise TypeError("'mappingproxy' object does not support item "
- "assignment")
- def update(self, _):
- # We gently pretend we're a Python 3 mappingproxy.
- raise AttributeError("'mappingproxy' object has no attribute "
- "'update'")
- def __delitem__(self, _):
- # We gently pretend we're a Python 3 mappingproxy.
- raise TypeError("'mappingproxy' object does not support item "
- "deletion")
- def clear(self):
- # We gently pretend we're a Python 3 mappingproxy.
- raise AttributeError("'mappingproxy' object has no attribute "
- "'clear'")
- def pop(self, key, default=None):
- # We gently pretend we're a Python 3 mappingproxy.
- raise AttributeError("'mappingproxy' object has no attribute "
- "'pop'")
- def popitem(self):
- # We gently pretend we're a Python 3 mappingproxy.
- raise AttributeError("'mappingproxy' object has no attribute "
- "'popitem'")
- def setdefault(self, key, default=None):
- # We gently pretend we're a Python 3 mappingproxy.
- raise AttributeError("'mappingproxy' object has no attribute "
- "'setdefault'")
- def __repr__(self):
- # Override to be identical to the Python 3 version.
- return "mappingproxy(" + repr(self.data) + ")"
- def metadata_proxy(d):
- res = ReadOnlyDict()
- res.data.update(d) # We blocked update, so we have to do it like this.
- return res
- else:
- def isclass(klass):
- return isinstance(klass, type)
- TYPE = "class"
- def iteritems(d):
- return d.items()
- def metadata_proxy(d):
- return types.MappingProxyType(dict(d))
- def import_ctypes():
- """
- Moved into a function for testability.
- """
- import ctypes
- return ctypes
- if not PY2:
- def just_warn(*args, **kw):
- """
- We only warn on Python 3 because we are not aware of any concrete
- consequences of not setting the cell on Python 2.
- """
- warnings.warn(
- "Missing ctypes. Some features like bare super() or accessing "
- "__class__ will not work with slots classes.",
- RuntimeWarning,
- stacklevel=2,
- )
- else:
- def just_warn(*args, **kw): # pragma: nocover
- """
- We only warn on Python 3 because we are not aware of any concrete
- consequences of not setting the cell on Python 2.
- """
- def make_set_closure_cell():
- """
- Moved into a function for testability.
- """
- if PYPY: # pragma: no cover
- def set_closure_cell(cell, value):
- cell.__setstate__((value,))
- else:
- try:
- ctypes = import_ctypes()
- set_closure_cell = ctypes.pythonapi.PyCell_Set
- set_closure_cell.argtypes = (ctypes.py_object, ctypes.py_object)
- set_closure_cell.restype = ctypes.c_int
- except Exception:
- # We try best effort to set the cell, but sometimes it's not
- # possible. For example on Jython or on GAE.
- set_closure_cell = just_warn
- return set_closure_cell
- set_closure_cell = make_set_closure_cell()
|