Merged revisions 58886-58929 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r58892 | guido.van.rossum | 2007-11-06 15:32:56 -0800 (Tue, 06 Nov 2007) | 2 lines

  Add missing "return NULL" in overflow check in PyObject_Repr().
........
  r58893 | raymond.hettinger | 2007-11-06 17:13:09 -0800 (Tue, 06 Nov 2007) | 1 line

  Fix marshal's incorrect handling of subclasses of builtin types (backport candidate).
........
  r58895 | raymond.hettinger | 2007-11-06 18:26:17 -0800 (Tue, 06 Nov 2007) | 1 line

  Optimize dict.fromkeys() with dict inputs.  Useful for resetting bag/muliset counts for example.
........
  r58896 | raymond.hettinger | 2007-11-06 18:45:46 -0800 (Tue, 06 Nov 2007) | 1 line

  Add build option for faster loop execution.
........
  r58900 | nick.coghlan | 2007-11-07 03:57:51 -0800 (Wed, 07 Nov 2007) | 1 line

  Add missing NEWS entry
........
  r58905 | christian.heimes | 2007-11-07 09:50:54 -0800 (Wed, 07 Nov 2007) | 1 line

  Backported fix for bug #1392 from py3k branch r58903.
........
  r58906 | christian.heimes | 2007-11-07 10:30:22 -0800 (Wed, 07 Nov 2007) | 1 line

  Backport of Guido's review of my patch.
........
  r58908 | raymond.hettinger | 2007-11-07 18:52:43 -0800 (Wed, 07 Nov 2007) | 1 line

  Add set.isdisjoint()
........
  r58915 | raymond.hettinger | 2007-11-08 10:47:51 -0800 (Thu, 08 Nov 2007) | 1 line

  Reposition the decref (spotted by eagle-eye norwitz).
........
  r58920 | georg.brandl | 2007-11-09 04:31:43 -0800 (Fri, 09 Nov 2007) | 2 lines

  Fix seealso link to sets docs. Do not merge to Py3k.
........
  r58921 | georg.brandl | 2007-11-09 05:08:48 -0800 (Fri, 09 Nov 2007) | 2 lines

  Fix misleading example.
........
  r58923 | georg.brandl | 2007-11-09 09:33:23 -0800 (Fri, 09 Nov 2007) | 3 lines

  Correct a comment about testing methods - nowadays most
  tests don't run directly on import.
........
  r58924 | martin.v.loewis | 2007-11-09 14:56:30 -0800 (Fri, 09 Nov 2007) | 2 lines

  Add Amaury Forgeot d'Arc.
........
  r58925 | raymond.hettinger | 2007-11-09 15:14:44 -0800 (Fri, 09 Nov 2007) | 1 line

  Optimize common case for dict.fromkeys().
........
  r58927 | raymond.hettinger | 2007-11-09 17:54:03 -0800 (Fri, 09 Nov 2007) | 1 line

  Use a freelist to speed-up block allocation and deallocation in collections.deque().
........
  r58929 | guido.van.rossum | 2007-11-10 14:12:24 -0800 (Sat, 10 Nov 2007) | 3 lines

  Issue 1416.  Add getter, setter, deleter methods to properties that can be
  used as decorators to create fully-populated properties.
........
This commit is contained in:
Guido van Rossum 2007-11-10 23:39:45 +00:00
parent 06cfe95237
commit 58da931da9
16 changed files with 349 additions and 39 deletions

View File

@ -44,12 +44,6 @@ and dictionaries are only supported as long as the values contained therein are
themselves supported; and recursive lists and dictionaries should not be written
(they will cause infinite loops).
.. warning::
Some unsupported types such as subclasses of builtins will appear to marshal
and unmarshal correctly, but in fact, their type will change and the
additional subclass functionality and instance attributes will be lost.
.. warning::
On machines where C's ``long int`` type has more than 32 bits (such as the

View File

@ -1418,6 +1418,13 @@ operations:
Test *x* for non-membership in *s*.
.. method:: set.isdisjoint(other)
Return True if the set has no elements in common with *other*.
Sets are disjoint if and only if their interesection is the empty set.
.. versionadded:: 2.6
.. method:: set.issubset(other)
set <= other

View File

@ -507,8 +507,9 @@ list or clear it entirely::
The built-in function :func:`len` also applies to lists::
>>> a = ['a', 'b', 'c', 'd']
>>> len(a)
8
4
It is possible to nest lists (create lists containing other lists), for
example::

View File

@ -588,10 +588,9 @@ def runtest_inner(test, generate, verbose, quiet,
abstest = 'test.' + test
the_package = __import__(abstest, globals(), locals(), [])
the_module = getattr(the_package, test)
# Most tests run to completion simply as a side-effect of
# being imported. For the benefit of tests that can't run
# that way (like test_threaded_import), explicitly invoke
# their test_main() function (if it exists).
# Old tests run to completion simply as a side-effect of
# being imported. For tests based on unittest or doctest,
# explicitly invoke their test_main() function (if it exists).
indirect_test = getattr(the_module, "test_main", None)
if indirect_test is not None:
indirect_test()

View File

@ -1984,6 +1984,71 @@ def properties():
p = property(_testcapi.test_with_docstring)
def properties_plus():
class C:
foo = property(doc="hello")
@foo.getter
def foo(self):
return self._foo
@foo.setter
def foo(self, value):
self._foo = abs(value)
@foo.deleter
def foo(self):
del self._foo
c = C()
assert C.foo.__doc__ == "hello"
assert not hasattr(c, "foo")
c.foo = -42
assert c.foo == 42
del c.foo
assert not hasattr(c, "foo")
class D(C):
@C.foo.deleter
def foo(self):
try:
del self._foo
except AttributeError:
pass
d = D()
d.foo = 24
assert d.foo == 24
del d.foo
del d.foo
class E:
@property
def foo(self):
return self._foo
@foo.setter
def foo (self, value):
raise RuntimeError
@foo.setter
@foo.deleter
def foo(self, value=None):
if value is None:
del self._foo
else:
self._foo = abs(value)
e = E()
e.foo = -42
assert e.foo == 42
del e.foo
class F(E):
@E.foo.deleter
def foo(self):
del self._foo
@foo.setter
def foo(self, value):
self._foo = max(0, value)
f = F()
f.foo = -10
assert f.foo == 0
del f.foo
def supers():
if verbose: print("Testing super...")

View File

@ -236,6 +236,10 @@ class DictTest(unittest.TestCase):
self.assertRaises(Exc, baddict2.fromkeys, [1])
# test fast path for dictionary inputs
d = dict(zip(range(6), range(6)))
self.assertEqual(dict.fromkeys(d, 0), dict(zip(range(6), [0]*6)))
def test_copy(self):
d = {1:1, 2:2, 3:3}
self.assertEqual(d.copy(), {1:1, 2:2, 3:3})

View File

@ -188,6 +188,17 @@ class BugsTestCase(unittest.TestCase):
last.append([0])
self.assertRaises(ValueError, marshal.dumps, head)
def test_exact_type_match(self):
# Former bug:
# >>> class Int(int): pass
# >>> type(loads(dumps(Int())))
# <type 'int'>
for typ in (int, float, complex, tuple, list, dict, set, frozenset):
# Note: str sublclasses are not tested because they get handled
# by marshal's routines for objects supporting the buffer API.
subtyp = type('subtyp', (typ,), {})
self.assertRaises(ValueError, marshal.dumps, subtyp())
def test_main():
test_support.run_unittest(IntTestCase,
FloatTestCase,

View File

@ -102,6 +102,20 @@ class TestJointOps(unittest.TestCase):
self.assertEqual(self.thetype('abcba').intersection(C('ccb')), set('bc'))
self.assertEqual(self.thetype('abcba').intersection(C('ef')), set(''))
def test_isdisjoint(self):
def f(s1, s2):
'Pure python equivalent of isdisjoint()'
return not set(s1).intersection(s2)
for larg in '', 'a', 'ab', 'abc', 'ababac', 'cdc', 'cc', 'efgfe', 'ccb', 'ef':
s1 = self.thetype(larg)
for rarg in '', 'a', 'ab', 'abc', 'ababac', 'cdc', 'cc', 'efgfe', 'ccb', 'ef':
for C in set, frozenset, dict.fromkeys, str, list, tuple:
s2 = C(rarg)
actual = s1.isdisjoint(s2)
expected = f(s1, s2)
self.assertEqual(actual, expected)
self.assert_(actual is True or actual is False)
def test_and(self):
i = self.s.intersection(self.otherword)
self.assertEqual(self.s & set(self.otherword), i)
@ -701,6 +715,18 @@ class TestBasicOps(unittest.TestCase):
result = empty_set & self.set
self.assertEqual(result, empty_set)
def test_self_isdisjoint(self):
result = self.set.isdisjoint(self.set)
self.assertEqual(result, not self.set)
def test_empty_isdisjoint(self):
result = self.set.isdisjoint(empty_set)
self.assertEqual(result, True)
def test_isdisjoint_empty(self):
result = empty_set.isdisjoint(self.set)
self.assertEqual(result, True)
def test_self_symmetric_difference(self):
result = self.set ^ self.set
self.assertEqual(result, empty_set)
@ -879,6 +905,22 @@ class TestBinaryOps(unittest.TestCase):
result = self.set & set([8])
self.assertEqual(result, empty_set)
def test_isdisjoint_subset(self):
result = self.set.isdisjoint(set((2, 4)))
self.assertEqual(result, False)
def test_isdisjoint_superset(self):
result = self.set.isdisjoint(set([2, 4, 6, 8]))
self.assertEqual(result, False)
def test_isdisjoint_overlap(self):
result = self.set.isdisjoint(set([3, 4, 5]))
self.assertEqual(result, False)
def test_isdisjoint_non_overlap(self):
result = self.set.isdisjoint(set([8]))
self.assertEqual(result, True)
def test_sym_difference_subset(self):
result = self.set ^ set((2, 4))
self.assertEqual(result, set([6]))
@ -1497,11 +1539,14 @@ class TestVariousIteratorArgs(unittest.TestCase):
def test_inline_methods(self):
s = set('november')
for data in ("123", "", range(1000), ('do', 1.2), range(2000,2200,5), 'december'):
for meth in (s.union, s.intersection, s.difference, s.symmetric_difference):
for meth in (s.union, s.intersection, s.difference, s.symmetric_difference, s.isdisjoint):
for g in (G, I, Ig, L, R):
expected = meth(data)
actual = meth(G(data))
self.assertEqual(sorted(actual, key=repr), sorted(expected, key=repr))
if isinstance(expected, bool):
self.assertEqual(actual, expected)
else:
self.assertEqual(sorted(actual, key=repr), sorted(expected, key=repr))
self.assertRaises(TypeError, meth, X(s))
self.assertRaises(TypeError, meth, N(s))
self.assertRaises(ZeroDivisionError, meth, E(s))

View File

@ -17,6 +17,9 @@ the format to accommodate documentation needs as they arise.
Permissions History
-------------------
- Amaury Forgeot d'Arc was given SVN access on 9 November 2007 by MvL,
for general contributions to Python.
- Christian Heimes was given SVN access on 31 October 2007 by MvL,
for general contributions to Python.

View File

@ -51,6 +51,10 @@ typedef struct BLOCK {
PyObject *data[BLOCKLEN];
} block;
#define MAXFREEBLOCKS 10
static int numfreeblocks = 0;
static block *freeblocks[MAXFREEBLOCKS];
static block *
newblock(block *leftlink, block *rightlink, int len) {
block *b;
@ -66,16 +70,32 @@ newblock(block *leftlink, block *rightlink, int len) {
"cannot add more blocks to the deque");
return NULL;
}
b = PyMem_Malloc(sizeof(block));
if (b == NULL) {
PyErr_NoMemory();
return NULL;
if (numfreeblocks) {
numfreeblocks -= 1;
b = freeblocks[numfreeblocks];
} else {
b = PyMem_Malloc(sizeof(block));
if (b == NULL) {
PyErr_NoMemory();
return NULL;
}
}
b->leftlink = leftlink;
b->rightlink = rightlink;
return b;
}
void
freeblock(block *b)
{
if (numfreeblocks < MAXFREEBLOCKS) {
freeblocks[numfreeblocks] = b;
numfreeblocks++;
} else {
PyMem_Free(b);
}
}
typedef struct {
PyObject_HEAD
block *leftblock;
@ -161,7 +181,7 @@ deque_pop(dequeobject *deque, PyObject *unused)
} else {
prevblock = deque->rightblock->leftlink;
assert(deque->leftblock != deque->rightblock);
PyMem_Free(deque->rightblock);
freeblock(deque->rightblock);
prevblock->rightlink = NULL;
deque->rightblock = prevblock;
deque->rightindex = BLOCKLEN - 1;
@ -198,7 +218,7 @@ deque_popleft(dequeobject *deque, PyObject *unused)
} else {
assert(deque->leftblock != deque->rightblock);
prevblock = deque->leftblock->rightlink;
PyMem_Free(deque->leftblock);
freeblock(deque->leftblock);
assert(prevblock != NULL);
prevblock->leftlink = NULL;
deque->leftblock = prevblock;
@ -559,7 +579,7 @@ deque_dealloc(dequeobject *deque)
if (deque->leftblock != NULL) {
deque_clear(deque);
assert(deque->leftblock != NULL);
PyMem_Free(deque->leftblock);
freeblock(deque->leftblock);
}
deque->leftblock = NULL;
deque->rightblock = NULL;

View File

@ -1099,6 +1099,60 @@ static PyMemberDef property_members[] = {
{0}
};
PyDoc_STRVAR(getter_doc,
"Descriptor to change the getter on a property.");
PyObject *
property_getter(PyObject *self, PyObject *getter)
{
Py_XDECREF(((propertyobject *)self)->prop_get);
if (getter == Py_None)
getter = NULL;
Py_XINCREF(getter);
((propertyobject *)self)->prop_get = getter;
Py_INCREF(self);
return self;
}
PyDoc_STRVAR(setter_doc,
"Descriptor to change the setter on a property.\n");
PyObject *
property_setter(PyObject *self, PyObject *setter)
{
Py_XDECREF(((propertyobject *)self)->prop_set);
if (setter == Py_None)
setter = NULL;
Py_XINCREF(setter);
((propertyobject *)self)->prop_set = setter;
Py_INCREF(self);
return self;
}
PyDoc_STRVAR(deleter_doc,
"Descriptor to change the deleter on a property.");
PyObject *
property_deleter(PyObject *self, PyObject *deleter)
{
Py_XDECREF(((propertyobject *)self)->prop_del);
if (deleter == Py_None)
deleter = NULL;
Py_XINCREF(deleter);
((propertyobject *)self)->prop_del = deleter;
Py_INCREF(self);
return self;
}
static PyMethodDef property_methods[] = {
{"getter", property_getter, METH_O, getter_doc},
{"setter", property_setter, METH_O, setter_doc},
{"deleter", property_deleter, METH_O, deleter_doc},
{0}
};
static void
property_dealloc(PyObject *self)
@ -1251,7 +1305,7 @@ PyTypeObject PyProperty_Type = {
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
property_methods, /* tp_methods */
property_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */

View File

@ -1175,6 +1175,25 @@ dict_fromkeys(PyObject *cls, PyObject *args)
if (d == NULL)
return NULL;
if (PyDict_CheckExact(d) && PyDict_CheckExact(seq)) {
PyDictObject *mp = (PyDictObject *)d;
PyObject *oldvalue;
Py_ssize_t pos = 0;
PyObject *key;
long hash;
if (dictresize(mp, PySet_GET_SIZE(seq)))
return NULL;
while (_PyDict_Next(seq, &pos, &key, &oldvalue, &hash)) {
Py_INCREF(key);
Py_INCREF(value);
if (insertdict(mp, key, hash, value))
return NULL;
}
return d;
}
if (PyDict_CheckExact(d) && PyAnySet_CheckExact(seq)) {
PyDictObject *mp = (PyDictObject *)d;
Py_ssize_t pos = 0;
@ -1199,19 +1218,24 @@ dict_fromkeys(PyObject *cls, PyObject *args)
return NULL;
}
for (;;) {
key = PyIter_Next(it);
if (key == NULL) {
if (PyErr_Occurred())
if (PyDict_CheckExact(d)) {
while ((key = PyIter_Next(it)) != NULL) {
status = PyDict_SetItem(d, key, value);
Py_DECREF(key);
if (status < 0)
goto Fail;
}
} else {
while ((key = PyIter_Next(it)) != NULL) {
status = PyObject_SetItem(d, key, value);
Py_DECREF(key);
if (status < 0)
goto Fail;
break;
}
status = PyObject_SetItem(d, key, value);
Py_DECREF(key);
if (status < 0)
goto Fail;
}
if (PyErr_Occurred())
goto Fail;
Py_DECREF(it);
return d;

View File

@ -1314,6 +1314,73 @@ set_iand(PySetObject *so, PyObject *other)
return (PyObject *)so;
}
static PyObject *
set_isdisjoint(PySetObject *so, PyObject *other)
{
PyObject *key, *it, *tmp;
if ((PyObject *)so == other) {
if (PySet_GET_SIZE(so) == 0)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
if (PyAnySet_CheckExact(other)) {
Py_ssize_t pos = 0;
setentry *entry;
if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) {
tmp = (PyObject *)so;
so = (PySetObject *)other;
other = tmp;
}
while (set_next((PySetObject *)other, &pos, &entry)) {
int rv = set_contains_entry(so, entry);
if (rv == -1)
return NULL;
if (rv)
Py_RETURN_FALSE;
}
Py_RETURN_TRUE;
}
it = PyObject_GetIter(other);
if (it == NULL)
return NULL;
while ((key = PyIter_Next(it)) != NULL) {
int rv;
setentry entry;
long hash = PyObject_Hash(key);
if (hash == -1) {
Py_DECREF(key);
Py_DECREF(it);
return NULL;
}
entry.hash = hash;
entry.key = key;
rv = set_contains_entry(so, &entry);
Py_DECREF(key);
if (rv == -1) {
Py_DECREF(it);
return NULL;
}
if (rv) {
Py_DECREF(it);
Py_RETURN_FALSE;
}
}
Py_DECREF(it);
if (PyErr_Occurred())
return NULL;
Py_RETURN_TRUE;
}
PyDoc_STRVAR(isdisjoint_doc,
"Return True if two sets have a null intersection.");
static int
set_difference_update_internal(PySetObject *so, PyObject *other)
{
@ -1839,6 +1906,8 @@ static PyMethodDef set_methods[] = {
intersection_doc},
{"intersection_update",(PyCFunction)set_intersection_update, METH_O,
intersection_update_doc},
{"isdisjoint", (PyCFunction)set_isdisjoint, METH_O,
isdisjoint_doc},
{"issubset", (PyCFunction)set_issubset, METH_O,
issubset_doc},
{"issuperset", (PyCFunction)set_issuperset, METH_O,
@ -1960,6 +2029,8 @@ static PyMethodDef frozenset_methods[] = {
difference_doc},
{"intersection",(PyCFunction)set_intersection, METH_O,
intersection_doc},
{"isdisjoint", (PyCFunction)set_isdisjoint, METH_O,
isdisjoint_doc},
{"issubset", (PyCFunction)set_issubset, METH_O,
issubset_doc},
{"issuperset", (PyCFunction)set_issuperset, METH_O,

View File

@ -611,6 +611,7 @@ PyString_Repr(PyObject *obj, int smartquotes)
if (newsize > PY_SSIZE_T_MAX || (newsize-3) / 4 != length) {
PyErr_SetString(PyExc_OverflowError,
"bytes object is too large to make repr");
return NULL;
}
v = PyUnicode_FromUnicode(NULL, newsize);
if (v == NULL) {

View File

@ -2011,7 +2011,18 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
PREDICTED_WITH_ARG(JUMP_ABSOLUTE);
case JUMP_ABSOLUTE:
JUMPTO(oparg);
#if FAST_LOOPS
/* Enabling this path speeds-up all while and for-loops by bypassing
the per-loop checks for signals. By default, this should be turned-off
because it prevents detection of a control-break in tight loops like
"while 1: pass". Compile with this option turned-on when you need
the speed-up and do not need break checking inside tight loops (ones
that contain only instructions ending with goto fast_next_opcode).
*/
goto fast_next_opcode;
#else
continue;
#endif
case GET_ITER:
/* before: [obj]; after [getiter(obj)] */

View File

@ -147,7 +147,7 @@ w_object(PyObject *v, WFILE *p)
else if (v == Py_True) {
w_byte(TYPE_TRUE, p);
}
else if (PyLong_Check(v)) {
else if (PyLong_CheckExact(v)) {
long x = PyLong_AsLong(v);
if ((x == -1) && PyErr_Occurred()) {
PyLongObject *ob = (PyLongObject *)v;
@ -175,7 +175,7 @@ w_object(PyObject *v, WFILE *p)
}
}
}
else if (PyFloat_Check(v)) {
else if (PyFloat_CheckExact(v)) {
if (p->version > 1) {
unsigned char buf[8];
if (_PyFloat_Pack8(PyFloat_AsDouble(v),
@ -196,7 +196,7 @@ w_object(PyObject *v, WFILE *p)
}
}
#ifndef WITHOUT_COMPLEX
else if (PyComplex_Check(v)) {
else if (PyComplex_CheckExact(v)) {
if (p->version > 1) {
unsigned char buf[8];
if (_PyFloat_Pack8(PyComplex_RealAsDouble(v),
@ -228,7 +228,7 @@ w_object(PyObject *v, WFILE *p)
}
}
#endif
else if (PyString_Check(v)) {
else if (PyString_CheckExact(v)) {
w_byte(TYPE_STRING, p);
n = PyString_GET_SIZE(v);
if (n > INT_MAX) {
@ -240,7 +240,7 @@ w_object(PyObject *v, WFILE *p)
w_long((long)n, p);
w_string(PyString_AS_STRING(v), (int)n, p);
}
else if (PyUnicode_Check(v)) {
else if (PyUnicode_CheckExact(v)) {
PyObject *utf8;
utf8 = PyUnicode_AsUTF8String(v);
if (utf8 == NULL) {
@ -259,7 +259,7 @@ w_object(PyObject *v, WFILE *p)
w_string(PyString_AS_STRING(utf8), (int)n, p);
Py_DECREF(utf8);
}
else if (PyTuple_Check(v)) {
else if (PyTuple_CheckExact(v)) {
w_byte(TYPE_TUPLE, p);
n = PyTuple_Size(v);
w_long((long)n, p);
@ -267,7 +267,7 @@ w_object(PyObject *v, WFILE *p)
w_object(PyTuple_GET_ITEM(v, i), p);
}
}
else if (PyList_Check(v)) {
else if (PyList_CheckExact(v)) {
w_byte(TYPE_LIST, p);
n = PyList_GET_SIZE(v);
w_long((long)n, p);
@ -275,7 +275,7 @@ w_object(PyObject *v, WFILE *p)
w_object(PyList_GET_ITEM(v, i), p);
}
}
else if (PyDict_Check(v)) {
else if (PyDict_CheckExact(v)) {
Py_ssize_t pos;
PyObject *key, *value;
w_byte(TYPE_DICT, p);
@ -287,7 +287,7 @@ w_object(PyObject *v, WFILE *p)
}
w_object((PyObject *)NULL, p);
}
else if (PyAnySet_Check(v)) {
else if (PyAnySet_CheckExact(v)) {
PyObject *value, *it;
if (PyObject_TypeCheck(v, &PySet_Type))