0001 """Helper to provide extensibility for pickle/cPickle. 0002 0003 This is only useful to add pickle support for extension types defined in 0004 C, not for instances of user-defined classes. 0005 """ 0006 0007 from types import ClassType as _ClassType 0008 0009 __all__ = ["pickle", "constructor", 0010 "add_extension", "remove_extension", "clear_extension_cache"] 0011 0012 dispatch_table = {} 0013 0014 def pickle(ob_type, pickle_function, constructor_ob=None): 0015 if type(ob_type) is _ClassType: 0016 raise TypeError("copy_reg is not intended for use with classes") 0017 0018 if not callable(pickle_function): 0019 raise TypeError("reduction functions must be callable") 0020 dispatch_table[ob_type] = pickle_function 0021 0022 # The constructor_ob function is a vestige of safe for unpickling. 0023 # There is no reason for the caller to pass it anymore. 0024 if constructor_ob is not None: 0025 constructor(constructor_ob) 0026 0027 def constructor(object): 0028 if not callable(object): 0029 raise TypeError("constructors must be callable") 0030 0031 # Example: provide pickling support for complex numbers. 0032 0033 try: 0034 complex 0035 except NameError: 0036 pass 0037 else: 0038 0039 def pickle_complex(c): 0040 return complex, (c.real, c.imag) 0041 0042 pickle(complex, pickle_complex, complex) 0043 0044 # Support for pickling new-style objects 0045 0046 def _reconstructor(cls, base, state): 0047 if base is object: 0048 obj = object.__new__(cls) 0049 else: 0050 obj = base.__new__(cls, state) 0051 base.__init__(obj, state) 0052 return obj 0053 0054 _HEAPTYPE = 1<<9 0055 0056 # Python code for object.__reduce_ex__ for protocols 0 and 1 0057 0058 def _reduce_ex(self, proto): 0059 assert proto < 2 0060 for base in self.__class__.__mro__: 0061 if hasattr(base, '__flags__') and not base.__flags__ & _HEAPTYPE: 0062 break 0063 else: 0064 base = object # not really reachable 0065 if base is object: 0066 state = None 0067 else: 0068 if base is self.__class__: 0069 raise TypeError, "can't pickle %s objects" % base.__name__ 0070 state = base(self) 0071 args = (self.__class__, base, state) 0072 try: 0073 getstate = self.__getstate__ 0074 except AttributeError: 0075 if getattr(self, "__slots__", None): 0076 raise TypeError("a class that defines __slots__ without " 0077 "defining __getstate__ cannot be pickled") 0078 try: 0079 dict = self.__dict__ 0080 except AttributeError: 0081 dict = None 0082 else: 0083 dict = getstate() 0084 if dict: 0085 return _reconstructor, args, dict 0086 else: 0087 return _reconstructor, args 0088 0089 # Helper for __reduce_ex__ protocol 2 0090 0091 def __newobj__(cls, *args): 0092 return cls.__new__(cls, *args) 0093 0094 def _slotnames(cls): 0095 """Return a list of slot names for a given class. 0096 0097 This needs to find slots defined by the class and its bases, so we 0098 can't simply return the __slots__ attribute. We must walk down 0099 the Method Resolution Order and concatenate the __slots__ of each 0100 class found there. (This assumes classes don't modify their 0101 __slots__ attribute to misrepresent their slots after the class is 0102 defined.) 0103 """ 0104 0105 # Get the value from a cache in the class if possible 0106 names = cls.__dict__.get("__slotnames__") 0107 if names is not None: 0108 return names 0109 0110 # Not cached -- calculate the value 0111 names = [] 0112 if not hasattr(cls, "__slots__"): 0113 # This class has no slots 0114 pass 0115 else: 0116 # Slots found -- gather slot names from all base classes 0117 for c in cls.__mro__: 0118 if "__slots__" in c.__dict__: 0119 names += [name for name in c.__dict__["__slots__"] 0120 if name not in ("__dict__", "__weakref__")] 0121 0122 # Cache the outcome in the class if at all possible 0123 try: 0124 cls.__slotnames__ = names 0125 except: 0126 pass # But don't die if we can't 0127 0128 return names 0129 0130 # A registry of extension codes. This is an ad-hoc compression 0131 # mechanism. Whenever a global reference to <module>, <name> is about 0132 # to be pickled, the (<module>, <name>) tuple is looked up here to see 0133 # if it is a registered extension code for it. Extension codes are 0134 # universal, so that the meaning of a pickle does not depend on 0135 # context. (There are also some codes reserved for local use that 0136 # don't have this restriction.) Codes are positive ints; 0 is 0137 # reserved. 0138 0139 _extension_registry = {} # key -> code 0140 _inverted_registry = {} # code -> key 0141 _extension_cache = {} # code -> object 0142 # Don't ever rebind those names: cPickle grabs a reference to them when 0143 # it's initialized, and won't see a rebinding. 0144 0145 def add_extension(module, name, code): 0146 """Register an extension code.""" 0147 code = int(code) 0148 if not 1 <= code <= 0x7fffffff: 0149 raise ValueError, "code out of range" 0150 key = (module, name) 0151 if (_extension_registry.get(key) == code and 0152 _inverted_registry.get(code) == key): 0153 return # Redundant registrations are benign 0154 if key in _extension_registry: 0155 raise ValueError("key %s is already registered with code %s" % 0156 (key, _extension_registry[key])) 0157 if code in _inverted_registry: 0158 raise ValueError("code %s is already in use for key %s" % 0159 (code, _inverted_registry[code])) 0160 _extension_registry[key] = code 0161 _inverted_registry[code] = key 0162 0163 def remove_extension(module, name, code): 0164 """Unregister an extension code. For testing only.""" 0165 key = (module, name) 0166 if (_extension_registry.get(key) != code or 0167 _inverted_registry.get(code) != key): 0168 raise ValueError("key %s is not registered with code %s" % 0169 (key, code)) 0170 del _extension_registry[key] 0171 del _inverted_registry[code] 0172 if code in _extension_cache: 0173 del _extension_cache[code] 0174 0175 def clear_extension_cache(): 0176 _extension_cache.clear() 0177 0178 # Standard extension code assignments 0179 0180 # Reserved ranges 0181 0182 # First Last Count Purpose 0183 # 1 127 127 Reserved for Python standard library 0184 # 128 191 64 Reserved for Zope 0185 # 192 239 48 Reserved for 3rd parties 0186 # 240 255 16 Reserved for private use (will never be assigned) 0187 # 256 Inf Inf Reserved for future assignment 0188 0189 # Extension codes are assigned by the Python Software Foundation. 0190
Generated by PyXR 0.9.4