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:
Amaury Forgeot d'Arc 2008-06-17 20:36:03 +00:00
parent 36817a984c
commit fdfe62d887
10 changed files with 616 additions and 647 deletions

View File

@ -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``

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -35,7 +35,7 @@
#include <unistd.h>
#endif
/* For uintptr_t, intptr_t */
/* For size_t? */
#ifdef HAVE_STDDEF_H
#include <stddef.h>
#endif

View File

@ -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)
#==============================================================================

View File

@ -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):

View File

@ -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()

View File

@ -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;
}

View File

@ -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},