Merged revisions 64089,64098,64100-64102,64113,64115-64116,64118,64120,64132,64342 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r64089 | armin.ronacher | 2008-06-10 22:37:02 +0200 (mar., 10 juin 2008) | 3 lines Fix a formatting error in the ast documentation. ........ r64098 | raymond.hettinger | 2008-06-11 02:25:29 +0200 (mer., 11 juin 2008) | 6 lines Mini-PEP: Simplifying numbers.py * Convert binary methods in Integral to mixin methods * Remove three-arg __pow__ as a required method * Make __int__ the root method instead of __long__. ........ r64100 | raymond.hettinger | 2008-06-11 02:28:51 +0200 (mer., 11 juin 2008) | 1 line Update numbers doc for the Integral simplification. ........ r64101 | raymond.hettinger | 2008-06-11 02:44:47 +0200 (mer., 11 juin 2008) | 3 lines Handle the case with zero arguments. ........ r64102 | benjamin.peterson | 2008-06-11 03:31:28 +0200 (mer., 11 juin 2008) | 4 lines convert test_struct to a unittest thanks to Giampaolo Rodola I had to disable one test because it was functioning incorrectly, see #1530559 I also removed the debugging prints ........ r64113 | thomas.heller | 2008-06-11 09:10:43 +0200 (mer., 11 juin 2008) | 2 lines Fix markup. Document the new 'offset' parameter for the 'ctypes.byref' function. ........ r64115 | raymond.hettinger | 2008-06-11 12:30:54 +0200 (mer., 11 juin 2008) | 1 line Multi-arg form for set.difference() and set.difference_update(). ........ r64116 | raymond.hettinger | 2008-06-11 14:06:49 +0200 (mer., 11 juin 2008) | 1 line Issue 3051: Let heapq work with either __lt__ or __le__. ........ r64118 | raymond.hettinger | 2008-06-11 14:39:09 +0200 (mer., 11 juin 2008) | 1 line Optimize previous checkin for heapq. ........ r64120 | raymond.hettinger | 2008-06-11 15:14:50 +0200 (mer., 11 juin 2008) | 1 line Add test for heapq using both __lt__ and __le__. ........ r64132 | gregory.p.smith | 2008-06-11 20:00:52 +0200 (mer., 11 juin 2008) | 3 lines Correct an incorrect comment about our #include of stddef.h. (see Doug Evans' comment on python-dev 2008-06-10) ........ r64342 | guido.van.rossum | 2008-06-17 19:38:02 +0200 (mar., 17 juin 2008) | 3 lines Roll back Raymond's -r64098 while we think of something better. (See issue 3056 -- we're close to a resolution but need unittests.) ........
This commit is contained in:
parent
36817a984c
commit
fdfe62d887
|
@ -135,7 +135,7 @@ and classes for traversing abstract syntax trees:
|
|||
from untrusted sources without the need to parse the values oneself.
|
||||
|
||||
|
||||
.. function:: get_docstring(node, clean=True):
|
||||
.. function:: get_docstring(node, clean=True)
|
||||
|
||||
Return the docstring of the given *node* (which must be a
|
||||
:class:`FunctionDef`, :class:`ClassDef` or :class:`Module` node), or ``None``
|
||||
|
|
|
@ -1395,11 +1395,6 @@ GetLastError() and SetLastError() Windows api functions;
|
|||
to request and change the ctypes private copy of the windows error
|
||||
code.
|
||||
|
||||
.. versionchanged:: 2.6
|
||||
|
||||
The `use_errno` and `use_last_error` parameters were added in Python
|
||||
2.6.
|
||||
|
||||
.. data:: RTLD_GLOBAL
|
||||
:noindex:
|
||||
|
||||
|
@ -1561,22 +1556,23 @@ They are instances of a private class:
|
|||
Assign a Python function or another callable to this attribute. The
|
||||
callable will be called with three or more arguments:
|
||||
|
||||
|
||||
.. function:: callable(result, func, arguments)
|
||||
.. function:: callable(result, func, arguments)
|
||||
:noindex:
|
||||
|
||||
``result`` is what the foreign function returns, as specified by the
|
||||
:attr:`restype` attribute.
|
||||
``result`` is what the foreign function returns, as specified
|
||||
by the :attr:`restype` attribute.
|
||||
|
||||
``func`` is the foreign function object itself, this allows to reuse the same
|
||||
callable object to check or post process the results of several functions.
|
||||
``func`` is the foreign function object itself, this allows
|
||||
to reuse the same callable object to check or post process
|
||||
the results of several functions.
|
||||
|
||||
``arguments`` is a tuple containing the parameters originally passed to the
|
||||
function call, this allows to specialize the behavior on the arguments used.
|
||||
``arguments`` is a tuple containing the parameters originally
|
||||
passed to the function call, this allows to specialize the
|
||||
behavior on the arguments used.
|
||||
|
||||
The object that this function returns will be returned from the foreign
|
||||
function call, but it can also check the result value and raise an exception
|
||||
if the foreign function call failed.
|
||||
The object that this function returns will be returned from the
|
||||
foreign function call, but it can also check the result value
|
||||
and raise an exception if the foreign function call failed.
|
||||
|
||||
|
||||
.. exception:: ArgumentError()
|
||||
|
@ -1605,10 +1601,6 @@ type and the argument types of the function.
|
|||
variable is exchanged with the real `errno` value bafore and after the call;
|
||||
`use_last_error` does the same for the Windows error code.
|
||||
|
||||
.. versionchanged:: 2.6
|
||||
The optional `use_errno` and `use_last_error` parameters were
|
||||
added.
|
||||
|
||||
|
||||
.. function:: WINFUNCTYPE(restype, *argtypes, use_errno=False, use_last_error=False)
|
||||
|
||||
|
@ -1786,11 +1778,19 @@ Utility functions
|
|||
ctypes type or instance.
|
||||
|
||||
|
||||
.. function:: byref(obj)
|
||||
.. function:: byref(obj[, offset])
|
||||
|
||||
Returns a light-weight pointer to ``obj``, which must be an instance of a ctypes
|
||||
type. The returned object can only be used as a foreign function call parameter.
|
||||
It behaves similar to ``pointer(obj)``, but the construction is a lot faster.
|
||||
Returns a light-weight pointer to ``obj``, which must be an
|
||||
instance of a ctypes type. ``offset`` defaults to zero, it must be
|
||||
an integer which is added to the internal pointer value.
|
||||
|
||||
``byref(obj, offset)`` corresponds to this C code::
|
||||
|
||||
(((char *)&obj) + offset)
|
||||
|
||||
The returned object can only be used as a foreign function call
|
||||
parameter. It behaves similar to ``pointer(obj)``, but the
|
||||
construction is a lot faster.
|
||||
|
||||
|
||||
.. function:: cast(obj, type)
|
||||
|
|
|
@ -71,10 +71,10 @@ The numeric tower
|
|||
|
||||
.. class:: Integral
|
||||
|
||||
Subtypes :class:`Rational` and adds a conversion to :class:`long`, the
|
||||
3-argument form of :func:`pow`, and the bit-string operations: ``<<``,
|
||||
``>>``, ``&``, ``^``, ``|``, ``~``. Provides defaults for :func:`float`,
|
||||
:attr:`Rational.numerator`, and :attr:`Rational.denominator`.
|
||||
Subtypes :class:`Rational` and adds a conversion to :class:`int`.
|
||||
Provides defaults for :func:`float`, :attr:`Rational.numerator`, and
|
||||
:attr:`Rational.denominator`, and bit-string operations: ``<<``,
|
||||
``>>``, ``&``, ``^``, ``|``, ``~``.
|
||||
|
||||
|
||||
Notes for type implementors
|
||||
|
|
|
@ -1517,21 +1517,15 @@ The constructors for both classes work the same:
|
|||
|
||||
Return a new set with elements from both sets.
|
||||
|
||||
.. 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 - ...
|
||||
|
||||
.. method:: difference(other)
|
||||
set - other
|
||||
|
||||
Return a new set with elements in the set that are not in *other*.
|
||||
Return a new set with elements in the set that are not in the others.
|
||||
|
||||
.. method:: symmetric_difference(other)
|
||||
set ^ other
|
||||
|
@ -1595,10 +1589,13 @@ The constructors for both classes work the same:
|
|||
.. versionchanged:: 2.6
|
||||
Accepts multiple input iterables.
|
||||
|
||||
.. method:: difference_update(other)
|
||||
set -= other
|
||||
.. method:: difference_update(other, ...)
|
||||
set -= other | ...
|
||||
|
||||
Update the set, removing elements found in *other*.
|
||||
Update the set, removing elements found in others.
|
||||
|
||||
.. versionchanged:: 2.6
|
||||
Accepts multiple input iterables.
|
||||
|
||||
.. method:: symmetric_difference_update(other)
|
||||
set ^= other
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
/* For uintptr_t, intptr_t */
|
||||
/* For size_t? */
|
||||
#ifdef HAVE_STDDEF_H
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
|
|
|
@ -197,6 +197,27 @@ class TestHeapPython(TestHeap):
|
|||
class TestHeapC(TestHeap):
|
||||
module = c_heapq
|
||||
|
||||
def test_comparison_operator(self):
|
||||
# Issue 3501: Make sure heapq works with both __lt__ and __le__
|
||||
def hsort(data, comp):
|
||||
data = [comp(x) for x in data]
|
||||
self.module.heapify(data)
|
||||
return [self.module.heappop(data).x for i in range(len(data))]
|
||||
class LT:
|
||||
def __init__(self, x):
|
||||
self.x = x
|
||||
def __lt__(self, other):
|
||||
return self.x > other.x
|
||||
class LE:
|
||||
def __init__(self, x):
|
||||
self.x = x
|
||||
def __lt__(self, other):
|
||||
return self.x >= other.x
|
||||
data = [random.random() for i in range(100)]
|
||||
target = sorted(data, reverse=True)
|
||||
self.assertEqual(hsort(data, LT), target)
|
||||
self.assertEqual(hsort(data, LE), target)
|
||||
|
||||
|
||||
#==============================================================================
|
||||
|
||||
|
|
|
@ -105,6 +105,12 @@ class TestJointOps(unittest.TestCase):
|
|||
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'))
|
||||
s = self.thetype('abcba')
|
||||
z = s.intersection()
|
||||
if self.thetype == frozenset():
|
||||
self.assertEqual(id(s), id(z))
|
||||
else:
|
||||
self.assertNotEqual(id(s), id(z))
|
||||
|
||||
def test_isdisjoint(self):
|
||||
def f(s1, s2):
|
||||
|
@ -144,6 +150,8 @@ class TestJointOps(unittest.TestCase):
|
|||
self.assertEqual(self.thetype('abcba').difference(C('efgfe')), set('abc'))
|
||||
self.assertEqual(self.thetype('abcba').difference(C('ccb')), set('a'))
|
||||
self.assertEqual(self.thetype('abcba').difference(C('ef')), set('abc'))
|
||||
self.assertEqual(self.thetype('abcba').difference(), set('abc'))
|
||||
self.assertEqual(self.thetype('abcba').difference(C('a'), C('b')), set('c'))
|
||||
|
||||
def test_sub(self):
|
||||
i = self.s.difference(self.otherword)
|
||||
|
@ -470,6 +478,18 @@ class TestSet(TestJointOps):
|
|||
self.assertEqual(s.difference_update(C(p)), None)
|
||||
self.assertEqual(s, set(q))
|
||||
|
||||
s = self.thetype('abcdefghih')
|
||||
s.difference_update()
|
||||
self.assertEqual(s, self.thetype('abcdefghih'))
|
||||
|
||||
s = self.thetype('abcdefghih')
|
||||
s.difference_update(C('aba'))
|
||||
self.assertEqual(s, self.thetype('cdefghih'))
|
||||
|
||||
s = self.thetype('abcdefghih')
|
||||
s.difference_update(C('cdc'), C('aba'))
|
||||
self.assertEqual(s, self.thetype('efghih'))
|
||||
|
||||
def test_isub(self):
|
||||
self.s -= set(self.otherword)
|
||||
for c in (self.word + self.otherword):
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
from test.support import TestFailed, verbose, verify, vereq
|
||||
import test.support
|
||||
import struct
|
||||
import array
|
||||
import unittest
|
||||
import struct
|
||||
import warnings
|
||||
|
||||
from functools import wraps
|
||||
from test.support import TestFailed, verbose, run_unittest, catch_warning
|
||||
|
||||
import sys
|
||||
ISBIGENDIAN = sys.byteorder == "big"
|
||||
del sys
|
||||
verify((struct.pack('=i', 1)[0] == 0) == ISBIGENDIAN,
|
||||
"bigendian determination appears wrong")
|
||||
|
||||
try:
|
||||
import _struct
|
||||
|
@ -30,39 +30,21 @@ def bigendian_to_native(value):
|
|||
else:
|
||||
return string_reverse(value)
|
||||
|
||||
def simple_err(func, *args):
|
||||
try:
|
||||
func(*args)
|
||||
except struct.error:
|
||||
pass
|
||||
else:
|
||||
raise TestFailed("%s%s did not raise struct.error" % (
|
||||
func.__name__, args))
|
||||
|
||||
def any_err(func, *args):
|
||||
try:
|
||||
func(*args)
|
||||
except (struct.error, TypeError):
|
||||
pass
|
||||
else:
|
||||
raise TestFailed("%s%s did not raise error" % (
|
||||
func.__name__, args))
|
||||
|
||||
def with_warning_restore(func):
|
||||
def _with_warning_restore(*args, **kw):
|
||||
with test.support.catch_warning():
|
||||
@wraps(func)
|
||||
def decorator(*args, **kw):
|
||||
with catch_warning():
|
||||
# Grrr, we need this function to warn every time. Without removing
|
||||
# the warningregistry, running test_tarfile then test_struct would fail
|
||||
# on 64-bit platforms.
|
||||
globals = func.__globals__
|
||||
if '__warningregistry__' in globals:
|
||||
del globals['__warningregistry__']
|
||||
warnings.filterwarnings("error", r"""^struct.*""", DeprecationWarning)
|
||||
warnings.filterwarnings("error", r""".*format requires.*""",
|
||||
DeprecationWarning)
|
||||
warnings.filterwarnings("error", category=DeprecationWarning)
|
||||
return func(*args, **kw)
|
||||
return _with_warning_restore
|
||||
return decorator
|
||||
|
||||
@with_warning_restore
|
||||
def deprecated_err(func, *args):
|
||||
try:
|
||||
func(*args)
|
||||
|
@ -75,59 +57,83 @@ def deprecated_err(func, *args):
|
|||
else:
|
||||
raise TestFailed("%s%s did not raise error" % (
|
||||
func.__name__, args))
|
||||
deprecated_err = with_warning_restore(deprecated_err)
|
||||
|
||||
|
||||
simple_err(struct.calcsize, 'Z')
|
||||
class StructTest(unittest.TestCase):
|
||||
|
||||
sz = struct.calcsize('i')
|
||||
if sz * 3 != struct.calcsize('iii'):
|
||||
raise TestFailed('inconsistent sizes')
|
||||
@with_warning_restore
|
||||
def check_float_coerce(self, format, number):
|
||||
# SF bug 1530559. struct.pack raises TypeError where it used to convert.
|
||||
if PY_STRUCT_FLOAT_COERCE == 2:
|
||||
# Test for pre-2.5 struct module
|
||||
packed = struct.pack(format, number)
|
||||
floored = struct.unpack(format, packed)[0]
|
||||
self.assertEqual(floored, int(number),
|
||||
"did not correcly coerce float to int")
|
||||
return
|
||||
try:
|
||||
struct.pack(format, number)
|
||||
except (struct.error, TypeError):
|
||||
if PY_STRUCT_FLOAT_COERCE:
|
||||
self.fail("expected DeprecationWarning for float coerce")
|
||||
except DeprecationWarning:
|
||||
if not PY_STRUCT_FLOAT_COERCE:
|
||||
self.fail("expected to raise struct.error for float coerce")
|
||||
else:
|
||||
self.fail("did not raise error for float coerce")
|
||||
|
||||
fmt = 'cbxxxxxxhhhhiillffd?'
|
||||
fmt3 = '3c3b18x12h6i6l6f3d3?'
|
||||
sz = struct.calcsize(fmt)
|
||||
sz3 = struct.calcsize(fmt3)
|
||||
if sz * 3 != sz3:
|
||||
raise TestFailed('inconsistent sizes (3*%r -> 3*%d = %d, %r -> %d)' % (
|
||||
fmt, sz, 3*sz, fmt3, sz3))
|
||||
def test_isbigendian(self):
|
||||
self.assertEqual((struct.pack('=i', 1)[0] == chr(0)), ISBIGENDIAN)
|
||||
|
||||
simple_err(struct.pack, 'iii', 3)
|
||||
simple_err(struct.pack, 'i', 3, 3, 3)
|
||||
simple_err(struct.pack, 'i', 'foo')
|
||||
simple_err(struct.pack, 'P', 'foo')
|
||||
simple_err(struct.unpack, 'd', b'flap')
|
||||
s = struct.pack('ii', 1, 2)
|
||||
simple_err(struct.unpack, 'iii', s)
|
||||
simple_err(struct.unpack, 'i', s)
|
||||
def test_consistence(self):
|
||||
self.assertRaises(struct.error, struct.calcsize, 'Z')
|
||||
|
||||
c = b'a'
|
||||
b = 1
|
||||
h = 255
|
||||
i = 65535
|
||||
l = 65536
|
||||
f = 3.1415
|
||||
d = 3.1415
|
||||
t = True
|
||||
sz = struct.calcsize('i')
|
||||
self.assertEqual(sz * 3, struct.calcsize('iii'))
|
||||
|
||||
for prefix in ('', '@', '<', '>', '=', '!'):
|
||||
fmt = 'cbxxxxxxhhhhiillffd?'
|
||||
fmt3 = '3c3b18x12h6i6l6f3d3?'
|
||||
sz = struct.calcsize(fmt)
|
||||
sz3 = struct.calcsize(fmt3)
|
||||
self.assertEqual(sz * 3, sz3)
|
||||
|
||||
self.assertRaises(struct.error, struct.pack, 'iii', 3)
|
||||
self.assertRaises(struct.error, struct.pack, 'i', 3, 3, 3)
|
||||
self.assertRaises(struct.error, struct.pack, 'i', 'foo')
|
||||
self.assertRaises(struct.error, struct.pack, 'P', 'foo')
|
||||
self.assertRaises(struct.error, struct.unpack, 'd', b'flap')
|
||||
s = struct.pack('ii', 1, 2)
|
||||
self.assertRaises(struct.error, struct.unpack, 'iii', s)
|
||||
self.assertRaises(struct.error, struct.unpack, 'i', s)
|
||||
|
||||
def test_transitiveness(self):
|
||||
c = b'a'
|
||||
b = 1
|
||||
h = 255
|
||||
i = 65535
|
||||
l = 65536
|
||||
f = 3.1415
|
||||
d = 3.1415
|
||||
t = True
|
||||
|
||||
for prefix in ('', '@', '<', '>', '=', '!'):
|
||||
for format in ('xcbhilfd?', 'xcBHILfd?'):
|
||||
format = prefix + format
|
||||
if verbose:
|
||||
print("trying:", format)
|
||||
s = struct.pack(format, c, b, h, i, l, f, d, t)
|
||||
cp, bp, hp, ip, lp, fp, dp, tp = struct.unpack(format, s)
|
||||
if (cp != c or bp != b or hp != h or ip != i or lp != l or
|
||||
int(100 * fp) != int(100 * f) or int(100 * dp) != int(100 * d) or
|
||||
tp != t):
|
||||
# ^^^ calculate only to two decimal places
|
||||
raise TestFailed("unpack/pack not transitive (%s, %s)" % (
|
||||
str(format), str((cp, bp, hp, ip, lp, fp, dp, tp))))
|
||||
self.assertEqual(cp, c)
|
||||
self.assertEqual(bp, b)
|
||||
self.assertEqual(hp, h)
|
||||
self.assertEqual(ip, i)
|
||||
self.assertEqual(lp, l)
|
||||
self.assertEqual(int(100 * fp), int(100 * f))
|
||||
self.assertEqual(int(100 * dp), int(100 * d))
|
||||
self.assertEqual(tp, t)
|
||||
|
||||
# Test some of the new features in detail
|
||||
|
||||
# (format, argument, big-endian result, little-endian result, asymmetric)
|
||||
tests = [
|
||||
def test_new_features(self):
|
||||
# Test some of the new features in detail
|
||||
# (format, argument, big-endian result, little-endian result, asymmetric)
|
||||
tests = [
|
||||
('c', 'a', 'a', 'a', 0),
|
||||
('xc', 'a', '\0a', '\0a', 0),
|
||||
('cx', 'a', 'a\0', 'a\0', 0),
|
||||
|
@ -165,53 +171,42 @@ tests = [
|
|||
('?', True, '\1', '\1', 0),
|
||||
('?', [], '\0', '\0', 1),
|
||||
('?', (1,), '\1', '\1', 1),
|
||||
]
|
||||
]
|
||||
|
||||
for fmt, arg, big, lil, asy in tests:
|
||||
for fmt, arg, big, lil, asy in tests:
|
||||
big = bytes(big, "latin-1")
|
||||
lil = bytes(lil, "latin-1")
|
||||
if verbose:
|
||||
print("%r %r %r %r" % (fmt, arg, big, lil))
|
||||
for (xfmt, exp) in [('>'+fmt, big), ('!'+fmt, big), ('<'+fmt, lil),
|
||||
('='+fmt, ISBIGENDIAN and big or lil)]:
|
||||
res = struct.pack(xfmt, arg)
|
||||
if res != exp:
|
||||
raise TestFailed("pack(%r, %r) -> %r # expected %r" % (
|
||||
fmt, arg, res, exp))
|
||||
n = struct.calcsize(xfmt)
|
||||
if n != len(res):
|
||||
raise TestFailed("calcsize(%r) -> %d # expected %d" % (
|
||||
xfmt, n, len(res)))
|
||||
self.assertEqual(res, exp)
|
||||
self.assertEqual(struct.calcsize(xfmt), len(res))
|
||||
rev = struct.unpack(xfmt, res)[0]
|
||||
if isinstance(arg, str):
|
||||
# Strings are returned as bytes since you can't know the encoding of
|
||||
# the string when packed.
|
||||
# Strings are returned as bytes since you can't know the
|
||||
# encoding of the string when packed.
|
||||
arg = bytes(arg, 'latin1')
|
||||
if rev != arg and not asy:
|
||||
raise TestFailed("unpack(%r, %r) -> (%r,) # expected (%r,)" % (
|
||||
fmt, res, rev, arg))
|
||||
if rev != arg:
|
||||
self.assert_(asy)
|
||||
|
||||
###########################################################################
|
||||
# Simple native q/Q tests.
|
||||
def test_native_qQ(self):
|
||||
# can't pack -1 as unsigned regardless
|
||||
self.assertRaises((struct.error, TypeError), struct.pack, "Q", -1)
|
||||
# can't pack string as 'q' regardless
|
||||
self.assertRaises(struct.error, struct.pack, "q", "a")
|
||||
# ditto, but 'Q'
|
||||
self.assertRaises(struct.error, struct.pack, "Q", "a")
|
||||
|
||||
has_native_qQ = 1
|
||||
try:
|
||||
try:
|
||||
struct.pack("q", 5)
|
||||
except struct.error:
|
||||
has_native_qQ = 0
|
||||
|
||||
if verbose:
|
||||
print("Platform has native q/Q?", has_native_qQ and "Yes." or "No.")
|
||||
|
||||
any_err(struct.pack, "Q", -1) # can't pack -1 as unsigned regardless
|
||||
simple_err(struct.pack, "q", "a") # can't pack string as 'q' regardless
|
||||
simple_err(struct.pack, "Q", "a") # ditto, but 'Q'
|
||||
|
||||
def test_native_qQ():
|
||||
except struct.error:
|
||||
# does not have native q/Q
|
||||
pass
|
||||
else:
|
||||
nbytes = struct.calcsize('q')
|
||||
# The expected values here are in big-endian format, primarily because
|
||||
# I'm on a little-endian machine and so this is the clearest way (for
|
||||
# me) to force the code to get exercised.
|
||||
# The expected values here are in big-endian format, primarily
|
||||
# because I'm on a little-endian machine and so this is the
|
||||
# clearest way (for me) to force the code to get exercised.
|
||||
for format, input, expected in (
|
||||
('q', -1, '\xff' * nbytes),
|
||||
('q', 0, '\x00' * nbytes),
|
||||
|
@ -222,23 +217,15 @@ def test_native_qQ():
|
|||
expected = bytes(expected, "latin-1")
|
||||
got = struct.pack(format, input)
|
||||
native_expected = bigendian_to_native(expected)
|
||||
verify(got == native_expected,
|
||||
"%r-pack of %r gave %r, not %r" %
|
||||
(format, input, got, native_expected))
|
||||
self.assertEqual(got, native_expected)
|
||||
retrieved = struct.unpack(format, got)[0]
|
||||
verify(retrieved == input,
|
||||
"%r-unpack of %r gave %r, not %r" %
|
||||
(format, got, retrieved, input))
|
||||
self.assertEqual(retrieved, input)
|
||||
|
||||
if has_native_qQ:
|
||||
test_native_qQ()
|
||||
def test_standard_integers(self):
|
||||
# Standard integer tests (bBhHiIlLqQ).
|
||||
import binascii
|
||||
|
||||
###########################################################################
|
||||
# Standard integer tests (bBhHiIlLqQ).
|
||||
|
||||
import binascii
|
||||
|
||||
class IntTester:
|
||||
class IntTester(unittest.TestCase):
|
||||
|
||||
# XXX Most std integer modes fail to test for out-of-range.
|
||||
# The "i" and "l" codes appear to range-check OK on 32-bit boxes, but
|
||||
|
@ -247,12 +234,12 @@ class IntTester:
|
|||
BUGGY_RANGE_CHECK = "bBhHiIlL"
|
||||
|
||||
def __init__(self, formatpair, bytesize):
|
||||
assert len(formatpair) == 2
|
||||
self.assertEqual(len(formatpair), 2)
|
||||
self.formatpair = formatpair
|
||||
for direction in "<>!=":
|
||||
for code in formatpair:
|
||||
format = direction + code
|
||||
verify(struct.calcsize(format) == bytesize)
|
||||
self.assertEqual(struct.calcsize(format), bytesize)
|
||||
self.bytesize = bytesize
|
||||
self.bitsize = bytesize * 8
|
||||
self.signed_code, self.unsigned_code = formatpair
|
||||
|
@ -264,17 +251,14 @@ class IntTester:
|
|||
def test_one(self, x, pack=struct.pack,
|
||||
unpack=struct.unpack,
|
||||
unhexlify=binascii.unhexlify):
|
||||
if verbose:
|
||||
print("trying std", self.formatpair, "on", x, "==", hex(x))
|
||||
|
||||
# Try signed.
|
||||
code = self.signed_code
|
||||
if self.signed_min <= x <= self.signed_max:
|
||||
# Try big-endian.
|
||||
expected = int(x)
|
||||
expected = x
|
||||
if x < 0:
|
||||
expected += 1 << self.bitsize
|
||||
assert expected > 0
|
||||
self.assert_(expected > 0)
|
||||
expected = hex(expected)[2:] # chop "0x"
|
||||
if len(expected) & 1:
|
||||
expected = "0" + expected
|
||||
|
@ -284,18 +268,15 @@ class IntTester:
|
|||
# Pack work?
|
||||
format = ">" + code
|
||||
got = pack(format, x)
|
||||
verify(got == expected,
|
||||
"'%s'-pack of %r gave %r, not %r" %
|
||||
(format, x, got, expected))
|
||||
self.assertEqual(got, expected)
|
||||
|
||||
# Unpack work?
|
||||
retrieved = unpack(format, got)[0]
|
||||
verify(x == retrieved,
|
||||
"'%s'-unpack of %r gave %r, not %r" %
|
||||
(format, got, retrieved, x))
|
||||
self.assertEqual(x, retrieved)
|
||||
|
||||
# Adding any byte should cause a "too big" error.
|
||||
any_err(unpack, format, b'\x01' + got)
|
||||
self.assertRaises((struct.error, TypeError),
|
||||
unpack, format, b'\x01' + got)
|
||||
|
||||
# Try little-endian.
|
||||
format = "<" + code
|
||||
|
@ -303,18 +284,15 @@ class IntTester:
|
|||
|
||||
# Pack work?
|
||||
got = pack(format, x)
|
||||
verify(got == expected,
|
||||
"'%s'-pack of %r gave %r, not %r" %
|
||||
(format, x, got, expected))
|
||||
self.assertEqual(got, expected)
|
||||
|
||||
# Unpack work?
|
||||
retrieved = unpack(format, got)[0]
|
||||
verify(x == retrieved,
|
||||
"'%s'-unpack of %r gave %r, not %r" %
|
||||
(format, got, retrieved, x))
|
||||
self.assertEqual(x, retrieved)
|
||||
|
||||
# Adding any byte should cause a "too big" error.
|
||||
any_err(unpack, format, b'\x01' + got)
|
||||
self.assertRaises((struct.error, TypeError),
|
||||
unpack, format, b'\x01' + got)
|
||||
|
||||
else:
|
||||
# x is out of range -- verify pack realizes that.
|
||||
|
@ -330,7 +308,7 @@ class IntTester:
|
|||
if self.unsigned_min <= x <= self.unsigned_max:
|
||||
# Try big-endian.
|
||||
format = ">" + code
|
||||
expected = int(x)
|
||||
expected = x
|
||||
expected = hex(expected)[2:] # chop "0x"
|
||||
if len(expected) & 1:
|
||||
expected = "0" + expected
|
||||
|
@ -339,18 +317,15 @@ class IntTester:
|
|||
|
||||
# Pack work?
|
||||
got = pack(format, x)
|
||||
verify(got == expected,
|
||||
"'%s'-pack of %r gave %r, not %r" %
|
||||
(format, x, got, expected))
|
||||
self.assertEqual(got, expected)
|
||||
|
||||
# Unpack work?
|
||||
retrieved = unpack(format, got)[0]
|
||||
verify(x == retrieved,
|
||||
"'%s'-unpack of %r gave %r, not %r" %
|
||||
(format, got, retrieved, x))
|
||||
self.assertEqual(x, retrieved)
|
||||
|
||||
# Adding any byte should cause a "too big" error.
|
||||
any_err(unpack, format, b'\x01' + got)
|
||||
self.assertRaises((struct.error, TypeError),
|
||||
unpack, format, b'\x01' + got)
|
||||
|
||||
# Try little-endian.
|
||||
format = "<" + code
|
||||
|
@ -358,18 +333,15 @@ class IntTester:
|
|||
|
||||
# Pack work?
|
||||
got = pack(format, x)
|
||||
verify(got == expected,
|
||||
"'%s'-pack of %r gave %r, not %r" %
|
||||
(format, x, got, expected))
|
||||
self.assertEqual(got, expected)
|
||||
|
||||
# Unpack work?
|
||||
retrieved = unpack(format, got)[0]
|
||||
verify(x == retrieved,
|
||||
"'%s'-unpack of %r gave %r, not %r" %
|
||||
(format, got, retrieved, x))
|
||||
self.assertEqual(x, retrieved)
|
||||
|
||||
# Adding any byte should cause a "too big" error.
|
||||
any_err(unpack, format, b'\x01' + got)
|
||||
self.assertRaises((struct.error, TypeError),
|
||||
unpack, format, b'\x01' + got)
|
||||
|
||||
else:
|
||||
# x is out of range -- verify pack realizes that.
|
||||
|
@ -412,9 +384,11 @@ class IntTester:
|
|||
for direction in "<>":
|
||||
for code in self.formatpair:
|
||||
for badobject in "a string", 3+42j, randrange:
|
||||
any_err(struct.pack, direction + code, badobject)
|
||||
self.assertRaises((struct.error, TypeError),
|
||||
struct.pack, direction + code,
|
||||
badobject)
|
||||
|
||||
for args in [("bB", 1),
|
||||
for args in [("bB", 1),
|
||||
("hH", 2),
|
||||
("iI", 4),
|
||||
("lL", 4),
|
||||
|
@ -422,11 +396,8 @@ for args in [("bB", 1),
|
|||
t = IntTester(*args)
|
||||
t.run()
|
||||
|
||||
|
||||
###########################################################################
|
||||
# The p ("Pascal string") code.
|
||||
|
||||
def test_p_code():
|
||||
def test_p_code(self):
|
||||
# Test p ("Pascal string") code.
|
||||
for code, input, expected, expectedback in [
|
||||
('p','abc', '\x00', b''),
|
||||
('1p', 'abc', '\x00', b''),
|
||||
|
@ -438,23 +409,14 @@ def test_p_code():
|
|||
('1000p', 'x'*1000, '\xff' + 'x'*999, b'x'*255)]:
|
||||
expected = bytes(expected, "latin-1")
|
||||
got = struct.pack(code, input)
|
||||
if got != expected:
|
||||
raise TestFailed("pack(%r, %r) == %r but expected %r" %
|
||||
(code, input, got, expected))
|
||||
self.assertEqual(got, expected)
|
||||
(got,) = struct.unpack(code, got)
|
||||
if got != expectedback:
|
||||
raise TestFailed("unpack(%r, %r) == %r but expected %r" %
|
||||
(code, input, got, expectedback))
|
||||
self.assertEqual(got, expectedback)
|
||||
|
||||
test_p_code()
|
||||
|
||||
|
||||
###########################################################################
|
||||
# SF bug 705836. "<f" and ">f" had a severe rounding bug, where a carry
|
||||
# from the low-order discarded bits could propagate into the exponent
|
||||
# field, causing the result to be wrong by a factor of 2.
|
||||
|
||||
def test_705836():
|
||||
def test_705836(self):
|
||||
# SF bug 705836. "<f" and ">f" had a severe rounding bug, where a carry
|
||||
# from the low-order discarded bits could propagate into the exponent
|
||||
# field, causing the result to be wrong by a factor of 2.
|
||||
import math
|
||||
|
||||
for base in range(1, 33):
|
||||
|
@ -468,36 +430,28 @@ def test_705836():
|
|||
unpacked = struct.unpack("<f", packed)[0]
|
||||
# This failed at base = 2, 4, and 32, with unpacked = 1, 2, and
|
||||
# 16, respectively.
|
||||
verify(base == unpacked)
|
||||
self.assertEqual(base, unpacked)
|
||||
bigpacked = struct.pack(">f", smaller)
|
||||
verify(bigpacked == string_reverse(packed),
|
||||
">f pack should be byte-reversal of <f pack")
|
||||
self.assertEqual(bigpacked, string_reverse(packed))
|
||||
unpacked = struct.unpack(">f", bigpacked)[0]
|
||||
verify(base == unpacked)
|
||||
self.assertEqual(base, unpacked)
|
||||
|
||||
# Largest finite IEEE single.
|
||||
big = (1 << 24) - 1
|
||||
big = math.ldexp(big, 127 - 23)
|
||||
packed = struct.pack(">f", big)
|
||||
unpacked = struct.unpack(">f", packed)[0]
|
||||
verify(big == unpacked)
|
||||
self.assertEqual(big, unpacked)
|
||||
|
||||
# The same, but tack on a 1 bit so it rounds up to infinity.
|
||||
big = (1 << 25) - 1
|
||||
big = math.ldexp(big, 127 - 24)
|
||||
try:
|
||||
packed = struct.pack(">f", big)
|
||||
except OverflowError:
|
||||
pass
|
||||
else:
|
||||
raise TestFailed("expected OverflowError")
|
||||
self.assertRaises(OverflowError, struct.pack, ">f", big)
|
||||
|
||||
test_705836()
|
||||
|
||||
###########################################################################
|
||||
# SF bug 1229380. No struct.pack exception for some out of range integers
|
||||
|
||||
def test_1229380():
|
||||
if PY_STRUCT_RANGE_CHECKING:
|
||||
def test_1229380(self):
|
||||
# SF bug 1229380. No struct.pack exception for some out of
|
||||
# range integers
|
||||
import sys
|
||||
for endian in ('', '>', '<'):
|
||||
for fmt in ('B', 'H', 'I', 'L'):
|
||||
|
@ -509,83 +463,42 @@ def test_1229380():
|
|||
deprecated_err(struct.pack, endian + 'I', sys.maxsize * 4)
|
||||
deprecated_err(struct.pack, endian + 'L', sys.maxsize * 4)
|
||||
|
||||
if PY_STRUCT_RANGE_CHECKING:
|
||||
test_1229380()
|
||||
|
||||
###########################################################################
|
||||
# SF bug 1530559. struct.pack raises TypeError where it used to convert.
|
||||
|
||||
def check_float_coerce(format, number):
|
||||
if PY_STRUCT_FLOAT_COERCE == 2:
|
||||
# Test for pre-2.5 struct module
|
||||
packed = struct.pack(format, number)
|
||||
floored = struct.unpack(format, packed)[0]
|
||||
if floored != int(number):
|
||||
raise TestFailed("did not correcly coerce float to int")
|
||||
return
|
||||
try:
|
||||
func(*args)
|
||||
except (struct.error, TypeError):
|
||||
if PY_STRUCT_FLOAT_COERCE:
|
||||
raise TestFailed("expected DeprecationWarning for float coerce")
|
||||
except DeprecationWarning:
|
||||
if not PY_STRUCT_FLOAT_COERCE:
|
||||
raise TestFailed("expected to raise struct.error for float coerce")
|
||||
else:
|
||||
raise TestFailed("did not raise error for float coerce")
|
||||
|
||||
check_float_coerce = with_warning_restore(deprecated_err)
|
||||
|
||||
def test_1530559():
|
||||
def XXXtest_1530559(self):
|
||||
# XXX This is broken: see the bug report
|
||||
# SF bug 1530559. struct.pack raises TypeError where it used to convert.
|
||||
for endian in ('', '>', '<'):
|
||||
for fmt in ('B', 'H', 'I', 'L', 'b', 'h', 'i', 'l'):
|
||||
check_float_coerce(endian + fmt, 1.0)
|
||||
check_float_coerce(endian + fmt, 1.5)
|
||||
self.check_float_coerce(endian + fmt, 1.0)
|
||||
self.check_float_coerce(endian + fmt, 1.5)
|
||||
|
||||
test_1530559()
|
||||
|
||||
###########################################################################
|
||||
# Packing and unpacking to/from memory views.
|
||||
|
||||
# Copied and modified from unittest.
|
||||
def assertRaises(excClass, callableObj, *args, **kwargs):
|
||||
try:
|
||||
callableObj(*args, **kwargs)
|
||||
except excClass:
|
||||
return
|
||||
else:
|
||||
raise TestFailed("%s not raised." % excClass)
|
||||
|
||||
def test_unpack_from():
|
||||
def test_unpack_from(self):
|
||||
test_string = b'abcd01234'
|
||||
fmt = '4s'
|
||||
s = struct.Struct(fmt)
|
||||
for cls in (bytes, bytearray):
|
||||
if verbose:
|
||||
print("test_unpack_from using", cls.__name__)
|
||||
data = cls(test_string)
|
||||
if not isinstance(data, (bytes, bytearray)):
|
||||
bytes_data = bytes(data, 'latin1')
|
||||
else:
|
||||
bytes_data = data
|
||||
vereq(s.unpack_from(data), (b'abcd',))
|
||||
vereq(s.unpack_from(data, 2), (b'cd01',))
|
||||
vereq(s.unpack_from(data, 4), (b'0123',))
|
||||
self.assertEqual(s.unpack_from(data), (b'abcd',))
|
||||
self.assertEqual(s.unpack_from(data, 2), (b'cd01',))
|
||||
self.assertEqual(s.unpack_from(data, 4), (b'0123',))
|
||||
for i in range(6):
|
||||
vereq(s.unpack_from(data, i), (bytes_data[i:i+4],))
|
||||
self.assertEqual(s.unpack_from(data, i), (bytes_data[i:i+4],))
|
||||
for i in range(6, len(test_string) + 1):
|
||||
simple_err(s.unpack_from, data, i)
|
||||
self.assertRaises(struct.error, s.unpack_from, data, i)
|
||||
for cls in (bytes, bytearray):
|
||||
data = cls(test_string)
|
||||
vereq(struct.unpack_from(fmt, data), (b'abcd',))
|
||||
vereq(struct.unpack_from(fmt, data, 2), (b'cd01',))
|
||||
vereq(struct.unpack_from(fmt, data, 4), (b'0123',))
|
||||
self.assertEqual(struct.unpack_from(fmt, data), (b'abcd',))
|
||||
self.assertEqual(struct.unpack_from(fmt, data, 2), (b'cd01',))
|
||||
self.assertEqual(struct.unpack_from(fmt, data, 4), (b'0123',))
|
||||
for i in range(6):
|
||||
vereq(struct.unpack_from(fmt, data, i), (bytes_data[i:i+4],))
|
||||
self.assertEqual(struct.unpack_from(fmt, data, i), (data[i:i+4],))
|
||||
for i in range(6, len(test_string) + 1):
|
||||
simple_err(struct.unpack_from, fmt, data, i)
|
||||
self.assertRaises(struct.error, struct.unpack_from, fmt, data, i)
|
||||
|
||||
def test_pack_into():
|
||||
def test_pack_into(self):
|
||||
test_string = b'Reykjavik rocks, eow!'
|
||||
writable_buf = array.array('b', b' '*100)
|
||||
fmt = '21s'
|
||||
|
@ -594,19 +507,19 @@ def test_pack_into():
|
|||
# Test without offset
|
||||
s.pack_into(writable_buf, 0, test_string)
|
||||
from_buf = writable_buf.tostring()[:len(test_string)]
|
||||
vereq(from_buf, test_string)
|
||||
self.assertEqual(from_buf, test_string)
|
||||
|
||||
# Test with offset.
|
||||
s.pack_into(writable_buf, 10, test_string)
|
||||
from_buf = writable_buf.tostring()[:len(test_string)+10]
|
||||
vereq(from_buf, test_string[:10] + test_string)
|
||||
self.assertEqual(from_buf, test_string[:10] + test_string)
|
||||
|
||||
# Go beyond boundaries.
|
||||
small_buf = array.array('b', b' '*10)
|
||||
assertRaises(struct.error, s.pack_into, small_buf, 0, test_string)
|
||||
assertRaises(struct.error, s.pack_into, small_buf, 2, test_string)
|
||||
self.assertRaises(struct.error, s.pack_into, small_buf, 0, test_string)
|
||||
self.assertRaises(struct.error, s.pack_into, small_buf, 2, test_string)
|
||||
|
||||
def test_pack_into_fn():
|
||||
def test_pack_into_fn(self):
|
||||
test_string = b'Reykjavik rocks, eow!'
|
||||
writable_buf = array.array('b', b' '*100)
|
||||
fmt = '21s'
|
||||
|
@ -615,75 +528,60 @@ def test_pack_into_fn():
|
|||
# Test without offset.
|
||||
pack_into(writable_buf, 0, test_string)
|
||||
from_buf = writable_buf.tostring()[:len(test_string)]
|
||||
vereq(from_buf, test_string)
|
||||
self.assertEqual(from_buf, test_string)
|
||||
|
||||
# Test with offset.
|
||||
pack_into(writable_buf, 10, test_string)
|
||||
from_buf = writable_buf.tostring()[:len(test_string)+10]
|
||||
vereq(from_buf, test_string[:10] + test_string)
|
||||
self.assertEqual(from_buf, test_string[:10] + test_string)
|
||||
|
||||
# Go beyond boundaries.
|
||||
small_buf = array.array('b', b' '*10)
|
||||
assertRaises(struct.error, pack_into, small_buf, 0, test_string)
|
||||
assertRaises(struct.error, pack_into, small_buf, 2, test_string)
|
||||
self.assertRaises(struct.error, pack_into, small_buf, 0, test_string)
|
||||
self.assertRaises(struct.error, pack_into, small_buf, 2, test_string)
|
||||
|
||||
def test_unpack_with_memoryview():
|
||||
def test_unpack_with_buffer(self):
|
||||
# SF bug 1563759: struct.unpack doens't support buffer protocol objects
|
||||
data1 = array.array('B', b'\x12\x34\x56\x78')
|
||||
data2 = memoryview(b'\x12\x34\x56\x78') # XXX b'......XXXX......', 6, 4
|
||||
for data in [data1, data2]:
|
||||
value, = struct.unpack('>I', data)
|
||||
vereq(value, 0x12345678)
|
||||
self.assertEqual(value, 0x12345678)
|
||||
|
||||
# Test methods to pack and unpack from memoryviews rather than strings.
|
||||
test_unpack_from()
|
||||
test_pack_into()
|
||||
test_pack_into_fn()
|
||||
test_unpack_with_memoryview()
|
||||
|
||||
def test_bool():
|
||||
def test_bool(self):
|
||||
for prefix in tuple("<>!=")+('',):
|
||||
false = (), [], [], '', 0
|
||||
true = [1], 'test', 5, -1, 0xffffffff+1, 0xffffffff/2
|
||||
|
||||
falseFormat = prefix + '?' * len(false)
|
||||
if verbose:
|
||||
print('trying bool pack/unpack on', false, 'using format', falseFormat)
|
||||
packedFalse = struct.pack(falseFormat, *false)
|
||||
unpackedFalse = struct.unpack(falseFormat, packedFalse)
|
||||
|
||||
trueFormat = prefix + '?' * len(true)
|
||||
if verbose:
|
||||
print('trying bool pack/unpack on', true, 'using format', trueFormat)
|
||||
packedTrue = struct.pack(trueFormat, *true)
|
||||
unpackedTrue = struct.unpack(trueFormat, packedTrue)
|
||||
|
||||
if len(true) != len(unpackedTrue):
|
||||
raise TestFailed('unpacked true array is not of same size as input')
|
||||
if len(false) != len(unpackedFalse):
|
||||
raise TestFailed('unpacked false array is not of same size as input')
|
||||
self.assertEqual(len(true), len(unpackedTrue))
|
||||
self.assertEqual(len(false), len(unpackedFalse))
|
||||
|
||||
for t in unpackedFalse:
|
||||
if t is not False:
|
||||
raise TestFailed('%r did not unpack as False' % t)
|
||||
self.assertFalse(t)
|
||||
for t in unpackedTrue:
|
||||
if t is not True:
|
||||
raise TestFailed('%r did not unpack as false' % t)
|
||||
self.assertTrue(t)
|
||||
|
||||
if prefix and verbose:
|
||||
print('trying size of bool with format %r' % (prefix+'?'))
|
||||
packed = struct.pack(prefix+'?', 1)
|
||||
|
||||
if len(packed) != struct.calcsize(prefix+'?'):
|
||||
raise TestFailed('packed length is not equal to calculated size')
|
||||
self.assertEqual(len(packed), struct.calcsize(prefix+'?'))
|
||||
|
||||
if len(packed) != 1 and prefix:
|
||||
raise TestFailed('encoded bool is not one byte: %r' % packed)
|
||||
elif not prefix and verbose:
|
||||
print('size of bool in native format is %i' % (len(packed)))
|
||||
if len(packed) != 1:
|
||||
self.assertFalse(prefix, msg='encoded bool is not one byte: %r'
|
||||
%packed)
|
||||
|
||||
for c in [b'\x01', b'\x7f', b'\xff', b'\x0f', b'\xf0']:
|
||||
if struct.unpack('>?', c)[0] is not True:
|
||||
raise TestFailed('%c did not unpack as True' % c)
|
||||
self.assertTrue(struct.unpack('>?', c)[0])
|
||||
|
||||
test_bool()
|
||||
def test_main():
|
||||
run_unittest(StructTest)
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_main()
|
||||
|
|
|
@ -17,13 +17,18 @@ static int
|
|||
cmp_lt(PyObject *x, PyObject *y)
|
||||
{
|
||||
int cmp;
|
||||
cmp = PyObject_RichCompareBool(x, y, Py_LT);
|
||||
if (cmp == -1 && PyErr_ExceptionMatches(PyExc_AttributeError)) {
|
||||
PyErr_Clear();
|
||||
static PyObject *lt = NULL;
|
||||
|
||||
if (lt == NULL) {
|
||||
lt = PyUnicode_FromString("__lt__");
|
||||
if (lt == NULL)
|
||||
return -1;
|
||||
}
|
||||
if (PyObject_HasAttr(x, lt))
|
||||
return PyObject_RichCompareBool(x, y, Py_LT);
|
||||
cmp = PyObject_RichCompareBool(y, x, Py_LE);
|
||||
if (cmp != -1)
|
||||
cmp = 1 - cmp;
|
||||
}
|
||||
return cmp;
|
||||
}
|
||||
|
||||
|
|
|
@ -1304,6 +1304,9 @@ set_intersection_multi(PySetObject *so, PyObject *args)
|
|||
Py_ssize_t i;
|
||||
PyObject *result = (PyObject *)so;
|
||||
|
||||
if (PyTuple_GET_SIZE(args) == 0)
|
||||
return set_copy(so);
|
||||
|
||||
Py_INCREF(so);
|
||||
for (i=0 ; i<PyTuple_GET_SIZE(args) ; i++) {
|
||||
PyObject *other = PyTuple_GET_ITEM(args, i);
|
||||
|
@ -1484,11 +1487,16 @@ set_difference_update_internal(PySetObject *so, PyObject *other)
|
|||
}
|
||||
|
||||
static PyObject *
|
||||
set_difference_update(PySetObject *so, PyObject *other)
|
||||
set_difference_update(PySetObject *so, PyObject *args)
|
||||
{
|
||||
if (set_difference_update_internal(so, other) != -1)
|
||||
Py_RETURN_NONE;
|
||||
Py_ssize_t i;
|
||||
|
||||
for (i=0 ; i<PyTuple_GET_SIZE(args) ; i++) {
|
||||
PyObject *other = PyTuple_GET_ITEM(args, i);
|
||||
if (set_difference_update_internal(so, other) == -1)
|
||||
return NULL;
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(difference_update_doc,
|
||||
|
@ -1546,10 +1554,34 @@ set_difference(PySetObject *so, PyObject *other)
|
|||
return result;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
set_difference_multi(PySetObject *so, PyObject *args)
|
||||
{
|
||||
Py_ssize_t i;
|
||||
PyObject *result, *other;
|
||||
|
||||
if (PyTuple_GET_SIZE(args) == 0)
|
||||
return set_copy(so);
|
||||
|
||||
other = PyTuple_GET_ITEM(args, 0);
|
||||
result = set_difference(so, other);
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
|
||||
for (i=1 ; i<PyTuple_GET_SIZE(args) ; i++) {
|
||||
other = PyTuple_GET_ITEM(args, i);
|
||||
if (set_difference_update_internal((PySetObject *)result, other) == -1) {
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(difference_doc,
|
||||
"Return the difference of two sets as a new set.\n\
|
||||
"Return the difference of two or more sets as a new set.\n\
|
||||
\n\
|
||||
(i.e. all elements that are in this set but not the other.)");
|
||||
(i.e. all elements that are in this set but not the others.)");
|
||||
static PyObject *
|
||||
set_sub(PySetObject *so, PyObject *other)
|
||||
{
|
||||
|
@ -1563,16 +1595,12 @@ set_sub(PySetObject *so, PyObject *other)
|
|||
static PyObject *
|
||||
set_isub(PySetObject *so, PyObject *other)
|
||||
{
|
||||
PyObject *result;
|
||||
|
||||
if (!PyAnySet_Check(other)) {
|
||||
Py_INCREF(Py_NotImplemented);
|
||||
return Py_NotImplemented;
|
||||
}
|
||||
result = set_difference_update(so, other);
|
||||
if (result == NULL)
|
||||
if (set_difference_update_internal(so, other) == -1)
|
||||
return NULL;
|
||||
Py_DECREF(result);
|
||||
Py_INCREF(so);
|
||||
return (PyObject *)so;
|
||||
}
|
||||
|
@ -1963,9 +1991,9 @@ static PyMethodDef set_methods[] = {
|
|||
copy_doc},
|
||||
{"discard", (PyCFunction)set_discard, METH_O,
|
||||
discard_doc},
|
||||
{"difference", (PyCFunction)set_difference, METH_O,
|
||||
{"difference", (PyCFunction)set_difference_multi, METH_VARARGS,
|
||||
difference_doc},
|
||||
{"difference_update", (PyCFunction)set_difference_update, METH_O,
|
||||
{"difference_update", (PyCFunction)set_difference_update, METH_VARARGS,
|
||||
difference_update_doc},
|
||||
{"intersection",(PyCFunction)set_intersection_multi, METH_VARARGS,
|
||||
intersection_doc},
|
||||
|
@ -2087,7 +2115,7 @@ static PyMethodDef frozenset_methods[] = {
|
|||
contains_doc},
|
||||
{"copy", (PyCFunction)frozenset_copy, METH_NOARGS,
|
||||
copy_doc},
|
||||
{"difference", (PyCFunction)set_difference, METH_O,
|
||||
{"difference", (PyCFunction)set_difference_multi, METH_VARARGS,
|
||||
difference_doc},
|
||||
{"intersection",(PyCFunction)set_intersection_multi, METH_VARARGS,
|
||||
intersection_doc},
|
||||
|
|
Loading…
Reference in New Issue