/Lib/copy_reg.py

http://unladen-swallow.googlecode.com/ · Python · 204 lines · 148 code · 27 blank · 29 comment · 33 complexity · 58e16936037af0d93dfda468601dffa1 MD5 · raw file

  1. """Helper to provide extensibility for pickle/cPickle.
  2. This is only useful to add pickle support for extension types defined in
  3. C, not for instances of user-defined classes.
  4. """
  5. # Avoid importing the types module to speed up interpreter startup.
  6. class _C: pass
  7. _ClassType = type(_C)
  8. del _C
  9. __all__ = ["pickle", "constructor",
  10. "add_extension", "remove_extension", "clear_extension_cache"]
  11. dispatch_table = {}
  12. def pickle(ob_type, pickle_function, constructor_ob=None):
  13. if type(ob_type) is _ClassType:
  14. raise TypeError("copy_reg is not intended for use with classes")
  15. if not hasattr(pickle_function, '__call__'):
  16. raise TypeError("reduction functions must be callable")
  17. dispatch_table[ob_type] = pickle_function
  18. # The constructor_ob function is a vestige of safe for unpickling.
  19. # There is no reason for the caller to pass it anymore.
  20. if constructor_ob is not None:
  21. constructor(constructor_ob)
  22. def constructor(object):
  23. if not hasattr(object, '__call__'):
  24. raise TypeError("constructors must be callable")
  25. # Example: provide pickling support for complex numbers.
  26. try:
  27. complex
  28. except NameError:
  29. pass
  30. else:
  31. def pickle_complex(c):
  32. return complex, (c.real, c.imag)
  33. pickle(complex, pickle_complex, complex)
  34. # Support for pickling new-style objects
  35. def _reconstructor(cls, base, state):
  36. if base is object:
  37. obj = object.__new__(cls)
  38. else:
  39. obj = base.__new__(cls, state)
  40. if base.__init__ != object.__init__:
  41. base.__init__(obj, state)
  42. return obj
  43. _HEAPTYPE = 1<<9
  44. # Python code for object.__reduce_ex__ for protocols 0 and 1
  45. def _reduce_ex(self, proto):
  46. assert proto < 2
  47. for base in self.__class__.__mro__:
  48. if hasattr(base, '__flags__') and not base.__flags__ & _HEAPTYPE:
  49. break
  50. else:
  51. base = object # not really reachable
  52. if base is object:
  53. state = None
  54. else:
  55. if base is self.__class__:
  56. raise TypeError, "can't pickle %s objects" % base.__name__
  57. state = base(self)
  58. args = (self.__class__, base, state)
  59. try:
  60. getstate = self.__getstate__
  61. except AttributeError:
  62. if getattr(self, "__slots__", None):
  63. raise TypeError("a class that defines __slots__ without "
  64. "defining __getstate__ cannot be pickled")
  65. try:
  66. dict = self.__dict__
  67. except AttributeError:
  68. dict = None
  69. else:
  70. dict = getstate()
  71. if dict:
  72. return _reconstructor, args, dict
  73. else:
  74. return _reconstructor, args
  75. # Helper for __reduce_ex__ protocol 2
  76. def __newobj__(cls, *args):
  77. return cls.__new__(cls, *args)
  78. def _slotnames(cls):
  79. """Return a list of slot names for a given class.
  80. This needs to find slots defined by the class and its bases, so we
  81. can't simply return the __slots__ attribute. We must walk down
  82. the Method Resolution Order and concatenate the __slots__ of each
  83. class found there. (This assumes classes don't modify their
  84. __slots__ attribute to misrepresent their slots after the class is
  85. defined.)
  86. """
  87. # Get the value from a cache in the class if possible
  88. names = cls.__dict__.get("__slotnames__")
  89. if names is not None:
  90. return names
  91. # Not cached -- calculate the value
  92. names = []
  93. if not hasattr(cls, "__slots__"):
  94. # This class has no slots
  95. pass
  96. else:
  97. # Slots found -- gather slot names from all base classes
  98. for c in cls.__mro__:
  99. if "__slots__" in c.__dict__:
  100. slots = c.__dict__['__slots__']
  101. # if class has a single slot, it can be given as a string
  102. if isinstance(slots, basestring):
  103. slots = (slots,)
  104. for name in slots:
  105. # special descriptors
  106. if name in ("__dict__", "__weakref__"):
  107. continue
  108. # mangled names
  109. elif name.startswith('__') and not name.endswith('__'):
  110. names.append('_%s%s' % (c.__name__, name))
  111. else:
  112. names.append(name)
  113. # Cache the outcome in the class if at all possible
  114. try:
  115. cls.__slotnames__ = names
  116. except:
  117. pass # But don't die if we can't
  118. return names
  119. # A registry of extension codes. This is an ad-hoc compression
  120. # mechanism. Whenever a global reference to <module>, <name> is about
  121. # to be pickled, the (<module>, <name>) tuple is looked up here to see
  122. # if it is a registered extension code for it. Extension codes are
  123. # universal, so that the meaning of a pickle does not depend on
  124. # context. (There are also some codes reserved for local use that
  125. # don't have this restriction.) Codes are positive ints; 0 is
  126. # reserved.
  127. _extension_registry = {} # key -> code
  128. _inverted_registry = {} # code -> key
  129. _extension_cache = {} # code -> object
  130. # Don't ever rebind those names: cPickle grabs a reference to them when
  131. # it's initialized, and won't see a rebinding.
  132. def add_extension(module, name, code):
  133. """Register an extension code."""
  134. code = int(code)
  135. if not 1 <= code <= 0x7fffffff:
  136. raise ValueError, "code out of range"
  137. key = (module, name)
  138. if (_extension_registry.get(key) == code and
  139. _inverted_registry.get(code) == key):
  140. return # Redundant registrations are benign
  141. if key in _extension_registry:
  142. raise ValueError("key %s is already registered with code %s" %
  143. (key, _extension_registry[key]))
  144. if code in _inverted_registry:
  145. raise ValueError("code %s is already in use for key %s" %
  146. (code, _inverted_registry[code]))
  147. _extension_registry[key] = code
  148. _inverted_registry[code] = key
  149. def remove_extension(module, name, code):
  150. """Unregister an extension code. For testing only."""
  151. key = (module, name)
  152. if (_extension_registry.get(key) != code or
  153. _inverted_registry.get(code) != key):
  154. raise ValueError("key %s is not registered with code %s" %
  155. (key, code))
  156. del _extension_registry[key]
  157. del _inverted_registry[code]
  158. if code in _extension_cache:
  159. del _extension_cache[code]
  160. def clear_extension_cache():
  161. _extension_cache.clear()
  162. # Standard extension code assignments
  163. # Reserved ranges
  164. # First Last Count Purpose
  165. # 1 127 127 Reserved for Python standard library
  166. # 128 191 64 Reserved for Zope
  167. # 192 239 48 Reserved for 3rd parties
  168. # 240 255 16 Reserved for private use (will never be assigned)
  169. # 256 Inf Inf Reserved for future assignment
  170. # Extension codes are assigned by the Python Software Foundation.