summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorThomas Heller <theller@ctypes.org>2003-04-17 18:55:45 (GMT)
committerThomas Heller <theller@ctypes.org>2003-04-17 18:55:45 (GMT)
commita4ea603b055533e71920a088acb1c106e4895dbd (patch)
treec50efc24264738dee727367ed0e55bc3e6aedf84 /Lib
parente13ddc9ec85287b17fd03454f836f495c1167de9 (diff)
downloadcpython-a4ea603b055533e71920a088acb1c106e4895dbd.zip
cpython-a4ea603b055533e71920a088acb1c106e4895dbd.tar.gz
cpython-a4ea603b055533e71920a088acb1c106e4895dbd.tar.bz2
SF # 595026: support for masks in getargs.c.
New functions: unsigned long PyInt_AsUnsignedLongMask(PyObject *); unsigned PY_LONG_LONG) PyInt_AsUnsignedLongLongMask(PyObject *); unsigned long PyLong_AsUnsignedLongMask(PyObject *); unsigned PY_LONG_LONG) PyLong_AsUnsignedLongLongMask(PyObject *); New and changed format codes: b unsigned char 0..UCHAR_MAX B unsigned char none ** h unsigned short 0..USHRT_MAX H unsigned short none ** i int INT_MIN..INT_MAX I * unsigned int 0..UINT_MAX l long LONG_MIN..LONG_MAX k * unsigned long none L long long LLONG_MIN..LLONG_MAX K * unsigned long long none Notes: * New format codes. ** Changed from previous "range-and-a-half" to "none"; the range-and-a-half checking wasn't particularly useful. New test test_getargs2.py, to verify all this.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/test/test_getargs2.py245
1 files changed, 245 insertions, 0 deletions
diff --git a/Lib/test/test_getargs2.py b/Lib/test/test_getargs2.py
new file mode 100644
index 0000000..4cf876a
--- /dev/null
+++ b/Lib/test/test_getargs2.py
@@ -0,0 +1,245 @@
+import unittest
+from test import test_support
+import sys
+
+import warnings, re
+warnings.filterwarnings("ignore", category=DeprecationWarning, module=__name__)
+
+"""
+> How about the following counterproposal. This also changes some of
+> the other format codes to be a little more regular.
+>
+> Code C type Range check
+>
+> b unsigned char 0..UCHAR_MAX
+> h unsigned short 0..USHRT_MAX
+> B unsigned char none **
+> H unsigned short none **
+> k * unsigned long none
+> I * unsigned int 0..UINT_MAX
+
+
+> i int INT_MIN..INT_MAX
+> l long LONG_MIN..LONG_MAX
+
+> K * unsigned long long none
+> L long long LLONG_MIN..LLONG_MAX
+
+> Notes:
+>
+> * New format codes.
+>
+> ** Changed from previous "range-and-a-half" to "none"; the
+> range-and-a-half checking wasn't particularly useful.
+
+Plus a C API or two, e.g. PyInt_AsLongMask() ->
+unsigned long and PyInt_AsLongLongMask() -> unsigned
+long long (if that exists).
+"""
+
+LARGE = 0x7FFFFFFF
+VERY_LARGE = 0xFF0000121212121212121242L
+
+from _testcapi import UCHAR_MAX, USHRT_MAX, UINT_MAX, ULONG_MAX, INT_MAX, \
+ INT_MIN, LONG_MIN, LONG_MAX
+
+from _testcapi import getargs_ul as ul_convert
+from _testcapi import getargs_l as l_convert
+try:
+ from _testcapi import getargs_ll as ll_convert
+ from _testcapi import getargs_ull as ull_convert
+except ImportError:
+ pass
+
+# fake, they are not defined in Python's header files
+LLONG_MAX = 2**63-1
+LLONG_MIN = -2**63
+ULLONG_MAX = 2**64-1
+
+class Long:
+ def __int__(self):
+ return 99L
+
+class Int:
+ def __int__(self):
+ return 99
+
+class Unsigned_TestCase(unittest.TestCase):
+ def test_b(self):
+ # b returns 'unsigned char', and does range checking (0 ... UCHAR_MAX)
+ self.failUnlessEqual(3, ul_convert("b", 3.14))
+ self.failUnlessEqual(99, ul_convert("b", Long()))
+ self.failUnlessEqual(99, ul_convert("b", Int()))
+
+ self.assertRaises(OverflowError, ul_convert, "b", -1)
+ self.failUnlessEqual(0, ul_convert("b", 0))
+ self.failUnlessEqual(UCHAR_MAX, ul_convert("b", UCHAR_MAX))
+ self.assertRaises(OverflowError, ul_convert, "b", UCHAR_MAX + 1)
+
+ self.failUnlessEqual(42, ul_convert("b", 42))
+ self.failUnlessEqual(42, ul_convert("b", 42L))
+ self.assertRaises(OverflowError, ul_convert, "b", VERY_LARGE)
+
+ def test_h(self):
+ # h returns 'unsigned short', and does range checking (0 ... USHRT_MAX)
+ self.failUnlessEqual(3, ul_convert("h", 3.14))
+ self.failUnlessEqual(99, ul_convert("h", Long()))
+ self.failUnlessEqual(99, ul_convert("h", Int()))
+
+ self.assertRaises(OverflowError, ul_convert, "h", -1)
+ self.failUnlessEqual(0, ul_convert("h", 0))
+ self.failUnlessEqual(USHRT_MAX, ul_convert("h", USHRT_MAX))
+ self.assertRaises(OverflowError, ul_convert, "h", USHRT_MAX+1)
+
+ self.failUnlessEqual(42, ul_convert("h", 42))
+ self.failUnlessEqual(42, ul_convert("h", 42L))
+ self.assertRaises(OverflowError, ul_convert, "h", VERY_LARGE)
+
+ def test_B(self):
+ # B returns 'unsigned char', no range checking
+ self.failUnless(3 == ul_convert("B", 3.14))
+ self.failUnlessEqual(99, ul_convert("B", Long()))
+ self.failUnlessEqual(99, ul_convert("B", Int()))
+
+ self.failUnlessEqual(UCHAR_MAX, ul_convert("B", -1))
+ self.failUnlessEqual(UCHAR_MAX, ul_convert("B", -1L))
+ self.failUnlessEqual(0, ul_convert("B", 0))
+ self.failUnlessEqual(UCHAR_MAX, ul_convert("B", UCHAR_MAX))
+ self.failUnlessEqual(0, ul_convert("B", UCHAR_MAX+1))
+
+ self.failUnlessEqual(42, ul_convert("B", 42))
+ self.failUnlessEqual(42, ul_convert("B", 42L))
+ self.failUnlessEqual(UCHAR_MAX & VERY_LARGE, ul_convert("B", VERY_LARGE))
+
+ def test_H(self):
+ # H returns 'unsigned short', no range checking
+ self.failUnlessEqual(3, ul_convert("H", 3.14))
+ self.failUnlessEqual(99, ul_convert("H", Long()))
+ self.failUnlessEqual(99, ul_convert("H", Int()))
+
+ self.failUnlessEqual(USHRT_MAX, ul_convert("H", -1))
+ self.failUnlessEqual(0, ul_convert("H", 0))
+ self.failUnlessEqual(USHRT_MAX, ul_convert("H", USHRT_MAX))
+ self.failUnlessEqual(0, ul_convert("H", USHRT_MAX+1))
+
+ self.failUnlessEqual(42, ul_convert("H", 42))
+ self.failUnlessEqual(42, ul_convert("H", 42L))
+
+ self.failUnlessEqual(VERY_LARGE & USHRT_MAX, ul_convert("H", VERY_LARGE))
+
+ def test_I(self):
+ # I returns 'unsigned int', no range checking
+ self.failUnlessEqual(3, ul_convert("I", 3.14))
+ self.failUnlessEqual(99, ul_convert("I", Long()))
+ self.failUnlessEqual(99, ul_convert("I", Int()))
+
+ self.failUnlessEqual(UINT_MAX, ul_convert("I", -1))
+ self.failUnlessEqual(0, ul_convert("I", 0))
+ self.failUnlessEqual(UINT_MAX, ul_convert("I", UINT_MAX))
+ self.failUnlessEqual(0, ul_convert("I", UINT_MAX+1))
+
+ self.failUnlessEqual(42, ul_convert("I", 42))
+ self.failUnlessEqual(42, ul_convert("I", 42L))
+
+ self.failUnlessEqual(VERY_LARGE & UINT_MAX, ul_convert("I", VERY_LARGE))
+
+ def test_k(self):
+ # k returns 'unsigned long', no range checking
+ # it does not accept float, or instances with __int__
+ self.assertRaises(TypeError, ul_convert, "k", 3.14)
+ self.assertRaises(TypeError, ul_convert, "k", Long())
+ self.assertRaises(TypeError, ul_convert, "k", Int())
+
+ self.failUnlessEqual(ULONG_MAX, ul_convert("k", -1))
+ self.failUnlessEqual(0, ul_convert("k", 0))
+ self.failUnlessEqual(ULONG_MAX, ul_convert("k", ULONG_MAX))
+ self.failUnlessEqual(0, ul_convert("k", ULONG_MAX+1))
+
+ self.failUnlessEqual(42, ul_convert("k", 42))
+ self.failUnlessEqual(42, ul_convert("k", 42L))
+
+ self.failUnlessEqual(VERY_LARGE & ULONG_MAX, ul_convert("k", VERY_LARGE))
+
+class Signed_TestCase(unittest.TestCase):
+ def test_i(self):
+ # i returns 'int', and does range checking (INT_MIN ... INT_MAX)
+ self.failUnlessEqual(3, l_convert("i", 3.14))
+ self.failUnlessEqual(99, l_convert("i", Long()))
+ self.failUnlessEqual(99, l_convert("i", Int()))
+
+ self.assertRaises(OverflowError, l_convert, "i", INT_MIN-1)
+ self.failUnlessEqual(INT_MIN, l_convert("i", INT_MIN))
+ self.failUnlessEqual(INT_MAX, l_convert("i", INT_MAX))
+ self.assertRaises(OverflowError, l_convert, "i", INT_MAX+1)
+
+ self.failUnlessEqual(42, l_convert("i", 42))
+ self.failUnlessEqual(42, l_convert("i", 42L))
+ self.assertRaises(OverflowError, l_convert, "i", VERY_LARGE)
+
+ def test_l(self):
+ # l returns 'long', and does range checking (LONG_MIN ... LONG_MAX)
+ self.failUnlessEqual(3, l_convert("l", 3.14))
+ self.failUnlessEqual(99, l_convert("l", Long()))
+ self.failUnlessEqual(99, l_convert("l", Int()))
+
+ self.assertRaises(OverflowError, l_convert, "l", LONG_MIN-1)
+ self.failUnlessEqual(LONG_MIN, l_convert("l", LONG_MIN))
+ self.failUnlessEqual(LONG_MAX, l_convert("l", LONG_MAX))
+ self.assertRaises(OverflowError, l_convert, "l", LONG_MAX+1)
+
+ self.failUnlessEqual(42, l_convert("l", 42))
+ self.failUnlessEqual(42, l_convert("l", 42L))
+ self.assertRaises(OverflowError, l_convert, "l", VERY_LARGE)
+
+
+class LongLong_TestCase(unittest.TestCase):
+ def test_L(self):
+ # L returns 'long long', and does range checking (LLONG_MIN ... LLONG_MAX)
+
+ # XXX There's a bug in getargs.c, format code "L":
+ # If you pass something else than a Python long, you
+ # get "Bad argument to internal function".
+
+ # So these three tests are commented out:
+
+## self.failUnlessEqual(3, ll_convert("L", 3.14))
+## self.failUnlessEqual(99, ll_convert("L", Long()))
+## self.failUnlessEqual(99, ll_convert("L", Int()))
+
+ self.assertRaises(OverflowError, ll_convert, "L", LLONG_MIN-1)
+ self.failUnlessEqual(LLONG_MIN, ll_convert("L", LLONG_MIN))
+ self.failUnlessEqual(LLONG_MAX, ll_convert("L", LLONG_MAX))
+ self.assertRaises(OverflowError, ll_convert, "L", LLONG_MAX+1)
+
+ self.failUnlessEqual(42, ll_convert("L", 42))
+ self.failUnlessEqual(42, ll_convert("L", 42L))
+ self.assertRaises(OverflowError, ll_convert, "L", VERY_LARGE)
+
+ def test_K(self):
+ # K return 'unsigned long long', no range checking
+ self.assertRaises(TypeError, ull_convert, "K", 3.14)
+ self.assertRaises(TypeError, ull_convert, "K", Long())
+ self.assertRaises(TypeError, ull_convert, "K", Int())
+ self.failUnlessEqual(ULLONG_MAX, ull_convert("K", ULLONG_MAX))
+ self.failUnlessEqual(0, ull_convert("K", 0))
+ self.failUnlessEqual(0, ull_convert("K", ULLONG_MAX+1))
+
+ self.failUnlessEqual(42, ull_convert("K", 42))
+ self.failUnlessEqual(42, ull_convert("K", 42L))
+
+ self.failUnlessEqual(VERY_LARGE & ULLONG_MAX, ull_convert("K", VERY_LARGE))
+
+def test_main():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(Signed_TestCase))
+ suite.addTest(unittest.makeSuite(Unsigned_TestCase))
+ try:
+ ll_convert
+ except NameError:
+ pass # PY_LONG_LONG not available
+ else:
+ suite.addTest(unittest.makeSuite(LongLong_TestCase))
+ test_support.run_suite(suite)
+
+if __name__ == "__main__":
+ test_main()