GeezerVison is showing bugs.python.org — bugs.python.org diff -r d03c8d0a6a73 Include/object.h
--- a/Include/object.h Sat Jun 18 22:09:30 2016 +0300
+++ b/Include/object.h Sat Jun 18 22:59:01 2016 +0300
@@ -578,6 +578,11 @@ PyAPI_FUNC(PyObject *)
*/
PyAPI_FUNC(PyObject *) PyObject_Dir(PyObject *);
+/* Pickle support. */
+#ifndef Py_LIMITED_API
+PyAPI_FUNC(PyObject *) _PyObject_GetState(PyObject *);
+#endif
+
/* Helpers for printing recursive container types */
PyAPI_FUNC(int) Py_ReprEnter(PyObject *);
diff -r d03c8d0a6a73 Lib/_weakrefset.py
--- a/Lib/_weakrefset.py Sat Jun 18 22:09:30 2016 +0300
+++ b/Lib/_weakrefset.py Sat Jun 18 22:59:01 2016 +0300
@@ -3,6 +3,7 @@
# by abc.py to load everything else at startup.
from _weakref import ref
+from copyreg import _getstate
__all__ = ['WeakSet']
@@ -75,8 +76,7 @@ class WeakSet:
return wr in self.data
def __reduce__(self):
- return (self.__class__, (list(self),),
- getattr(self, '__dict__', None))
+ return self.__class__, (list(self),), _getstate(self)
def add(self, item):
if self._pending_removals:
diff -r d03c8d0a6a73 Lib/collections/__init__.py
--- a/Lib/collections/__init__.py Sat Jun 18 22:09:30 2016 +0300
+++ b/Lib/collections/__init__.py Sat Jun 18 22:59:01 2016 +0300
@@ -23,6 +23,7 @@ from _collections_abc import *
import _collections_abc
__all__ += _collections_abc.__all__
+from copyreg import _getstate
from operator import itemgetter as _itemgetter, eq as _eq
from keyword import iskeyword as _iskeyword
import sys as _sys
@@ -260,10 +261,22 @@ class OrderedDict(dict):
def __reduce__(self):
'Return state information for pickling'
- inst_dict = vars(self).copy()
- for k in vars(OrderedDict()):
- inst_dict.pop(k, None)
- return self.__class__, (), inst_dict or None, None, iter(self.items())
+ state = _getstate(self)
+ if state:
+ if isinstance(state, tuple):
+ state, slots = state
+ else:
+ slots = {}
+ state = state.copy()
+ slots = slots.copy()
+ for k in vars(OrderedDict()):
+ state.pop(k, None)
+ slots.pop(k, None)
+ if slots:
+ state = state, slots
+ else:
+ state = state or None
+ return self.__class__, (), state, None, iter(self.items())
def copy(self):
'od.copy() -> a shallow copy of od'
diff -r d03c8d0a6a73 Lib/copyreg.py
--- a/Lib/copyreg.py Sat Jun 18 22:09:30 2016 +0300
+++ b/Lib/copyreg.py Sat Jun 18 22:59:01 2016 +0300
@@ -140,6 +140,27 @@ def _slotnames(cls):
return names
+def _getstate(obj):
+ try:
+ getstate = obj.__getstate__
+ except AttributeError:
+ pass
+ else:
+ return getstate()
+
+ state = getattr(obj, '__dict__', None) or None
+ slotnames = _slotnames(type(obj))
+ if slotnames:
+ slots = {}
+ for name in slotnames:
+ try:
+ slots[name] = getattr(obj, name)
+ except AttributeError:
+ pass # the attribute is not present
+ if slots:
+ state = state, slots
+ return state
+
# A registry of extension codes. This is an ad-hoc compression
# mechanism. Whenever a global reference to , is about
# to be pickled, the (, ) tuple is looked up here to see
diff -r d03c8d0a6a73 Lib/datetime.py
--- a/Lib/datetime.py Sat Jun 18 22:09:30 2016 +0300
+++ b/Lib/datetime.py Sat Jun 18 22:59:01 2016 +0300
@@ -6,6 +6,7 @@ time zone and DST data sources.
import time as _time
import math as _math
+from copyreg import _getstate
def _cmp(x, y):
return 0 if x == y else 1 if x > y else -1
@@ -1005,15 +1006,7 @@ class tzinfo:
args = getinitargs()
else:
args = ()
- getstate = getattr(self, "__getstate__", None)
- if getstate:
- state = getstate()
- else:
- state = getattr(self, "__dict__", None) or None
- if state is None:
- return (self.__class__, args)
- else:
- return (self.__class__, args, state)
+ return (self.__class__, args, _getstate(self))
_tzinfo_class = tzinfo
diff -r d03c8d0a6a73 Lib/email/headerregistry.py
--- a/Lib/email/headerregistry.py Sat Jun 18 22:09:30 2016 +0300
+++ b/Lib/email/headerregistry.py Sat Jun 18 22:59:01 2016 +0300
@@ -12,6 +12,7 @@ from types import MappingProxyType
from email import utils
from email import errors
from email import _header_value_parser as parser
+from copyreg import _getstate
class Address:
@@ -223,7 +224,7 @@ class BaseHeader(str):
self.__class__.__bases__,
str(self),
),
- self.__dict__)
+ _getstate(self))
@classmethod
def _reconstruct(cls, value):
diff -r d03c8d0a6a73 Lib/test/datetimetester.py
--- a/Lib/test/datetimetester.py Sat Jun 18 22:09:30 2016 +0300
+++ b/Lib/test/datetimetester.py Sat Jun 18 22:59:01 2016 +0300
@@ -117,8 +117,8 @@ class PicklableFixedOffset(FixedOffset):
def __init__(self, offset=None, name=None, dstoffset=None):
FixedOffset.__init__(self, offset, name, dstoffset)
- def __getstate__(self):
- return self.__dict__
+class PicklableFixedOffsetWithSlots(PicklableFixedOffset):
+ __slots__ = '_FixedOffset__offset', '_FixedOffset__name', 'spam'
class _TZInfo(tzinfo):
def utcoffset(self, datetime_module):
@@ -180,6 +180,7 @@ class TestTZInfo(unittest.TestCase):
offset = timedelta(minutes=-300)
for otype, args in [
(PicklableFixedOffset, (offset, 'cookie')),
+ (PicklableFixedOffsetWithSlots, (offset, 'cookie')),
(timezone, (offset,)),
(timezone, (offset, "EST"))]:
orig = otype(*args)
@@ -195,6 +196,7 @@ class TestTZInfo(unittest.TestCase):
self.assertIs(type(derived), otype)
self.assertEqual(derived.utcoffset(None), offset)
self.assertEqual(derived.tzname(None), oname)
+ self.assertFalse(hasattr(derived, 'spam'))
def test_issue23600(self):
DSTDIFF = DSTOFFSET = timedelta(hours=1)
diff -r d03c8d0a6a73 Lib/test/test_bytes.py
--- a/Lib/test/test_bytes.py Sat Jun 18 22:09:30 2016 +0300
+++ b/Lib/test/test_bytes.py Sat Jun 18 22:59:01 2016 +0300
@@ -1566,28 +1566,30 @@ class SubclassTest:
def test_pickle(self):
a = self.type2test(b"abcd")
a.x = 10
- a.y = self.type2test(b"efgh")
+ a.z = self.type2test(b"efgh")
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
b = pickle.loads(pickle.dumps(a, proto))
self.assertNotEqual(id(a), id(b))
self.assertEqual(a, b)
self.assertEqual(a.x, b.x)
- self.assertEqual(a.y, b.y)
+ self.assertEqual(a.z, b.z)
self.assertEqual(type(a), type(b))
- self.assertEqual(type(a.y), type(b.y))
+ self.assertEqual(type(a.z), type(b.z))
+ self.assertFalse(hasattr(b, 'y'))
def test_copy(self):
a = self.type2test(b"abcd")
a.x = 10
- a.y = self.type2test(b"efgh")
+ a.z = self.type2test(b"efgh")
for copy_method in (copy.copy, copy.deepcopy):
b = copy_method(a)
self.assertNotEqual(id(a), id(b))
self.assertEqual(a, b)
self.assertEqual(a.x, b.x)
- self.assertEqual(a.y, b.y)
+ self.assertEqual(a.z, b.z)
self.assertEqual(type(a), type(b))
- self.assertEqual(type(a.y), type(b.y))
+ self.assertEqual(type(a.z), type(b.z))
+ self.assertFalse(hasattr(b, 'y'))
test_fromhex = BaseBytesTest.test_fromhex
@@ -1595,6 +1597,9 @@ class SubclassTest:
class ByteArraySubclass(bytearray):
pass
+class ByteArraySubclassWithSlots(bytearray):
+ __slots__ = ('x', 'z', '__dict__')
+
class BytesSubclass(bytes):
pass
@@ -1615,6 +1620,9 @@ class ByteArraySubclassTest(SubclassTest
x = subclass(newarg=4, source=b"abcd")
self.assertEqual(x, b"abcd")
+class ByteArraySubclassWithSlotsTest(SubclassTest, unittest.TestCase):
+ basetype = bytearray
+ type2test = ByteArraySubclassWithSlots
class BytesSubclassTest(SubclassTest, unittest.TestCase):
basetype = bytes
diff -r d03c8d0a6a73 Lib/test/test_deque.py
--- a/Lib/test/test_deque.py Sat Jun 18 22:09:30 2016 +0300
+++ b/Lib/test/test_deque.py Sat Jun 18 22:59:01 2016 +0300
@@ -792,6 +792,9 @@ class TestVariousIteratorArgs(unittest.T
class Deque(deque):
pass
+class DequeWithSlots(deque):
+ __slots__ = ('x', 'y', '__dict__')
+
class DequeWithBadIter(deque):
def __iter__(self):
raise TypeError
@@ -821,40 +824,28 @@ class TestSubclass(unittest.TestCase):
self.assertEqual(len(d), 0)
def test_copy_pickle(self):
+ for cls in Deque, DequeWithSlots:
+ for d in cls('abc'), cls('abcde', maxlen=4):
+ d.x = ['x']
+ d.z = ['z']
- d = Deque('abc')
+ e = d.__copy__()
+ self.assertEqual(type(d), type(e))
+ self.assertEqual(list(d), list(e))
- e = d.__copy__()
- self.assertEqual(type(d), type(e))
- self.assertEqual(list(d), list(e))
+ e = cls(d)
+ self.assertEqual(type(d), type(e))
+ self.assertEqual(list(d), list(e))
- e = Deque(d)
- self.assertEqual(type(d), type(e))
- self.assertEqual(list(d), list(e))
-
- for proto in range(pickle.HIGHEST_PROTOCOL + 1):
- s = pickle.dumps(d, proto)
- e = pickle.loads(s)
- self.assertNotEqual(id(d), id(e))
- self.assertEqual(type(d), type(e))
- self.assertEqual(list(d), list(e))
-
- d = Deque('abcde', maxlen=4)
-
- e = d.__copy__()
- self.assertEqual(type(d), type(e))
- self.assertEqual(list(d), list(e))
-
- e = Deque(d)
- self.assertEqual(type(d), type(e))
- self.assertEqual(list(d), list(e))
-
- for proto in range(pickle.HIGHEST_PROTOCOL + 1):
- s = pickle.dumps(d, proto)
- e = pickle.loads(s)
- self.assertNotEqual(id(d), id(e))
- self.assertEqual(type(d), type(e))
- self.assertEqual(list(d), list(e))
+ for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+ s = pickle.dumps(d, proto)
+ e = pickle.loads(s)
+ self.assertNotEqual(id(d), id(e))
+ self.assertEqual(type(d), type(e))
+ self.assertEqual(list(d), list(e))
+ self.assertEqual(e.x, d.x)
+ self.assertEqual(e.z, d.z)
+ self.assertFalse(hasattr(e, 'y'))
def test_pickle_recursive(self):
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
diff -r d03c8d0a6a73 Lib/test/test_ordered_dict.py
--- a/Lib/test/test_ordered_dict.py Sat Jun 18 22:09:30 2016 +0300
+++ b/Lib/test/test_ordered_dict.py Sat Jun 18 22:59:01 2016 +0300
@@ -262,6 +262,8 @@ class OrderedDictTests:
# and have a repr/eval round-trip
pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
od = OrderedDict(pairs)
+ od.x = ['x']
+ od.z = ['z']
def check(dup):
msg = "\ncopy: %s\nod: %s" % (dup, od)
self.assertIsNot(dup, od, msg)
@@ -270,13 +272,27 @@ class OrderedDictTests:
self.assertEqual(len(dup), len(od))
self.assertEqual(type(dup), type(od))
check(od.copy())
- check(copy.copy(od))
- check(copy.deepcopy(od))
+ dup = copy.copy(od)
+ check(dup)
+ self.assertIs(dup.x, od.x)
+ self.assertIs(dup.z, od.z)
+ self.assertFalse(hasattr(dup, 'y'))
+ dup = copy.deepcopy(od)
+ check(dup)
+ self.assertEqual(dup.x, od.x)
+ self.assertIsNot(dup.x, od.x)
+ self.assertEqual(dup.z, od.z)
+ self.assertIsNot(dup.z, od.z)
+ self.assertFalse(hasattr(dup, 'y'))
# pickle directly pulls the module, so we have to fake it
with replaced_module('collections', self.module):
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
with self.subTest(proto=proto):
- check(pickle.loads(pickle.dumps(od, proto)))
+ dup = pickle.loads(pickle.dumps(od, proto))
+ check(dup)
+ self.assertEqual(dup.x, od.x)
+ self.assertEqual(dup.z, od.z)
+ self.assertFalse(hasattr(dup, 'y'))
check(eval(repr(od)))
update_test = OrderedDict()
update_test.update(od)
@@ -690,6 +706,23 @@ class CPythonOrderedDictSubclassTests(CP
pass
+class PurePythonOrderedDictWithSlotsCopyingTests(unittest.TestCase):
+
+ module = py_coll
+ class OrderedDict(py_coll.OrderedDict):
+ __slots__ = ('x', 'y')
+ test_copying = OrderedDictTests.test_copying
+
+
[email protected](c_coll, 'requires the C version of the collections module')
+class CPythonOrderedDictWithSlotsCopyingTests(unittest.TestCase):
+
+ module = c_coll
+ class OrderedDict(c_coll.OrderedDict):
+ __slots__ = ('x', 'y')
+ test_copying = OrderedDictTests.test_copying
+
+
class PurePythonGeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
@classmethod
diff -r d03c8d0a6a73 Lib/test/test_set.py
--- a/Lib/test/test_set.py Sat Jun 18 22:09:30 2016 +0300
+++ b/Lib/test/test_set.py Sat Jun 18 22:59:01 2016 +0300
@@ -227,14 +227,17 @@ class TestJointOps:
def test_pickling(self):
for i in range(pickle.HIGHEST_PROTOCOL + 1):
+ if type(self.s) not in (set, frozenset):
+ self.s.x = ['x']
+ self.s.z = ['z']
p = pickle.dumps(self.s, i)
dup = pickle.loads(p)
self.assertEqual(self.s, dup, "%s != %s" % (self.s, dup))
if type(self.s) not in (set, frozenset):
- self.s.x = 10
- p = pickle.dumps(self.s, i)
- dup = pickle.loads(p)
self.assertEqual(self.s.x, dup.x)
+ self.assertEqual(self.s.z, dup.z)
+ self.assertFalse(hasattr(self.s, 'y'))
+ del self.s.x, self.s.z
def test_iterator_pickling(self):
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
@@ -769,6 +772,21 @@ class TestFrozenSetSubclass(TestFrozenSe
# All empty frozenset subclass instances should have different ids
self.assertEqual(len(set(map(id, efs))), len(efs))
+
+class SetSubclassWithSlots(set):
+ __slots__ = ('x', 'y', '__dict__')
+
+class TestSetSubclassWithSlots(unittest.TestCase):
+ thetype = SetSubclassWithSlots
+ setUp = TestJointOps.setUp
+ test_pickling = TestJointOps.test_pickling
+
+class FrozenSetSubclassWithSlots(frozenset):
+ __slots__ = ('x', 'y', '__dict__')
+
+class TestFrozenSetSubclassWithSlots(TestSetSubclassWithSlots):
+ thetype = FrozenSetSubclassWithSlots
+
# Tests taken from test_sets.py =============================================
empty_set = set()
diff -r d03c8d0a6a73 Lib/test/test_weakset.py
--- a/Lib/test/test_weakset.py Sat Jun 18 22:09:30 2016 +0300
+++ b/Lib/test/test_weakset.py Sat Jun 18 22:59:01 2016 +0300
@@ -1,5 +1,6 @@
import unittest
from weakref import WeakSet
+import copy
import string
from collections import UserString as ustr
import gc
@@ -13,6 +14,12 @@ class RefCycle:
def __init__(self):
self.cycle = self
+class WeakSetSubclass(WeakSet):
+ pass
+
+class WeakSetWithSlots(WeakSet):
+ __slots__ = ('x', 'y')
+
class TestWeakSet(unittest.TestCase):
@@ -434,6 +441,30 @@ class TestWeakSet(unittest.TestCase):
self.assertGreaterEqual(n2, 0)
self.assertLessEqual(n2, n1)
+ def test_copying(self):
+ for cls in WeakSet, WeakSetWithSlots:
+ s = cls(self.items)
+ s.x = ['x']
+ s.z = ['z']
+
+ dup = copy.copy(s)
+ self.assertIsInstance(dup, cls)
+ self.assertEqual(dup, s)
+ self.assertIsNot(dup, s)
+ self.assertIs(dup.x, s.x)
+ self.assertIs(dup.z, s.z)
+ self.assertFalse(hasattr(dup, 'y'))
+
+ dup = copy.deepcopy(s)
+ self.assertIsInstance(dup, cls)
+ self.assertEqual(dup, s)
+ self.assertIsNot(dup, s)
+ self.assertEqual(dup.x, s.x)
+ self.assertIsNot(dup.x, s.x)
+ self.assertEqual(dup.z, s.z)
+ self.assertIsNot(dup.z, s.z)
+ self.assertFalse(hasattr(dup, 'y'))
+
if __name__ == "__main__":
unittest.main()
diff -r d03c8d0a6a73 Modules/_collectionsmodule.c
--- a/Modules/_collectionsmodule.c Sat Jun 18 22:09:30 2016 +0300
+++ b/Modules/_collectionsmodule.c Sat Jun 18 22:59:01 2016 +0300
@@ -1296,30 +1296,24 @@ deque_traverse(dequeobject *deque, visit
static PyObject *
deque_reduce(dequeobject *deque)
{
- PyObject *dict, *it;
- _Py_IDENTIFIER(__dict__);
+ PyObject *state, *it;
- dict = _PyObject_GetAttrId((PyObject *)deque, &PyId___dict__);
- if (dict == NULL) {
- if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
- return NULL;
- }
- PyErr_Clear();
- dict = Py_None;
- Py_INCREF(dict);
+ state = _PyObject_GetState((PyObject *)deque);
+ if (state == NULL) {
+ return NULL;
}
it = PyObject_GetIter((PyObject *)deque);
if (it == NULL) {
- Py_DECREF(dict);
+ Py_DECREF(state);
return NULL;
}
if (deque->maxlen < 0) {
- return Py_BuildValue("O()NN", Py_TYPE(deque), dict, it);
+ return Py_BuildValue("O()NN", Py_TYPE(deque), state, it);
}
else {
- return Py_BuildValue("O(()n)NN", Py_TYPE(deque), deque->maxlen, dict, it);
+ return Py_BuildValue("O(()n)NN", Py_TYPE(deque), deque->maxlen, state, it);
}
}
diff -r d03c8d0a6a73 Modules/_datetimemodule.c
--- a/Modules/_datetimemodule.c Sat Jun 18 22:09:30 2016 +0300
+++ b/Modules/_datetimemodule.c Sat Jun 18 22:59:01 2016 +0300
@@ -3077,9 +3077,8 @@ static PyObject *
tzinfo_reduce(PyObject *self)
{
PyObject *args, *state, *tmp;
- PyObject *getinitargs, *getstate;
+ PyObject *getinitargs;
_Py_IDENTIFIER(__getinitargs__);
- _Py_IDENTIFIER(__getstate__);
tmp = PyTuple_New(0);
if (tmp == NULL)
@@ -3100,34 +3099,13 @@ tzinfo_reduce(PyObject *self)
Py_INCREF(args);
}
- getstate = _PyObject_GetAttrId(self, &PyId___getstate__);
- if (getstate != NULL) {
- state = PyObject_CallObject(getstate, tmp);
- Py_DECREF(getstate);
- if (state == NULL) {
- Py_DECREF(args);
- Py_DECREF(tmp);
- return NULL;
- }
+ state = _PyObject_GetState(self);
+ if (state == NULL) {
+ Py_DECREF(args);
+ return NULL;
}
- else {
- PyObject **dictptr;
- PyErr_Clear();
- state = Py_None;
- dictptr = _PyObject_GetDictPtr(self);
- if (dictptr && *dictptr && PyDict_Size(*dictptr))
- state = *dictptr;
- Py_INCREF(state);
- }
-
- Py_DECREF(tmp);
-
- if (state == Py_None) {
- Py_DECREF(state);
- return Py_BuildValue("(ON)", Py_TYPE(self), args);
- }
- else
- return Py_BuildValue("(ONN)", Py_TYPE(self), args, state);
+
+ return Py_BuildValue("(ONN)", Py_TYPE(self), args, state);
}
static PyMethodDef tzinfo_methods[] = {
diff -r d03c8d0a6a73 Objects/bytearrayobject.c
--- a/Objects/bytearrayobject.c Sat Jun 18 22:09:30 2016 +0300
+++ b/Objects/bytearrayobject.c Sat Jun 18 22:59:01 2016 +0300
@@ -2002,35 +2002,26 @@ bytearray_hex(PyBytesObject *self)
static PyObject *
_common_reduce(PyByteArrayObject *self, int proto)
{
- PyObject *dict;
- _Py_IDENTIFIER(__dict__);
- char *buf;
+ PyObject *state;
+ const char *buf;
- dict = _PyObject_GetAttrId((PyObject *)self, &PyId___dict__);
- if (dict == NULL) {
- PyErr_Clear();
- dict = Py_None;
- Py_INCREF(dict);
+ state = _PyObject_GetState((PyObject *)self);
+ if (state == NULL) {
+ return NULL;
}
+ if (!Py_SIZE(self)) {
+ return Py_BuildValue("(O()N)", Py_TYPE(self), state);
+ }
buf = PyByteArray_AS_STRING(self);
if (proto < 3) {
/* use str based reduction for backwards compatibility with Python 2.x */
- PyObject *latin1;
- if (Py_SIZE(self))
- latin1 = PyUnicode_DecodeLatin1(buf, Py_SIZE(self), NULL);
- else
- latin1 = PyUnicode_FromString("");
- return Py_BuildValue("(O(Ns)N)", Py_TYPE(self), latin1, "latin-1", dict);
+ PyObject *latin1 = PyUnicode_DecodeLatin1(buf, Py_SIZE(self), NULL);
+ return Py_BuildValue("(O(Ns)N)", Py_TYPE(self), latin1, "latin-1", state);
}
else {
/* use more efficient byte based reduction */
- if (Py_SIZE(self)) {
- return Py_BuildValue("(O(y#)N)", Py_TYPE(self), buf, Py_SIZE(self), dict);
- }
- else {
- return Py_BuildValue("(O()N)", Py_TYPE(self), dict);
- }
+ return Py_BuildValue("(O(y#)N)", Py_TYPE(self), buf, Py_SIZE(self), state);
}
}
diff -r d03c8d0a6a73 Objects/odictobject.c
--- a/Objects/odictobject.c Sat Jun 18 22:09:30 2016 +0300
+++ b/Objects/odictobject.c Sat Jun 18 22:59:01 2016 +0300
@@ -953,25 +953,14 @@ PyDoc_STRVAR(odict_reduce__doc__, "Retur
static PyObject *
odict_reduce(register PyODictObject *od)
{
- _Py_IDENTIFIER(__dict__);
_Py_IDENTIFIER(items);
- PyObject *dict = NULL, *result = NULL;
+ PyObject *state, *result = NULL;
PyObject *items_iter, *items, *args = NULL;
/* capture any instance state */
- dict = _PyObject_GetAttrId((PyObject *)od, &PyId___dict__);
- if (dict == NULL)
+ state = _PyObject_GetState((PyObject *)od);
+ if (state == NULL)
goto Done;
- else {
- /* od.__dict__ isn't necessarily a dict... */
- Py_ssize_t dict_len = PyObject_Length(dict);
- if (dict_len == -1)
- goto Done;
- if (!dict_len) {
- /* nothing to pickle in od.__dict__ */
- Py_CLEAR(dict);
- }
- }
/* build the result */
args = PyTuple_New(0);
@@ -987,11 +976,11 @@ odict_reduce(register PyODictObject *od)
if (items_iter == NULL)
goto Done;
- result = PyTuple_Pack(5, Py_TYPE(od), args, dict ? dict : Py_None, Py_None, items_iter);
+ result = PyTuple_Pack(5, Py_TYPE(od), args, state, Py_None, items_iter);
Py_DECREF(items_iter);
Done:
- Py_XDECREF(dict);
+ Py_DECREF(state);
Py_XDECREF(args);
return result;
diff -r d03c8d0a6a73 Objects/setobject.c
--- a/Objects/setobject.c Sat Jun 18 22:09:30 2016 +0300
+++ b/Objects/setobject.c Sat Jun 18 22:59:01 2016 +0300
@@ -1957,8 +1957,7 @@ If the element is not a member, do nothi
static PyObject *
set_reduce(PySetObject *so)
{
- PyObject *keys=NULL, *args=NULL, *result=NULL, *dict=NULL;
- _Py_IDENTIFIER(__dict__);
+ PyObject *keys=NULL, *args=NULL, *result=NULL, *state=NULL;
keys = PySequence_List((PyObject *)so);
if (keys == NULL)
@@ -1966,17 +1965,14 @@ set_reduce(PySetObject *so)
args = PyTuple_Pack(1, keys);
if (args == NULL)
goto done;
- dict = _PyObject_GetAttrId((PyObject *)so, &PyId___dict__);
- if (dict == NULL) {
- PyErr_Clear();
- dict = Py_None;
- Py_INCREF(dict);
- }
- result = PyTuple_Pack(3, Py_TYPE(so), args, dict);
+ state = _PyObject_GetState((PyObject *)so);
+ if (state == NULL)
+ goto done;
+ result = PyTuple_Pack(3, Py_TYPE(so), args, state);
done:
Py_XDECREF(args);
Py_XDECREF(keys);
- Py_XDECREF(dict);
+ Py_XDECREF(state);
return result;
}
diff -r d03c8d0a6a73 Objects/typeobject.c
--- a/Objects/typeobject.c Sat Jun 18 22:09:30 2016 +0300
+++ b/Objects/typeobject.c Sat Jun 18 22:59:01 2016 +0300
@@ -3827,7 +3827,7 @@ Py_LOCAL(PyObject *)
}
Py_LOCAL(PyObject *)
-_PyObject_GetState(PyObject *obj, int required)
+getstate(PyObject *obj, int required)
{
PyObject *state;
PyObject *getstate;
@@ -3972,6 +3972,12 @@ Py_LOCAL(PyObject *)
return state;
}
+PyObject *
+_PyObject_GetState(PyObject *obj)
+{
+ return getstate(obj, 0);
+}
+
Py_LOCAL(int)
_PyObject_GetNewArguments(PyObject *obj, PyObject **args, PyObject **kwargs)
{
@@ -4186,8 +4192,7 @@ reduce_newobj(PyObject *obj)
}
}
- state = _PyObject_GetState(obj,
- !hasargs && !PyList_Check(obj) && !PyDict_Check(obj));
+ state = getstate(obj, !hasargs && !PyList_Check(obj) && !PyDict_Check(obj));
if (state == NULL) {
Py_DECREF(newobj);
Py_DECREF(newargs);
|