Commit 4eeea17b authored by Georg Brandl's avatar Georg Brandl

Merged revisions...

Merged revisions 64002-64003,64012,64036-64037,64047,64050-64052,64054-64055,64066,64071 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r64002 | travis.oliphant | 2008-06-07 00:33:21 +0200 (Sat, 07 Jun 2008) | 1 line

  Add long double check support to configure test.
........
  r64003 | travis.oliphant | 2008-06-07 00:39:47 +0200 (Sat, 07 Jun 2008) | 1 line

  Remove locking part of new buffer protocol.
........
  r64012 | facundo.batista | 2008-06-07 15:36:36 +0200 (Sat, 07 Jun 2008) | 4 lines


  Finished bug #2451.  Fixed the retrying part to make it
  more robust.
........
  r64036 | georg.brandl | 2008-06-08 10:54:40 +0200 (Sun, 08 Jun 2008) | 2 lines

  #3028: tokenize passes the physical line.
........
  r64037 | georg.brandl | 2008-06-08 10:59:38 +0200 (Sun, 08 Jun 2008) | 2 lines

  Argh, I read it wrong. Reverted 64036 and added a clarifying remark.
........
  r64047 | raymond.hettinger | 2008-06-09 03:28:30 +0200 (Mon, 09 Jun 2008) | 1 line

  Issue3065:  Fixed pickling of named tuples.  Added tests.
........
  r64050 | raymond.hettinger | 2008-06-09 08:54:45 +0200 (Mon, 09 Jun 2008) | 1 line

  Issue #2138: Add math.factorial().
........
  r64051 | raymond.hettinger | 2008-06-09 10:33:37 +0200 (Mon, 09 Jun 2008) | 1 line

  Let set.union() and set.update() accept multiple inputs.
........
  r64052 | raymond.hettinger | 2008-06-09 11:29:17 +0200 (Mon, 09 Jun 2008) | 1 line

  Address double-rounding scenarios by setting all variables to long doubles.
........
  r64054 | raymond.hettinger | 2008-06-09 13:24:47 +0200 (Mon, 09 Jun 2008) | 1 line

  Unhappy buildbots.  Revert 64052.  Long doubles have unexpected effects on some builds.
........
  r64055 | raymond.hettinger | 2008-06-09 15:07:27 +0200 (Mon, 09 Jun 2008) | 1 line

  Let set.intersection() and set.intersection_update() take multiple input arguments.
........
  r64066 | robert.schuppenies | 2008-06-10 12:10:31 +0200 (Tue, 10 Jun 2008) | 2 lines

  Issue 3048: Fixed sys.getsizeof for unicode objects.
........
  r64071 | thomas.heller | 2008-06-10 16:07:12 +0200 (Tue, 10 Jun 2008) | 3 lines

  NEWS entry for:
  Add an optional 'offset' parameter to byref, defaulting to zero.
........
parent f7b15984
...@@ -519,6 +519,9 @@ Example: ...@@ -519,6 +519,9 @@ Example:
if kwds: if kwds:
raise ValueError('Got unexpected field names: %r' % kwds.keys()) raise ValueError('Got unexpected field names: %r' % kwds.keys())
return result return result
<BLANKLINE>
def __getnewargs__(self):
return tuple(self)
<BLANKLINE> <BLANKLINE>
x = property(itemgetter(0)) x = property(itemgetter(0))
y = property(itemgetter(1)) y = property(itemgetter(1))
......
...@@ -41,6 +41,10 @@ Number-theoretic and representation functions: ...@@ -41,6 +41,10 @@ Number-theoretic and representation functions:
Return the absolute value of *x*. Return the absolute value of *x*.
.. function:: factorial(x)
Return *x* factorial. Raises :exc:`ValueError` if *x* is not intergral or
is negative.
.. function:: floor(x) .. function:: floor(x)
......
...@@ -1501,16 +1501,22 @@ The constructors for both classes work the same: ...@@ -1501,16 +1501,22 @@ The constructors for both classes work the same:
Test whether the set is a true superset of *other*, that is, ``set >= Test whether the set is a true superset of *other*, that is, ``set >=
other and set != other``. other and set != other``.
.. method:: union(other) .. method:: union(other, ...)
set | other set | other | ...
Return a new set with elements from both sets. Return a new set with elements from both sets.
.. method:: intersection(other) .. versionchanged:: 2.6
set & other Accepts multiple input iterables.
.. method:: intersection(other, ...)
set & other & ...
Return a new set with elements common to both sets. Return a new set with elements common to both sets.
.. versionchanged:: 2.6
Accepts multiple input iterables.
.. method:: difference(other) .. method:: difference(other)
set - other set - other
...@@ -1562,16 +1568,22 @@ The constructors for both classes work the same: ...@@ -1562,16 +1568,22 @@ The constructors for both classes work the same:
The following table lists operations available for :class:`set` that do not The following table lists operations available for :class:`set` that do not
apply to immutable instances of :class:`frozenset`: apply to immutable instances of :class:`frozenset`:
.. method:: update(other) .. method:: update(other, ...)
set |= other set |= other | ...
Update the set, adding elements from *other*. Update the set, adding elements from *other*.
.. method:: intersection_update(other) .. versionchanged:: 2.6
set &= other Accepts multiple input iterables.
.. method:: intersection_update(other, ...)
set &= other & ...
Update the set, keeping only elements found in it and *other*. Update the set, keeping only elements found in it and *other*.
.. versionchanged:: 2.6
Accepts multiple input iterables.
.. method:: difference_update(other) .. method:: difference_update(other)
set -= other set -= other
......
:mod:`tokenize` --- Tokenizer for Python source :mod:`tokenize` --- Tokenizer for Python source
=============================================== ===============================================
...@@ -15,7 +14,6 @@ colorizers for on-screen displays. ...@@ -15,7 +14,6 @@ colorizers for on-screen displays.
The primary entry point is a :term:`generator`: The primary entry point is a :term:`generator`:
.. function:: tokenize(readline) .. function:: tokenize(readline)
The :func:`tokenize` generator requires one argument, *readline*, which The :func:`tokenize` generator requires one argument, *readline*, which
...@@ -28,11 +26,11 @@ The primary entry point is a :term:`generator`: ...@@ -28,11 +26,11 @@ The primary entry point is a :term:`generator`:
token string; a 2-tuple ``(srow, scol)`` of ints specifying the row and token string; a 2-tuple ``(srow, scol)`` of ints specifying the row and
column where the token begins in the source; a 2-tuple ``(erow, ecol)`` of column where the token begins in the source; a 2-tuple ``(erow, ecol)`` of
ints specifying the row and column where the token ends in the source; and ints specifying the row and column where the token ends in the source; and
the line on which the token was found. The line passed is the *logical* the line on which the token was found. The line passed (the last tuple item)
line; continuation lines are included. is the *logical* line; continuation lines are included.
tokenize determines the source encoding of the file by looking for a utf-8 :func:`tokenize` determines the source encoding of the file by looking for a
bom or encoding cookie, according to :pep:`263`. UTF-8 BOM or encoding cookie, according to :pep:`263`.
All constants from the :mod:`token` module are also exported from All constants from the :mod:`token` module are also exported from
......
...@@ -87,7 +87,9 @@ def namedtuple(typename, field_names, verbose=False): ...@@ -87,7 +87,9 @@ def namedtuple(typename, field_names, verbose=False):
result = self._make(map(kwds.pop, %(field_names)r, self)) result = self._make(map(kwds.pop, %(field_names)r, self))
if kwds: if kwds:
raise ValueError('Got unexpected field names: %%r' %% kwds.keys()) raise ValueError('Got unexpected field names: %%r' %% kwds.keys())
return result \n\n''' % locals() return result \n
def __getnewargs__(self):
return tuple(self) \n\n''' % locals()
for i, name in enumerate(field_names): for i, name in enumerate(field_names):
template += ' %s = property(itemgetter(%d))\n' % (name, i) template += ' %s = property(itemgetter(%d))\n' % (name, i)
if verbose: if verbose:
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
import unittest, doctest import unittest, doctest
from test import support from test import support
from collections import namedtuple from collections import namedtuple
import pickle, copy
from collections import Hashable, Iterable, Iterator from collections import Hashable, Iterable, Iterator
from collections import Sized, Container, Callable from collections import Sized, Container, Callable
from collections import Set, MutableSet from collections import Set, MutableSet
...@@ -10,6 +11,7 @@ from collections import Mapping, MutableMapping ...@@ -10,6 +11,7 @@ from collections import Mapping, MutableMapping
from collections import Sequence, MutableSequence from collections import Sequence, MutableSequence
from collections import ByteString from collections import ByteString
TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests
class TestNamedTuple(unittest.TestCase): class TestNamedTuple(unittest.TestCase):
...@@ -111,7 +113,7 @@ class TestNamedTuple(unittest.TestCase): ...@@ -111,7 +113,7 @@ class TestNamedTuple(unittest.TestCase):
self.assertEqual(Dot(1)._replace(d=999), (999,)) self.assertEqual(Dot(1)._replace(d=999), (999,))
self.assertEqual(Dot(1)._fields, ('d',)) self.assertEqual(Dot(1)._fields, ('d',))
# n = 10000 # n = 5000
n = 254 # SyntaxError: more than 255 arguments: n = 254 # SyntaxError: more than 255 arguments:
import string, random import string, random
names = list(set(''.join([random.choice(string.ascii_letters) names = list(set(''.join([random.choice(string.ascii_letters)
...@@ -134,6 +136,23 @@ class TestNamedTuple(unittest.TestCase): ...@@ -134,6 +136,23 @@ class TestNamedTuple(unittest.TestCase):
self.assertEqual(b2, tuple(b2_expected)) self.assertEqual(b2, tuple(b2_expected))
self.assertEqual(b._fields, tuple(names)) self.assertEqual(b._fields, tuple(names))
def test_pickle(self):
p = TestNT(x=10, y=20, z=30)
for module in (pickle,):
loads = getattr(module, 'loads')
dumps = getattr(module, 'dumps')
for protocol in -1, 0, 1, 2:
q = loads(dumps(p, protocol))
self.assertEqual(p, q)
self.assertEqual(p._fields, q._fields)
def test_copy(self):
p = TestNT(x=10, y=20, z=30)
for copier in copy.copy, copy.deepcopy:
q = copier(p)
self.assertEqual(p, q)
self.assertEqual(p._fields, q._fields)
class TestOneTrickPonyABCs(unittest.TestCase): class TestOneTrickPonyABCs(unittest.TestCase):
def test_Hashable(self): def test_Hashable(self):
......
...@@ -6,6 +6,7 @@ import unittest ...@@ -6,6 +6,7 @@ import unittest
import math import math
import os import os
import sys import sys
import random
eps = 1E-05 eps = 1E-05
NAN = float('nan') NAN = float('nan')
...@@ -274,6 +275,20 @@ class MathTests(unittest.TestCase): ...@@ -274,6 +275,20 @@ class MathTests(unittest.TestCase):
self.ftest('fabs(0)', math.fabs(0), 0) self.ftest('fabs(0)', math.fabs(0), 0)
self.ftest('fabs(1)', math.fabs(1), 1) self.ftest('fabs(1)', math.fabs(1), 1)
def testFactorial(self):
def fact(n):
result = 1
for i in range(1, int(n)+1):
result *= i
return result
values = list(range(10)) + [50, 100, 500]
random.shuffle(values)
for x in range(10):
for cast in (int, float):
self.assertEqual(math.factorial(cast(x)), fact(x), (x, fact(x), math.factorial(x)))
self.assertRaises(ValueError, math.factorial, -1)
self.assertRaises(ValueError, math.factorial, math.pi)
def testFloor(self): def testFloor(self):
self.assertRaises(TypeError, math.floor) self.assertRaises(TypeError, math.floor)
self.assertEquals(int, type(math.floor(0.5))) self.assertEquals(int, type(math.floor(0.5)))
......
...@@ -79,6 +79,7 @@ class TestJointOps(unittest.TestCase): ...@@ -79,6 +79,7 @@ class TestJointOps(unittest.TestCase):
self.assertEqual(self.thetype('abcba').union(C('efgfe')), set('abcefg')) self.assertEqual(self.thetype('abcba').union(C('efgfe')), set('abcefg'))
self.assertEqual(self.thetype('abcba').union(C('ccb')), set('abc')) self.assertEqual(self.thetype('abcba').union(C('ccb')), set('abc'))
self.assertEqual(self.thetype('abcba').union(C('ef')), set('abcef')) self.assertEqual(self.thetype('abcba').union(C('ef')), set('abcef'))
self.assertEqual(self.thetype('abcba').union(C('ef'), C('fg')), set('abcefg'))
def test_or(self): def test_or(self):
i = self.s.union(self.otherword) i = self.s.union(self.otherword)
...@@ -103,6 +104,7 @@ class TestJointOps(unittest.TestCase): ...@@ -103,6 +104,7 @@ class TestJointOps(unittest.TestCase):
self.assertEqual(self.thetype('abcba').intersection(C('efgfe')), set('')) self.assertEqual(self.thetype('abcba').intersection(C('efgfe')), set(''))
self.assertEqual(self.thetype('abcba').intersection(C('ccb')), set('bc')) self.assertEqual(self.thetype('abcba').intersection(C('ccb')), set('bc'))
self.assertEqual(self.thetype('abcba').intersection(C('ef')), set('')) self.assertEqual(self.thetype('abcba').intersection(C('ef')), set(''))
self.assertEqual(self.thetype('abcba').intersection(C('cbcf'), C('bag')), set('b'))
def test_isdisjoint(self): def test_isdisjoint(self):
def f(s1, s2): def f(s1, s2):
...@@ -410,6 +412,12 @@ class TestSet(TestJointOps): ...@@ -410,6 +412,12 @@ class TestSet(TestJointOps):
s = self.thetype('abcba') s = self.thetype('abcba')
self.assertEqual(s.update(C(p)), None) self.assertEqual(s.update(C(p)), None)
self.assertEqual(s, set(q)) self.assertEqual(s, set(q))
for p in ('cdc', 'efgfe', 'ccb', 'ef', 'abcda'):
q = 'ahi'
for C in set, frozenset, dict.fromkeys, str, list, tuple:
s = self.thetype('abcba')
self.assertEqual(s.update(C(p), C(q)), None)
self.assertEqual(s, set(s) | set(p) | set(q))
def test_ior(self): def test_ior(self):
self.s |= set(self.otherword) self.s |= set(self.otherword)
...@@ -431,6 +439,11 @@ class TestSet(TestJointOps): ...@@ -431,6 +439,11 @@ class TestSet(TestJointOps):
s = self.thetype('abcba') s = self.thetype('abcba')
self.assertEqual(s.intersection_update(C(p)), None) self.assertEqual(s.intersection_update(C(p)), None)
self.assertEqual(s, set(q)) self.assertEqual(s, set(q))
ss = 'abcba'
s = self.thetype(ss)
t = 'cbc'
self.assertEqual(s.intersection_update(C(p), C(t)), None)
self.assertEqual(s, set('abcba')&set(p)&set(t))
def test_iand(self): def test_iand(self):
self.s &= set(self.otherword) self.s &= set(self.otherword)
......
...@@ -386,11 +386,14 @@ class SizeofTest(unittest.TestCase): ...@@ -386,11 +386,14 @@ class SizeofTest(unittest.TestCase):
self.file.close() self.file.close()
test.support.unlink(test.support.TESTFN) test.support.unlink(test.support.TESTFN)
def check_sizeof(self, o, size): def check_sizeof(self, o, size, size2=None):
"""Check size of o. Possible are size and optionally size2)."""
result = sys.getsizeof(o) result = sys.getsizeof(o)
msg = 'wrong size for %s: got %d, expected %d' \ msg = 'wrong size for %s: got %d, expected ' % (type(o), result)
% (type(o), result, size) if (size2 != None) and (result != size):
self.assertEqual(result, size, msg) self.assertEqual(result, size2, msg + str(size2))
else:
self.assertEqual(result, size, msg + str(size))
def align(self, value): def align(self, value):
mod = value % self.p mod = value % self.p
...@@ -486,6 +489,24 @@ class SizeofTest(unittest.TestCase): ...@@ -486,6 +489,24 @@ class SizeofTest(unittest.TestCase):
# list # list
self.check_sizeof([], h + l + p + l) self.check_sizeof([], h + l + p + l)
self.check_sizeof([1, 2, 3], h + l + p + l + 3*l) self.check_sizeof([1, 2, 3], h + l + p + l + 3*l)
# unicode
import math
usize = math.log(sys.maxunicode + 1, 2) / 8
samples = ['', '1'*100]
# we need to test for both sizes, because we don't know if the string
# has been cached
for s in samples:
basicsize = h + l + p + l + l + p + usize * (len(s) + 1)
defenc = bytes(s, 'ascii')
self.check_sizeof(s, basicsize,
size2=basicsize + sys.getsizeof(defenc))
# trigger caching encoded version as bytes object
try:
getattr(sys, s)
except AttributeError:
pass
finally:
self.check_sizeof(s, basicsize + sys.getsizeof(defenc))
h += l h += l
# long # long
...@@ -495,9 +516,6 @@ class SizeofTest(unittest.TestCase): ...@@ -495,9 +516,6 @@ class SizeofTest(unittest.TestCase):
self.check_sizeof(32768, h + self.align(2) + 2) self.check_sizeof(32768, h + self.align(2) + 2)
self.check_sizeof(32768*32768-1, h + self.align(2) + 2) self.check_sizeof(32768*32768-1, h + self.align(2) + 2)
self.check_sizeof(32768*32768, h + self.align(2) + 4) self.check_sizeof(32768*32768, h + self.align(2) + 4)
# XXX add Unicode support
# self.check_sizeof('', h + l + self.align(i + 1))
# self.check_sizeof('abc', h + l + self.align(i + 1) + 3)
def test_main(): def test_main():
......
...@@ -11,19 +11,25 @@ import os ...@@ -11,19 +11,25 @@ import os
import mimetools import mimetools
def _urlopen_with_retry(host, *args, **kwargs): def _retry_thrice(func, exc, *args, **kwargs):
# Connecting to remote hosts is flaky. Make it more robust
# by retrying the connection several times.
for i in range(3): for i in range(3):
try: try:
return urllib2.urlopen(host, *args, **kwargs) return func(*args, **kwargs)
except urllib2.URLError as e: except exc as e:
last_exc = e last_exc = e
continue continue
except: except:
raise raise
raise last_exc raise last_exc
def _wrap_with_retry_thrice(func, exc):
def wrapped(*args, **kwargs):
return _retry_thrice(func, exc, *args, **kwargs)
return wrapped
# Connecting to remote hosts is flaky. Make it more robust by retrying
# the connection several times.
_urlopen_with_retry = _wrap_with_retry_thrice(urllib2.urlopen, urllib2.URLError)
class AuthTests(unittest.TestCase): class AuthTests(unittest.TestCase):
...@@ -114,7 +120,7 @@ class OtherNetworkTests(unittest.TestCase): ...@@ -114,7 +120,7 @@ class OtherNetworkTests(unittest.TestCase):
'file:'+sanepathname2url(os.path.abspath(TESTFN)), 'file:'+sanepathname2url(os.path.abspath(TESTFN)),
('file:///nonsensename/etc/passwd', None, urllib2.URLError), ('file:///nonsensename/etc/passwd', None, urllib2.URLError),
] ]
self._test_urls(urls, self._extra_handlers(), urllib2.urlopen) self._test_urls(urls, self._extra_handlers(), retry=True)
finally: finally:
os.remove(TESTFN) os.remove(TESTFN)
...@@ -146,13 +152,15 @@ class OtherNetworkTests(unittest.TestCase): ...@@ -146,13 +152,15 @@ class OtherNetworkTests(unittest.TestCase):
## self._test_urls(urls, self._extra_handlers()+[bauth, dauth]) ## self._test_urls(urls, self._extra_handlers()+[bauth, dauth])
def _test_urls(self, urls, handlers, urlopen=_urlopen_with_retry): def _test_urls(self, urls, handlers, retry=True):
import socket import socket
import time import time
import logging import logging
debug = logging.getLogger("test_urllib2").debug debug = logging.getLogger("test_urllib2").debug
urllib2.install_opener(urllib2.build_opener(*handlers)) urlopen = urllib2.build_opener(*handlers).open
if retry:
urlopen = _wrap_with_retry_thrice(urlopen, urllib2.URLError)
for url in urls: for url in urls:
if isinstance(url, tuple): if isinstance(url, tuple):
......
...@@ -567,6 +567,54 @@ PyDoc_STRVAR(math_sum_doc, ...@@ -567,6 +567,54 @@ PyDoc_STRVAR(math_sum_doc,
Return an accurate floating point sum of values in the iterable.\n\ Return an accurate floating point sum of values in the iterable.\n\
Assumes IEEE-754 floating point arithmetic."); Assumes IEEE-754 floating point arithmetic.");
static PyObject *
math_factorial(PyObject *self, PyObject *arg)
{
long i, x;
PyObject *result, *iobj, *newresult;
if (PyFloat_Check(arg)) {
double dx = PyFloat_AS_DOUBLE((PyFloatObject *)arg);
if (dx != floor(dx)) {
PyErr_SetString(PyExc_ValueError,
"factorial() only accepts integral values");
return NULL;
}
}
x = PyLong_AsLong(arg);
if (x == -1 && PyErr_Occurred())
return NULL;
if (x < 0) {
PyErr_SetString(PyExc_ValueError,
"factorial() not defined for negative values");
return NULL;
}
result = (PyObject *)PyLong_FromLong(1);
if (result == NULL)
return NULL;
for (i=1 ; i<=x ; i++) {
iobj = (PyObject *)PyLong_FromLong(i);
if (iobj == NULL)
goto error;
newresult = PyNumber_Multiply(result, iobj);
Py_DECREF(iobj);
if (newresult == NULL)
goto error;
Py_DECREF(result);
result = newresult;
}
return result;
error:
Py_DECREF(result);
Py_XDECREF(iobj);
return NULL;
}
PyDoc_STRVAR(math_factorial_doc, "Return n!");
static PyObject * static PyObject *
math_trunc(PyObject *self, PyObject *number) math_trunc(PyObject *self, PyObject *number)
{ {
...@@ -1022,6 +1070,7 @@ static PyMethodDef math_methods[] = { ...@@ -1022,6 +1070,7 @@ static PyMethodDef math_methods[] = {
{"degrees", math_degrees, METH_O, math_degrees_doc}, {"degrees", math_degrees, METH_O, math_degrees_doc},
{"exp", math_exp, METH_O, math_exp_doc}, {"exp", math_exp, METH_O, math_exp_doc},
{"fabs", math_fabs, METH_O, math_fabs_doc}, {"fabs", math_fabs, METH_O, math_fabs_doc},
{"factorial", math_factorial, METH_O, math_factorial_doc},
{"floor", math_floor, METH_O, math_floor_doc}, {"floor", math_floor, METH_O, math_floor_doc},
{"fmod", math_fmod, METH_VARARGS, math_fmod_doc}, {"fmod", math_fmod, METH_VARARGS, math_fmod_doc},
{"frexp", math_frexp, METH_O, math_frexp_doc}, {"frexp", math_frexp, METH_O, math_frexp_doc},
......
...@@ -959,15 +959,20 @@ set_update_internal(PySetObject *so, PyObject *other) ...@@ -959,15 +959,20 @@ set_update_internal(PySetObject *so, PyObject *other)
} }
static PyObject * static PyObject *
set_update(PySetObject *so, PyObject *other) set_update(PySetObject *so, PyObject *args)
{ {
if (set_update_internal(so, other) == -1) Py_ssize_t i;
return NULL;
for (i=0 ; i<PyTuple_GET_SIZE(args) ; i++) {
PyObject *other = PyTuple_GET_ITEM(args, i);
if (set_update_internal(so, other) == -1)
return NULL;
}
Py_RETURN_NONE; Py_RETURN_NONE;
} }
PyDoc_STRVAR(update_doc, PyDoc_STRVAR(update_doc,
"Update a set with the union of itself and another."); "Update a set with the union of itself and others.");
static PyObject * static PyObject *
make_new_set(PyTypeObject *type, PyObject *iterable) make_new_set(PyTypeObject *type, PyObject *iterable)
...@@ -1148,35 +1153,53 @@ set_clear(PySetObject *so) ...@@ -1148,35 +1153,53 @@ set_clear(PySetObject *so)
PyDoc_STRVAR(clear_doc, "Remove all elements from this set."); PyDoc_STRVAR(clear_doc, "Remove all elements from this set.");
static PyObject * static PyObject *
set_union(PySetObject *so, PyObject *other) set_union(PySetObject *so, PyObject *args)
{ {
PySetObject *result; PySetObject *result;
PyObject *other;
Py_ssize_t i;
result = (PySetObject *)set_copy(so); result = (PySetObject *)set_copy(so);
if (result == NULL) if (result == NULL)
return NULL; return NULL;
if ((PyObject *)so == other)
return (PyObject *)result; for (i=0 ; i<PyTuple_GET_SIZE(args) ; i++) {
if (set_update_internal(result, other) == -1) { other = PyTuple_GET_ITEM(args, i);
Py_DECREF(result); if ((PyObject *)so == other)
return NULL; return (PyObject *)result;
if (set_update_internal(result, other) == -1) {
Py_DECREF(result);
return NULL;
}
} }
return (PyObject *)result; return (PyObject *)result;
} }
PyDoc_STRVAR(union_doc, PyDoc_STRVAR(union_doc,
"Return the union of two sets as a new set.\n\ "Return the union of sets as a new set.\n\
\n\ \n\
(i.e. all elements that are in either set.)"); (i.e. all elements that are in either set.)");
static PyObject * static PyObject *
set_or(PySetObject *so, PyObject *other) set_or(PySetObject *so, PyObject *other)
{ {
PySetObject *result;
if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) { if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) {
Py_INCREF(Py_NotImplemented); Py_INCREF(Py_NotImplemented);
return Py_NotImplemented; return Py_NotImplemented;
} }
return set_union(so, other);
result = (PySetObject *)set_copy(so);
if (result == NULL)
return NULL;
if ((PyObject *)so == other)
return (PyObject *)result;
if (set_update_internal(result, other) == -1) {
Py_DECREF(result);
return NULL;
}
return (PyObject *)result;
} }
static PyObject * static PyObject *
...@@ -1275,6 +1298,26 @@ set_intersection(PySetObject *so, PyObject *other) ...@@ -1275,6 +1298,26 @@ set_intersection(PySetObject *so, PyObject *other)
return (PyObject *)result; return (PyObject *)result;
} }
static PyObject *
set_intersection_multi(PySetObject *so, PyObject *args)
{
Py_ssize_t i;
PyObject *result = (PyObject *)so;
Py_INCREF(so);
for (i=0 ; i<PyTuple_GET_SIZE(args) ; i++) {
PyObject *other = PyTuple_GET_ITEM(args, i);
PyObject *newresult = set_intersection((PySetObject *)result, other);
if (newresult == NULL) {
Py_DECREF(result);
return NULL;
}
Py_DECREF(result);
result = newresult;
}
return result;
}
PyDoc_STRVAR(intersection_doc, PyDoc_STRVAR(intersection_doc,
"Return the intersection of two sets as a new set.\n\ "Return the intersection of two sets as a new set.\n\
\n\ \n\
...@@ -1293,6 +1336,19 @@ set_intersection_update(PySetObject *so, PyObject *other) ...@@ -1293,6 +1336,19 @@ set_intersection_update(PySetObject *so, PyObject *other)
Py_RETURN_NONE; Py_RETURN_NONE;
} }
static PyObject *
set_intersection_update_multi(PySetObject *so, PyObject *args)
{
PyObject *tmp;
tmp = set_intersection_multi(so, args);
if (tmp == NULL)
return NULL;
set_swap_bodies(so, (PySetObject *)tmp);
Py_DECREF(tmp);
Py_RETURN_NONE;
}
PyDoc_STRVAR(intersection_update_doc, PyDoc_STRVAR(intersection_update_doc,
"Update a set with the intersection of itself and another."); "Update a set with the intersection of itself and another.");
...@@ -1911,9 +1967,9 @@ static PyMethodDef set_methods[] = { ...@@ -1911,9 +1967,9 @@ static PyMethodDef set_methods[] = {
difference_doc}, difference_doc},
{"difference_update", (PyCFunction)set_difference_update, METH_O, {"difference_update", (PyCFunction)set_difference_update, METH_O,
difference_update_doc}, difference_update_doc},
{"intersection",(PyCFunction)set_intersection, METH_O, {"intersection",(PyCFunction)set_intersection_multi, METH_VARARGS,
intersection_doc}, intersection_doc},
{"intersection_update",(PyCFunction)set_intersection_update, METH_O, {"intersection_update",(PyCFunction)set_intersection_update_multi, METH_VARARGS,
intersection_update_doc}, intersection_update_doc},
{"isdisjoint", (PyCFunction)set_isdisjoint, METH_O, {"isdisjoint", (PyCFunction)set_isdisjoint, METH_O,
isdisjoint_doc}, isdisjoint_doc},
...@@ -1935,9 +1991,9 @@ static PyMethodDef set_methods[] = { ...@@ -1935,9 +1991,9 @@ static PyMethodDef set_methods[] = {
{"test_c_api", (PyCFunction)test_c_api, METH_NOARGS, {"test_c_api", (PyCFunction)test_c_api, METH_NOARGS,
test_c_api_doc}, test_c_api_doc},
#endif #endif
{"union", (PyCFunction)set_union, METH_O, {"union", (PyCFunction)set_union, METH_VARARGS,
union_doc}, union_doc},
{"update", (PyCFunction)set_update, METH_O, {"update", (PyCFunction)set_update, METH_VARARGS,
update_doc}, update_doc},
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };
...@@ -2036,7 +2092,7 @@ static PyMethodDef frozenset_methods[] = { ...@@ -2036,7 +2092,7 @@ static PyMethodDef frozenset_methods[] = {
copy_doc}, copy_doc},
{"difference", (PyCFunction)set_difference, METH_O, {"difference", (PyCFunction)set_difference, METH_O,
difference_doc}, difference_doc},
{"intersection",(PyCFunction)set_intersection, METH_O, {"intersection",(PyCFunction)set_intersection_multi, METH_VARARGS,
intersection_doc}, intersection_doc},
{"isdisjoint", (PyCFunction)set_isdisjoint, METH_O, {"isdisjoint", (PyCFunction)set_isdisjoint, METH_O,
isdisjoint_doc}, isdisjoint_doc},
...@@ -2048,7 +2104,7 @@ static PyMethodDef frozenset_methods[] = { ...@@ -2048,7 +2104,7 @@ static PyMethodDef frozenset_methods[] = {
reduce_doc}, reduce_doc},
{"symmetric_difference",(PyCFunction)set_symmetric_difference, METH_O, {"symmetric_difference",(PyCFunction)set_symmetric_difference, METH_O,
symmetric_difference_doc}, symmetric_difference_doc},
{"union", (PyCFunction)set_union, METH_O, {"union", (PyCFunction)set_union, METH_VARARGS,
union_doc}, union_doc},
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };
......
...@@ -8300,6 +8300,28 @@ PyDoc_STRVAR(p_format__doc__, ...@@ -8300,6 +8300,28 @@ PyDoc_STRVAR(p_format__doc__,
\n\ \n\
"); ");
static PyObject *
unicode__sizeof__(PyUnicodeObject *v)
{
PyObject *res = NULL, *defsize = NULL;
res = PyLong_FromSsize_t(sizeof(PyUnicodeObject) +
sizeof(Py_UNICODE) * (v->length + 1));
if (v->defenc) {
defsize = PyObject_CallMethod(v->defenc, "__sizeof__", NULL);
if (defsize == NULL) {
Py_DECREF(res);
return NULL;
}
res = PyNumber_Add(res, defsize);
Py_DECREF(defsize);
}
return res;
}
PyDoc_STRVAR(sizeof__doc__,
"S.__sizeof__() -> size of S in memory, in bytes");
static PyObject * static PyObject *
unicode_getnewargs(PyUnicodeObject *v) unicode_getnewargs(PyUnicodeObject *v)
{ {
...@@ -8357,6 +8379,7 @@ static PyMethodDef unicode_methods[] = { ...@@ -8357,6 +8379,7 @@ static PyMethodDef unicode_methods[] = {
{"_formatter_parser", (PyCFunction) formatter_parser, METH_NOARGS}, {"_formatter_parser", (PyCFunction) formatter_parser, METH_NOARGS},
{"maketrans", (PyCFunction) unicode_maketrans, {"maketrans", (PyCFunction) unicode_maketrans,
METH_VARARGS | METH_STATIC, maketrans__doc__}, METH_VARARGS | METH_STATIC, maketrans__doc__},
{"__sizeof__", (PyCFunction) unicode__sizeof__, METH_NOARGS, sizeof__doc__},
#if 0 #if 0
{"capwords", (PyCFunction) unicode_capwords, METH_NOARGS, capwords__doc__}, {"capwords", (PyCFunction) unicode_capwords, METH_NOARGS, capwords__doc__},
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment