+++ /dev/null
-"""Helper to provide extensibility for pickle/cPickle.\r
-\r
-This is only useful to add pickle support for extension types defined in\r
-C, not for instances of user-defined classes.\r
-"""\r
-\r
-from types import ClassType as _ClassType\r
-\r
-__all__ = ["pickle", "constructor",\r
- "add_extension", "remove_extension", "clear_extension_cache"]\r
-\r
-dispatch_table = {}\r
-\r
-def pickle(ob_type, pickle_function, constructor_ob=None):\r
- if type(ob_type) is _ClassType:\r
- raise TypeError("copy_reg is not intended for use with classes")\r
-\r
- if not hasattr(pickle_function, '__call__'):\r
- raise TypeError("reduction functions must be callable")\r
- dispatch_table[ob_type] = pickle_function\r
-\r
- # The constructor_ob function is a vestige of safe for unpickling.\r
- # There is no reason for the caller to pass it anymore.\r
- if constructor_ob is not None:\r
- constructor(constructor_ob)\r
-\r
-def constructor(object):\r
- if not hasattr(object, '__call__'):\r
- raise TypeError("constructors must be callable")\r
-\r
-# Example: provide pickling support for complex numbers.\r
-\r
-try:\r
- complex\r
-except NameError:\r
- pass\r
-else:\r
-\r
- def pickle_complex(c):\r
- return complex, (c.real, c.imag)\r
-\r
- pickle(complex, pickle_complex, complex)\r
-\r
-# Support for pickling new-style objects\r
-\r
-def _reconstructor(cls, base, state):\r
- if base is object:\r
- obj = object.__new__(cls)\r
- else:\r
- obj = base.__new__(cls, state)\r
- if base.__init__ != object.__init__:\r
- base.__init__(obj, state)\r
- return obj\r
-\r
-_HEAPTYPE = 1<<9\r
-\r
-# Python code for object.__reduce_ex__ for protocols 0 and 1\r
-\r
-def _reduce_ex(self, proto):\r
- assert proto < 2\r
- for base in self.__class__.__mro__:\r
- if hasattr(base, '__flags__') and not base.__flags__ & _HEAPTYPE:\r
- break\r
- else:\r
- base = object # not really reachable\r
- if base is object:\r
- state = None\r
- else:\r
- if base is self.__class__:\r
- raise TypeError, "can't pickle %s objects" % base.__name__\r
- state = base(self)\r
- args = (self.__class__, base, state)\r
- try:\r
- getstate = self.__getstate__\r
- except AttributeError:\r
- if getattr(self, "__slots__", None):\r
- raise TypeError("a class that defines __slots__ without "\r
- "defining __getstate__ cannot be pickled")\r
- try:\r
- dict = self.__dict__\r
- except AttributeError:\r
- dict = None\r
- else:\r
- dict = getstate()\r
- if dict:\r
- return _reconstructor, args, dict\r
- else:\r
- return _reconstructor, args\r
-\r
-# Helper for __reduce_ex__ protocol 2\r
-\r
-def __newobj__(cls, *args):\r
- return cls.__new__(cls, *args)\r
-\r
-def _slotnames(cls):\r
- """Return a list of slot names for a given class.\r
-\r
- This needs to find slots defined by the class and its bases, so we\r
- can't simply return the __slots__ attribute. We must walk down\r
- the Method Resolution Order and concatenate the __slots__ of each\r
- class found there. (This assumes classes don't modify their\r
- __slots__ attribute to misrepresent their slots after the class is\r
- defined.)\r
- """\r
-\r
- # Get the value from a cache in the class if possible\r
- names = cls.__dict__.get("__slotnames__")\r
- if names is not None:\r
- return names\r
-\r
- # Not cached -- calculate the value\r
- names = []\r
- if not hasattr(cls, "__slots__"):\r
- # This class has no slots\r
- pass\r
- else:\r
- # Slots found -- gather slot names from all base classes\r
- for c in cls.__mro__:\r
- if "__slots__" in c.__dict__:\r
- slots = c.__dict__['__slots__']\r
- # if class has a single slot, it can be given as a string\r
- if isinstance(slots, basestring):\r
- slots = (slots,)\r
- for name in slots:\r
- # special descriptors\r
- if name in ("__dict__", "__weakref__"):\r
- continue\r
- # mangled names\r
- elif name.startswith('__') and not name.endswith('__'):\r
- names.append('_%s%s' % (c.__name__, name))\r
- else:\r
- names.append(name)\r
-\r
- # Cache the outcome in the class if at all possible\r
- try:\r
- cls.__slotnames__ = names\r
- except:\r
- pass # But don't die if we can't\r
-\r
- return names\r
-\r
-# A registry of extension codes. This is an ad-hoc compression\r
-# mechanism. Whenever a global reference to <module>, <name> is about\r
-# to be pickled, the (<module>, <name>) tuple is looked up here to see\r
-# if it is a registered extension code for it. Extension codes are\r
-# universal, so that the meaning of a pickle does not depend on\r
-# context. (There are also some codes reserved for local use that\r
-# don't have this restriction.) Codes are positive ints; 0 is\r
-# reserved.\r
-\r
-_extension_registry = {} # key -> code\r
-_inverted_registry = {} # code -> key\r
-_extension_cache = {} # code -> object\r
-# Don't ever rebind those names: cPickle grabs a reference to them when\r
-# it's initialized, and won't see a rebinding.\r
-\r
-def add_extension(module, name, code):\r
- """Register an extension code."""\r
- code = int(code)\r
- if not 1 <= code <= 0x7fffffff:\r
- raise ValueError, "code out of range"\r
- key = (module, name)\r
- if (_extension_registry.get(key) == code and\r
- _inverted_registry.get(code) == key):\r
- return # Redundant registrations are benign\r
- if key in _extension_registry:\r
- raise ValueError("key %s is already registered with code %s" %\r
- (key, _extension_registry[key]))\r
- if code in _inverted_registry:\r
- raise ValueError("code %s is already in use for key %s" %\r
- (code, _inverted_registry[code]))\r
- _extension_registry[key] = code\r
- _inverted_registry[code] = key\r
-\r
-def remove_extension(module, name, code):\r
- """Unregister an extension code. For testing only."""\r
- key = (module, name)\r
- if (_extension_registry.get(key) != code or\r
- _inverted_registry.get(code) != key):\r
- raise ValueError("key %s is not registered with code %s" %\r
- (key, code))\r
- del _extension_registry[key]\r
- del _inverted_registry[code]\r
- if code in _extension_cache:\r
- del _extension_cache[code]\r
-\r
-def clear_extension_cache():\r
- _extension_cache.clear()\r
-\r
-# Standard extension code assignments\r
-\r
-# Reserved ranges\r
-\r
-# First Last Count Purpose\r
-# 1 127 127 Reserved for Python standard library\r
-# 128 191 64 Reserved for Zope\r
-# 192 239 48 Reserved for 3rd parties\r
-# 240 255 16 Reserved for private use (will never be assigned)\r
-# 256 Inf Inf Reserved for future assignment\r
-\r
-# Extension codes are assigned by the Python Software Foundation.\r