|
27 | 27 | __version__ = "$Revision$" # Code version |
28 | 28 |
|
29 | 29 | from types import * |
30 | | -from copy_reg import dispatch_table, _reconstructor |
| 30 | +from copy_reg import dispatch_table, _reconstructor, _better_reduce |
31 | 31 | from copy_reg import _extension_registry, _inverted_registry, _extension_cache |
32 | 32 | import marshal |
33 | 33 | import sys |
@@ -310,10 +310,7 @@ def save(self, obj): |
310 | 310 | if self.proto >= 2: |
311 | 311 | # Protocol 2 can do better than the default __reduce__ |
312 | 312 | if reduce is object.__reduce__: |
313 | | - reduce = None |
314 | | - if not reduce: |
315 | | - self.save_newobj(obj) |
316 | | - return |
| 313 | + reduce = _better_reduce |
317 | 314 | if not reduce: |
318 | 315 | raise PicklingError("Can't pickle %r object: %r" % |
319 | 316 | (t.__name__, obj)) |
@@ -433,86 +430,6 @@ def save_reduce(self, func, args, state=None, |
433 | 430 | save(state) |
434 | 431 | write(BUILD) |
435 | 432 |
|
436 | | - def save_newobj(self, obj): |
437 | | - # Save a new-style class instance, using protocol 2. |
438 | | - assert self.proto >= 2 # This only works for protocol 2 |
439 | | - t = type(obj) |
440 | | - getnewargs = getattr(obj, "__getnewargs__", None) |
441 | | - if getnewargs: |
442 | | - args = getnewargs() # This better not reference obj |
443 | | - else: |
444 | | - args = () |
445 | | - |
446 | | - save = self.save |
447 | | - write = self.write |
448 | | - |
449 | | - self.save(t) |
450 | | - save(args) |
451 | | - write(NEWOBJ) |
452 | | - self.memoize(obj) |
453 | | - |
454 | | - if isinstance(obj, list): |
455 | | - self._batch_appends(iter(obj)) |
456 | | - elif isinstance(obj, dict): |
457 | | - self._batch_setitems(obj.iteritems()) |
458 | | - |
459 | | - getstate = getattr(obj, "__getstate__", None) |
460 | | - |
461 | | - if getstate: |
462 | | - # A class may define both __getstate__ and __getnewargs__. |
463 | | - # If they are the same function, we ignore __getstate__. |
464 | | - # This is for the benefit of protocols 0 and 1, which don't |
465 | | - # use __getnewargs__. Note that the only way to make them |
466 | | - # the same function is something like this: |
467 | | - # |
468 | | - # class C(object): |
469 | | - # def __getstate__(self): |
470 | | - # return ... |
471 | | - # __getnewargs__ = __getstate__ |
472 | | - # |
473 | | - # No tricks are needed to ignore __setstate__; it simply |
474 | | - # won't be called when we don't generate BUILD. |
475 | | - # Also note that when __getnewargs__ and __getstate__ are |
476 | | - # the same function, we don't do the default thing of |
477 | | - # looking for __dict__ and slots either -- it is assumed |
478 | | - # that __getnewargs__ returns all the state there is |
479 | | - # (which should be a safe assumption since __getstate__ |
480 | | - # returns the *same* state). |
481 | | - if getstate == getnewargs: |
482 | | - return |
483 | | - |
484 | | - try: |
485 | | - state = getstate() |
486 | | - except TypeError, err: |
487 | | - # XXX Catch generic exception caused by __slots__ |
488 | | - if str(err) != ("a class that defines __slots__ " |
489 | | - "without defining __getstate__ " |
490 | | - "cannot be pickled"): |
491 | | - raise # Not that specific exception |
492 | | - getstate = None |
493 | | - |
494 | | - if not getstate: |
495 | | - state = getattr(obj, "__dict__", None) |
496 | | - if not state: |
497 | | - state = None |
498 | | - # If there are slots, the state becomes a tuple of two |
499 | | - # items: the first item the regular __dict__ or None, and |
500 | | - # the second a dict mapping slot names to slot values |
501 | | - names = _slotnames(t) |
502 | | - if names: |
503 | | - slots = {} |
504 | | - nil = [] |
505 | | - for name in names: |
506 | | - value = getattr(obj, name, nil) |
507 | | - if value is not nil: |
508 | | - slots[name] = value |
509 | | - if slots: |
510 | | - state = (state, slots) |
511 | | - |
512 | | - if state is not None: |
513 | | - save(state) |
514 | | - write(BUILD) |
515 | | - |
516 | 433 | # Methods below this point are dispatched through the dispatch table |
517 | 434 |
|
518 | 435 | dispatch = {} |
@@ -713,7 +630,8 @@ def _batch_appends(self, items): |
713 | 630 | tmp = [] |
714 | 631 | for i in r: |
715 | 632 | try: |
716 | | - tmp.append(items.next()) |
| 633 | + x = items.next() |
| 634 | + tmp.append(x) |
717 | 635 | except StopIteration: |
718 | 636 | items = None |
719 | 637 | break |
@@ -865,42 +783,6 @@ def save_global(self, obj, name=None, pack=struct.pack): |
865 | 783 |
|
866 | 784 | # Pickling helpers |
867 | 785 |
|
868 | | -def _slotnames(cls): |
869 | | - """Return a list of slot names for a given class. |
870 | | -
|
871 | | - This needs to find slots defined by the class and its bases, so we |
872 | | - can't simply return the __slots__ attribute. We must walk down |
873 | | - the Method Resolution Order and concatenate the __slots__ of each |
874 | | - class found there. (This assumes classes don't modify their |
875 | | - __slots__ attribute to misrepresent their slots after the class is |
876 | | - defined.) |
877 | | - """ |
878 | | - |
879 | | - # Get the value from a cache in the class if possible |
880 | | - names = cls.__dict__.get("__slotnames__") |
881 | | - if names is not None: |
882 | | - return names |
883 | | - |
884 | | - # Not cached -- calculate the value |
885 | | - names = [] |
886 | | - if not hasattr(cls, "__slots__"): |
887 | | - # This class has no slots |
888 | | - pass |
889 | | - else: |
890 | | - # Slots found -- gather slot names from all base classes |
891 | | - for c in cls.__mro__: |
892 | | - if "__slots__" in c.__dict__: |
893 | | - names += [name for name in c.__dict__["__slots__"] |
894 | | - if name not in ("__dict__", "__weakref__")] |
895 | | - |
896 | | - # Cache the outcome in the class if at all possible |
897 | | - try: |
898 | | - cls.__slotnames__ = names |
899 | | - except: |
900 | | - pass # But don't die if we can't |
901 | | - |
902 | | - return names |
903 | | - |
904 | 786 | def _keep_alive(x, memo): |
905 | 787 | """Keeps a reference to the object x in the memo. |
906 | 788 |
|
|
0 commit comments