summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/collections.rst3
-rw-r--r--Doc/library/math.rst4
-rw-r--r--Doc/library/stdtypes.rst28
-rw-r--r--Doc/library/tokenize.rst10
-rw-r--r--Lib/collections.py4
-rw-r--r--Lib/test/test_collections.py21
-rw-r--r--Lib/test/test_math.py15
-rw-r--r--Lib/test/test_set.py13
-rw-r--r--Lib/test/test_sys.py32
-rw-r--r--Lib/test/test_urllib2net.py24
-rw-r--r--Modules/mathmodule.c49
-rw-r--r--Objects/setobject.c92
-rw-r--r--Objects/unicodeobject.c23
13 files changed, 269 insertions, 49 deletions
diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst
index 5035ac9..3203ca5 100644
--- a/Doc/library/collections.rst
+++ b/Doc/library/collections.rst
@@ -519,6 +519,9 @@ Example:
if kwds:
raise ValueError('Got unexpected field names: %r' % kwds.keys())
return result
+ <BLANKLINE>
+ def __getnewargs__(self):
+ return tuple(self)
<BLANKLINE>
x = property(itemgetter(0))
y = property(itemgetter(1))
diff --git a/Doc/library/math.rst b/Doc/library/math.rst
index 0868e8e..aba6b0e 100644
--- a/Doc/library/math.rst
+++ b/Doc/library/math.rst
@@ -41,6 +41,10 @@ Number-theoretic and representation functions:
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)
diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst
index 09549ad..27c3fb4 100644
--- a/Doc/library/stdtypes.rst
+++ b/Doc/library/stdtypes.rst
@@ -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 >=
other and set != other``.
- .. method:: union(other)
- set | other
+ .. method:: union(other, ...)
+ set | other | ...
Return a new set with elements from both sets.
- .. method:: intersection(other)
- set & other
+ .. versionchanged:: 2.6
+ Accepts multiple input iterables.
+
+ .. method:: intersection(other, ...)
+ set & other & ...
Return a new set with elements common to both sets.
+ .. versionchanged:: 2.6
+ Accepts multiple input iterables.
+
.. method:: difference(other)
set - other
@@ -1562,16 +1568,22 @@ The constructors for both classes work the same:
The following table lists operations available for :class:`set` that do not
apply to immutable instances of :class:`frozenset`:
- .. method:: update(other)
- set |= other
+ .. method:: update(other, ...)
+ set |= other | ...
Update the set, adding elements from *other*.
- .. method:: intersection_update(other)
- set &= other
+ .. versionchanged:: 2.6
+ Accepts multiple input iterables.
+
+ .. method:: intersection_update(other, ...)
+ set &= other & ...
Update the set, keeping only elements found in it and *other*.
+ .. versionchanged:: 2.6
+ Accepts multiple input iterables.
+
.. method:: difference_update(other)
set -= other
diff --git a/Doc/library/tokenize.rst b/Doc/library/tokenize.rst
index bbe73d0..b2caded 100644
--- a/Doc/library/tokenize.rst
+++ b/Doc/library/tokenize.rst
@@ -1,4 +1,3 @@
-
:mod:`tokenize` --- Tokenizer for Python source
===============================================
@@ -15,7 +14,6 @@ colorizers for on-screen displays.
The primary entry point is a :term:`generator`:
-
.. function:: tokenize(readline)
The :func:`tokenize` generator requires one argument, *readline*, which
@@ -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
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
- the line on which the token was found. The line passed is the *logical*
- line; continuation lines are included.
+ the line on which the token was found. The line passed (the last tuple item)
+ is the *logical* line; continuation lines are included.
- tokenize determines the source encoding of the file by looking for a utf-8
- bom or encoding cookie, according to :pep:`263`.
+ :func:`tokenize` determines the source encoding of the file by looking for a
+ UTF-8 BOM or encoding cookie, according to :pep:`263`.
All constants from the :mod:`token` module are also exported from
diff --git a/Lib/collections.py b/Lib/collections.py
index 73fc150..6d439e5 100644
--- a/Lib/collections.py
+++ b/Lib/collections.py
@@ -87,7 +87,9 @@ def namedtuple(typename, field_names, verbose=False):
result = self._make(map(kwds.pop, %(field_names)r, self))
if kwds:
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):
template += ' %s = property(itemgetter(%d))\n' % (name, i)
if verbose:
diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py
index 4ed0e24..9289afe 100644
--- a/Lib/test/test_collections.py
+++ b/Lib/test/test_collections.py
@@ -3,6 +3,7 @@
import unittest, doctest
from test import support
from collections import namedtuple
+import pickle, copy
from collections import Hashable, Iterable, Iterator
from collections import Sized, Container, Callable
from collections import Set, MutableSet
@@ -10,6 +11,7 @@ from collections import Mapping, MutableMapping
from collections import Sequence, MutableSequence
from collections import ByteString
+TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests
class TestNamedTuple(unittest.TestCase):
@@ -111,7 +113,7 @@ class TestNamedTuple(unittest.TestCase):
self.assertEqual(Dot(1)._replace(d=999), (999,))
self.assertEqual(Dot(1)._fields, ('d',))
- # n = 10000
+ # n = 5000
n = 254 # SyntaxError: more than 255 arguments:
import string, random
names = list(set(''.join([random.choice(string.ascii_letters)
@@ -134,6 +136,23 @@ class TestNamedTuple(unittest.TestCase):
self.assertEqual(b2, tuple(b2_expected))
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):
def test_Hashable(self):
diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py
index f4c27bb..1eafeba 100644
--- a/Lib/test/test_math.py
+++ b/Lib/test/test_math.py
@@ -6,6 +6,7 @@ import unittest
import math
import os
import sys
+import random
eps = 1E-05
NAN = float('nan')
@@ -274,6 +275,20 @@ class MathTests(unittest.TestCase):
self.ftest('fabs(0)', math.fabs(0), 0)
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):
self.assertRaises(TypeError, math.floor)
self.assertEquals(int, type(math.floor(0.5)))
diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py
index d05df3f..ed2db18 100644
--- a/Lib/test/test_set.py
+++ b/Lib/test/test_set.py
@@ -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('ccb')), set('abc'))
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):
i = self.s.union(self.otherword)
@@ -103,6 +104,7 @@ class TestJointOps(unittest.TestCase):
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('ef')), set(''))
+ self.assertEqual(self.thetype('abcba').intersection(C('cbcf'), C('bag')), set('b'))
def test_isdisjoint(self):
def f(s1, s2):
@@ -410,6 +412,12 @@ class TestSet(TestJointOps):
s = self.thetype('abcba')
self.assertEqual(s.update(C(p)), None)
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):
self.s |= set(self.otherword)
@@ -431,6 +439,11 @@ class TestSet(TestJointOps):
s = self.thetype('abcba')
self.assertEqual(s.intersection_update(C(p)), None)
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):
self.s &= set(self.otherword)
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
index e9570e9..39ed0ad 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -386,11 +386,14 @@ class SizeofTest(unittest.TestCase):
self.file.close()
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)
- msg = 'wrong size for %s: got %d, expected %d' \
- % (type(o), result, size)
- self.assertEqual(result, size, msg)
+ msg = 'wrong size for %s: got %d, expected ' % (type(o), result)
+ if (size2 != None) and (result != size):
+ self.assertEqual(result, size2, msg + str(size2))
+ else:
+ self.assertEqual(result, size, msg + str(size))
def align(self, value):
mod = value % self.p
@@ -486,6 +489,24 @@ class SizeofTest(unittest.TestCase):
# list
self.check_sizeof([], h + l + p + 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
# long
@@ -495,9 +516,6 @@ class SizeofTest(unittest.TestCase):
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, 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():
diff --git a/Lib/test/test_urllib2net.py b/Lib/test/test_urllib2net.py
index 752406c..1c4af18 100644
--- a/Lib/test/test_urllib2net.py
+++ b/Lib/test/test_urllib2net.py
@@ -11,19 +11,25 @@ import os
import mimetools
-def _urlopen_with_retry(host, *args, **kwargs):
- # Connecting to remote hosts is flaky. Make it more robust
- # by retrying the connection several times.
+def _retry_thrice(func, exc, *args, **kwargs):
for i in range(3):
try:
- return urllib2.urlopen(host, *args, **kwargs)
- except urllib2.URLError as e:
+ return func(*args, **kwargs)
+ except exc as e:
last_exc = e
continue
except:
raise
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):
@@ -114,7 +120,7 @@ class OtherNetworkTests(unittest.TestCase):
'file:'+sanepathname2url(os.path.abspath(TESTFN)),
('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:
os.remove(TESTFN)
@@ -146,13 +152,15 @@ class OtherNetworkTests(unittest.TestCase):
## 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 time
import logging
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:
if isinstance(url, tuple):
diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c
index 16c829a..f759ada 100644
--- a/Modules/mathmodule.c
+++ b/Modules/mathmodule.c
@@ -568,6 +568,54 @@ Return an accurate floating point sum of values in the iterable.\n\
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 *
math_trunc(PyObject *self, PyObject *number)
{
static PyObject *trunc_str = NULL;
@@ -1022,6 +1070,7 @@ static PyMethodDef math_methods[] = {
{"degrees", math_degrees, METH_O, math_degrees_doc},
{"exp", math_exp, METH_O, math_exp_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},
{"fmod", math_fmod, METH_VARARGS, math_fmod_doc},
{"frexp", math_frexp, METH_O, math_frexp_doc},
diff --git a/Objects/setobject.c b/Objects/setobject.c
index f760b6a..4456ef4 100644
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -959,15 +959,20 @@ set_update_internal(PySetObject *so, PyObject *other)
}
static PyObject *
-set_update(PySetObject *so, PyObject *other)
+set_update(PySetObject *so, PyObject *args)
{
- if (set_update_internal(so, other) == -1)
- return NULL;
+ Py_ssize_t i;
+
+ 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;
}
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 *
make_new_set(PyTypeObject *type, PyObject *iterable)
@@ -1148,35 +1153,53 @@ set_clear(PySetObject *so)
PyDoc_STRVAR(clear_doc, "Remove all elements from this set.");
static PyObject *
-set_union(PySetObject *so, PyObject *other)
+set_union(PySetObject *so, PyObject *args)
{
PySetObject *result;
+ PyObject *other;
+ Py_ssize_t i;
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;
+
+ for (i=0 ; i<PyTuple_GET_SIZE(args) ; i++) {
+ other = PyTuple_GET_ITEM(args, i);
+ if ((PyObject *)so == other)
+ return (PyObject *)result;
+ if (set_update_internal(result, other) == -1) {
+ Py_DECREF(result);
+ return NULL;
+ }
}
return (PyObject *)result;
}
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\
(i.e. all elements that are in either set.)");
static PyObject *
set_or(PySetObject *so, PyObject *other)
{
+ PySetObject *result;
+
if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) {
Py_INCREF(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 *
@@ -1275,6 +1298,26 @@ set_intersection(PySetObject *so, PyObject *other)
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,
"Return the intersection of two sets as a new set.\n\
\n\
@@ -1293,6 +1336,19 @@ set_intersection_update(PySetObject *so, PyObject *other)
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,
"Update a set with the intersection of itself and another.");
@@ -1911,9 +1967,9 @@ static PyMethodDef set_methods[] = {
difference_doc},
{"difference_update", (PyCFunction)set_difference_update, METH_O,
difference_update_doc},
- {"intersection",(PyCFunction)set_intersection, METH_O,
+ {"intersection",(PyCFunction)set_intersection_multi, METH_VARARGS,
intersection_doc},
- {"intersection_update",(PyCFunction)set_intersection_update, METH_O,
+ {"intersection_update",(PyCFunction)set_intersection_update_multi, METH_VARARGS,
intersection_update_doc},
{"isdisjoint", (PyCFunction)set_isdisjoint, METH_O,
isdisjoint_doc},
@@ -1935,9 +1991,9 @@ static PyMethodDef set_methods[] = {
{"test_c_api", (PyCFunction)test_c_api, METH_NOARGS,
test_c_api_doc},
#endif
- {"union", (PyCFunction)set_union, METH_O,
+ {"union", (PyCFunction)set_union, METH_VARARGS,
union_doc},
- {"update", (PyCFunction)set_update, METH_O,
+ {"update", (PyCFunction)set_update, METH_VARARGS,
update_doc},
{NULL, NULL} /* sentinel */
};
@@ -2036,7 +2092,7 @@ static PyMethodDef frozenset_methods[] = {
copy_doc},
{"difference", (PyCFunction)set_difference, METH_O,
difference_doc},
- {"intersection",(PyCFunction)set_intersection, METH_O,
+ {"intersection",(PyCFunction)set_intersection_multi, METH_VARARGS,
intersection_doc},
{"isdisjoint", (PyCFunction)set_isdisjoint, METH_O,
isdisjoint_doc},
@@ -2048,7 +2104,7 @@ static PyMethodDef frozenset_methods[] = {
reduce_doc},
{"symmetric_difference",(PyCFunction)set_symmetric_difference, METH_O,
symmetric_difference_doc},
- {"union", (PyCFunction)set_union, METH_O,
+ {"union", (PyCFunction)set_union, METH_VARARGS,
union_doc},
{NULL, NULL} /* sentinel */
};
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 5cd9eb9..db907d6 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -8301,6 +8301,28 @@ PyDoc_STRVAR(p_format__doc__,
");
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 *
unicode_getnewargs(PyUnicodeObject *v)
{
return Py_BuildValue("(u#)", v->str, v->length);
@@ -8357,6 +8379,7 @@ static PyMethodDef unicode_methods[] = {
{"_formatter_parser", (PyCFunction) formatter_parser, METH_NOARGS},
{"maketrans", (PyCFunction) unicode_maketrans,
METH_VARARGS | METH_STATIC, maketrans__doc__},
+ {"__sizeof__", (PyCFunction) unicode__sizeof__, METH_NOARGS, sizeof__doc__},
#if 0
{"capwords", (PyCFunction) unicode_capwords, METH_NOARGS, capwords__doc__},
#endif