diff options
author | Guido van Rossum <guido@python.org> | 2003-02-06 22:57:00 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2003-02-06 22:57:00 (GMT) |
commit | 5aac4e631292faf7f1679b28c906dd823c734b2d (patch) | |
tree | 98a3ffa79c235fe9d06839d304c934517dc274d9 /Lib/pickle.py | |
parent | e7ee17c58e4271d72f9a6609c92fdaeeb9c9ba79 (diff) | |
download | cpython-5aac4e631292faf7f1679b28c906dd823c734b2d.zip cpython-5aac4e631292faf7f1679b28c906dd823c734b2d.tar.gz cpython-5aac4e631292faf7f1679b28c906dd823c734b2d.tar.bz2 |
Move _better_reduce from copy.py to copy_reg.py, and also use it in
pickle.py, where it makes save_newobj() unnecessary. Tests pass.
Diffstat (limited to 'Lib/pickle.py')
-rw-r--r-- | Lib/pickle.py | 126 |
1 files changed, 4 insertions, 122 deletions
diff --git a/Lib/pickle.py b/Lib/pickle.py index 91236e9..84c5fe4 100644 --- a/Lib/pickle.py +++ b/Lib/pickle.py @@ -27,7 +27,7 @@ Misc variables: __version__ = "$Revision$" # Code version from types import * -from copy_reg import dispatch_table, _reconstructor +from copy_reg import dispatch_table, _reconstructor, _better_reduce from copy_reg import _extension_registry, _inverted_registry, _extension_cache import marshal import sys @@ -310,10 +310,7 @@ class Pickler: if self.proto >= 2: # Protocol 2 can do better than the default __reduce__ if reduce is object.__reduce__: - reduce = None - if not reduce: - self.save_newobj(obj) - return + reduce = _better_reduce if not reduce: raise PicklingError("Can't pickle %r object: %r" % (t.__name__, obj)) @@ -433,86 +430,6 @@ class Pickler: save(state) write(BUILD) - def save_newobj(self, obj): - # Save a new-style class instance, using protocol 2. - assert self.proto >= 2 # This only works for protocol 2 - t = type(obj) - getnewargs = getattr(obj, "__getnewargs__", None) - if getnewargs: - args = getnewargs() # This better not reference obj - else: - args = () - - save = self.save - write = self.write - - self.save(t) - save(args) - write(NEWOBJ) - self.memoize(obj) - - if isinstance(obj, list): - self._batch_appends(iter(obj)) - elif isinstance(obj, dict): - self._batch_setitems(obj.iteritems()) - - getstate = getattr(obj, "__getstate__", None) - - if getstate: - # A class may define both __getstate__ and __getnewargs__. - # If they are the same function, we ignore __getstate__. - # This is for the benefit of protocols 0 and 1, which don't - # use __getnewargs__. Note that the only way to make them - # the same function is something like this: - # - # class C(object): - # def __getstate__(self): - # return ... - # __getnewargs__ = __getstate__ - # - # No tricks are needed to ignore __setstate__; it simply - # won't be called when we don't generate BUILD. - # Also note that when __getnewargs__ and __getstate__ are - # the same function, we don't do the default thing of - # looking for __dict__ and slots either -- it is assumed - # that __getnewargs__ returns all the state there is - # (which should be a safe assumption since __getstate__ - # returns the *same* state). - if getstate == getnewargs: - return - - try: - state = getstate() - except TypeError, err: - # XXX Catch generic exception caused by __slots__ - if str(err) != ("a class that defines __slots__ " - "without defining __getstate__ " - "cannot be pickled"): - raise # Not that specific exception - getstate = None - - if not getstate: - state = getattr(obj, "__dict__", None) - if not state: - state = None - # If there are slots, the state becomes a tuple of two - # items: the first item the regular __dict__ or None, and - # the second a dict mapping slot names to slot values - names = _slotnames(t) - if names: - slots = {} - nil = [] - for name in names: - value = getattr(obj, name, nil) - if value is not nil: - slots[name] = value - if slots: - state = (state, slots) - - if state is not None: - save(state) - write(BUILD) - # Methods below this point are dispatched through the dispatch table dispatch = {} @@ -713,7 +630,8 @@ class Pickler: tmp = [] for i in r: try: - tmp.append(items.next()) + x = items.next() + tmp.append(x) except StopIteration: items = None break @@ -865,42 +783,6 @@ class Pickler: # Pickling helpers -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__: - names += [name for name in c.__dict__["__slots__"] - if name not in ("__dict__", "__weakref__")] - - # 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 - def _keep_alive(x, memo): """Keeps a reference to the object x in the memo. |