[Python-checkins] r54412 - in python/trunk: Doc/ref/ref3.tex Lib/test/test_descr.py Misc/ACKS Misc/NEWS Objects/typeobject.c
ziga.seilnacht
python-checkins at python.org
Fri Mar 16 12:59:44 CET 2007
Author: ziga.seilnacht
Date: Fri Mar 16 12:59:38 2007
New Revision: 54412
Modified:
python/trunk/Doc/ref/ref3.tex
python/trunk/Lib/test/test_descr.py
python/trunk/Misc/ACKS
python/trunk/Misc/NEWS
python/trunk/Objects/typeobject.c
Log:
Patch #1623563: allow __class__ assignment for classes with __slots__.
The old and the new class are still required to have the same slot
names, but the order in which they are specified is not relevant.
Modified: python/trunk/Doc/ref/ref3.tex
==============================================================================
--- python/trunk/Doc/ref/ref3.tex (original)
+++ python/trunk/Doc/ref/ref3.tex Fri Mar 16 12:59:38 2007
@@ -1593,6 +1593,11 @@
Mappings may also be used; however, in the future, special meaning may
be assigned to the values corresponding to each key.
+\item \var{__class__} assignment works only if both classes have the
+same \var{__slots__}.
+\versionchanged[Previously, \var{__class__} assignment raised an error
+if either new or old class had \var{__slots__}]{2.6}
+
\end{itemize}
@@ -2223,3 +2228,6 @@
Python \keyword{with} statement.}
\end{seealso}
+
+
+
Modified: python/trunk/Lib/test/test_descr.py
==============================================================================
--- python/trunk/Lib/test/test_descr.py (original)
+++ python/trunk/Lib/test/test_descr.py Fri Mar 16 12:59:38 2007
@@ -2853,6 +2853,51 @@
cant(o, type(1))
cant(o, type(None))
del o
+ class G(object):
+ __slots__ = ["a", "b"]
+ class H(object):
+ __slots__ = ["b", "a"]
+ try:
+ unicode
+ except NameError:
+ class I(object):
+ __slots__ = ["a", "b"]
+ else:
+ class I(object):
+ __slots__ = [unicode("a"), unicode("b")]
+ class J(object):
+ __slots__ = ["c", "b"]
+ class K(object):
+ __slots__ = ["a", "b", "d"]
+ class L(H):
+ __slots__ = ["e"]
+ class M(I):
+ __slots__ = ["e"]
+ class N(J):
+ __slots__ = ["__weakref__"]
+ class P(J):
+ __slots__ = ["__dict__"]
+ class Q(J):
+ pass
+ class R(J):
+ __slots__ = ["__dict__", "__weakref__"]
+
+ for cls, cls2 in ((G, H), (G, I), (I, H), (Q, R), (R, Q)):
+ x = cls()
+ x.a = 1
+ x.__class__ = cls2
+ verify(x.__class__ is cls2,
+ "assigning %r as __class__ for %r silently failed" % (cls2, x))
+ vereq(x.a, 1)
+ x.__class__ = cls
+ verify(x.__class__ is cls,
+ "assigning %r as __class__ for %r silently failed" % (cls, x))
+ vereq(x.a, 1)
+ for cls in G, J, K, L, M, N, P, R, list, Int:
+ for cls2 in G, J, K, L, M, N, P, R, list, Int:
+ if cls is cls2:
+ continue
+ cant(cls(), cls2)
def setdict():
if verbose: print "Testing __dict__ assignment..."
Modified: python/trunk/Misc/ACKS
==============================================================================
--- python/trunk/Misc/ACKS (original)
+++ python/trunk/Misc/ACKS Fri Mar 16 12:59:38 2007
@@ -276,6 +276,7 @@
Ivan Herman
Jürgen Hermann
Gary Herron
+Thomas Herve
Bernhard Herzog
Magnus L. Hetland
Raymond Hettinger
Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS (original)
+++ python/trunk/Misc/NEWS Fri Mar 16 12:59:38 2007
@@ -12,6 +12,9 @@
Core and builtins
-----------------
+- Patch #1623563: allow __class__ assignment for classes with __slots__.
+ The old and the new class are still required to have the same slot names.
+
- Patch #1642547: Fix an error/crash when encountering syntax errors in
complex if statements.
Modified: python/trunk/Objects/typeobject.c
==============================================================================
--- python/trunk/Objects/typeobject.c (original)
+++ python/trunk/Objects/typeobject.c Fri Mar 16 12:59:38 2007
@@ -1844,8 +1844,11 @@
}
}
- /* Copy slots into yet another tuple, demangling names */
- newslots = PyTuple_New(nslots - add_dict - add_weak);
+ /* Copy slots into a list, mangle names and sort them.
+ Sorted names are needed for __class__ assignment.
+ Convert them back to tuple at the end.
+ */
+ newslots = PyList_New(nslots - add_dict - add_weak);
if (newslots == NULL)
goto bad_slots;
for (i = j = 0; i < nslots; i++) {
@@ -1858,13 +1861,23 @@
tmp =_Py_Mangle(name, tmp);
if (!tmp)
goto bad_slots;
- PyTuple_SET_ITEM(newslots, j, tmp);
+ PyList_SET_ITEM(newslots, j, tmp);
j++;
}
assert(j == nslots - add_dict - add_weak);
nslots = j;
Py_DECREF(slots);
- slots = newslots;
+ if (PyList_Sort(newslots) == -1) {
+ Py_DECREF(bases);
+ Py_DECREF(newslots);
+ return NULL;
+ }
+ slots = PyList_AsTuple(newslots);
+ Py_DECREF(newslots);
+ if (slots == NULL) {
+ Py_DECREF(bases);
+ return NULL;
+ }
/* Secondary bases may provide weakrefs or dict */
if (nbases > 1 &&
@@ -2481,6 +2494,7 @@
{
PyTypeObject *base = a->tp_base;
Py_ssize_t size;
+ PyObject *slots_a, *slots_b;
if (base != b->tp_base)
return 0;
@@ -2491,6 +2505,15 @@
size += sizeof(PyObject *);
if (a->tp_weaklistoffset == size && b->tp_weaklistoffset == size)
size += sizeof(PyObject *);
+
+ /* Check slots compliance */
+ slots_a = ((PyHeapTypeObject *)a)->ht_slots;
+ slots_b = ((PyHeapTypeObject *)b)->ht_slots;
+ if (slots_a && slots_b) {
+ if (PyObject_Compare(slots_a, slots_b) != 0)
+ return 0;
+ size += sizeof(PyObject *) * PyTuple_GET_SIZE(slots_a);
+ }
return size == a->tp_basicsize && size == b->tp_basicsize;
}
More information about the Python-checkins
mailing list