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