[Python-checkins] cpython (2.7): Issue #26995: Added tests for "f", "d", "D", "S", "Y", and "U" format codes

serhiy.storchaka python-checkins at python.org
Mon May 16 03:13:15 EDT 2016


https://hg.python.org/cpython/rev/c3346c89f6d4
changeset:   101366:c3346c89f6d4
branch:      2.7
parent:      101363:621e0a3249c2
user:        Serhiy Storchaka <storchaka at gmail.com>
date:        Mon May 16 10:12:02 2016 +0300
summary:
  Issue #26995: Added tests for "f", "d", "D", "S", "Y", and "U" format codes
in PyArg_ParseTuple().

files:
  Lib/test/test_getargs2.py |  166 +++++++++++++++++++++++++-
  Modules/_testcapimodule.c |   67 ++++++++++
  2 files changed, 232 insertions(+), 1 deletions(-)


diff --git a/Lib/test/test_getargs2.py b/Lib/test/test_getargs2.py
--- a/Lib/test/test_getargs2.py
+++ b/Lib/test/test_getargs2.py
@@ -1,4 +1,6 @@
 import unittest
+import math
+import sys
 from test import test_support
 # Skip this test if the _testcapi module isn't available.
 test_support.import_module('_testcapi')
@@ -42,7 +44,11 @@
 
 from _testcapi import UCHAR_MAX, USHRT_MAX, UINT_MAX, ULONG_MAX, INT_MAX, \
      INT_MIN, LONG_MIN, LONG_MAX, PY_SSIZE_T_MIN, PY_SSIZE_T_MAX, \
-     SHRT_MIN, SHRT_MAX
+     SHRT_MIN, SHRT_MAX, FLT_MIN, FLT_MAX, DBL_MIN, DBL_MAX
+
+DBL_MAX_EXP = sys.float_info.max_exp
+INF = float('inf')
+NAN = float('nan')
 
 try:
     from _testcapi import getargs_L, getargs_K
@@ -64,6 +70,55 @@
     def __int__(self):
         return 99
 
+
+class Float:
+    def __float__(self):
+        return 4.25
+
+class FloatSubclass(float):
+    pass
+
+class FloatSubclass2(float):
+    def __float__(self):
+        return 4.25
+
+class BadFloat:
+    def __float__(self):
+        return 687
+
+class BadFloat2:
+    def __float__(self):
+        return FloatSubclass(4.25)
+
+class BadFloat3(float):
+    def __float__(self):
+        return FloatSubclass(4.25)
+
+
+class Complex:
+    def __complex__(self):
+        return 4.25+0.5j
+
+class ComplexSubclass(complex):
+    pass
+
+class ComplexSubclass2(complex):
+    def __complex__(self):
+        return 4.25+0.5j
+
+class BadComplex:
+    def __complex__(self):
+        return 1.25
+
+class BadComplex2:
+    def __complex__(self):
+        return ComplexSubclass(4.25+0.5j)
+
+class BadComplex3(complex):
+    def __complex__(self):
+        return ComplexSubclass(4.25+0.5j)
+
+
 class TupleSubclass(tuple):
     pass
 
@@ -273,6 +328,80 @@
         self.assertEqual(VERY_LARGE & ULLONG_MAX, getargs_K(VERY_LARGE))
 
 
+class Float_TestCase(unittest.TestCase):
+    def assertEqualWithSign(self, actual, expected):
+        self.assertEqual(actual, expected)
+        self.assertEqual(math.copysign(1, actual), math.copysign(1, expected))
+
+    def test_f(self):
+        from _testcapi import getargs_f
+        self.assertEqual(getargs_f(4.25), 4.25)
+        self.assertEqual(getargs_f(4), 4.0)
+        self.assertRaises(TypeError, getargs_f, 4.25+0j)
+        self.assertEqual(getargs_f(Float()), 4.25)
+        self.assertEqual(getargs_f(FloatSubclass(7.5)), 7.5)
+        self.assertEqual(getargs_f(FloatSubclass2(7.5)), 7.5)
+        self.assertRaises(TypeError, getargs_f, BadFloat())
+        self.assertEqual(getargs_f(BadFloat2()), 4.25)
+        self.assertEqual(getargs_f(BadFloat3(7.5)), 7.5)
+
+        for x in (FLT_MIN, -FLT_MIN, FLT_MAX, -FLT_MAX, INF, -INF):
+            self.assertEqual(getargs_f(x), x)
+        if FLT_MAX < DBL_MAX:
+            self.assertEqual(getargs_f(DBL_MAX), INF)
+            self.assertEqual(getargs_f(-DBL_MAX), -INF)
+        if FLT_MIN > DBL_MIN:
+            self.assertEqualWithSign(getargs_f(DBL_MIN), 0.0)
+            self.assertEqualWithSign(getargs_f(-DBL_MIN), -0.0)
+        self.assertEqualWithSign(getargs_f(0.0), 0.0)
+        self.assertEqualWithSign(getargs_f(-0.0), -0.0)
+        r = getargs_f(NAN)
+        self.assertNotEqual(r, r)
+
+    def test_d(self):
+        from _testcapi import getargs_d
+        self.assertEqual(getargs_d(4.25), 4.25)
+        self.assertEqual(getargs_d(4), 4.0)
+        self.assertRaises(TypeError, getargs_d, 4.25+0j)
+        self.assertEqual(getargs_d(Float()), 4.25)
+        self.assertEqual(getargs_d(FloatSubclass(7.5)), 7.5)
+        self.assertEqual(getargs_d(FloatSubclass2(7.5)), 7.5)
+        self.assertRaises(TypeError, getargs_d, BadFloat())
+        self.assertEqual(getargs_d(BadFloat2()), 4.25)
+        self.assertEqual(getargs_d(BadFloat3(7.5)), 7.5)
+
+        for x in (DBL_MIN, -DBL_MIN, DBL_MAX, -DBL_MAX, INF, -INF):
+            self.assertEqual(getargs_d(x), x)
+        self.assertRaises(OverflowError, getargs_d, 1<<DBL_MAX_EXP)
+        self.assertRaises(OverflowError, getargs_d, -1<<DBL_MAX_EXP)
+        self.assertEqualWithSign(getargs_d(0.0), 0.0)
+        self.assertEqualWithSign(getargs_d(-0.0), -0.0)
+        r = getargs_d(NAN)
+        self.assertNotEqual(r, r)
+
+    def test_D(self):
+        from _testcapi import getargs_D
+        self.assertEqual(getargs_D(4.25+0.5j), 4.25+0.5j)
+        self.assertEqual(getargs_D(4.25), 4.25+0j)
+        self.assertEqual(getargs_D(4), 4.0+0j)
+        self.assertEqual(getargs_D(Complex()), 4.25+0.5j)
+        self.assertEqual(getargs_D(ComplexSubclass(7.5+0.25j)), 7.5+0.25j)
+        self.assertEqual(getargs_D(ComplexSubclass2(7.5+0.25j)), 7.5+0.25j)
+        self.assertRaises(TypeError, getargs_D, BadComplex())
+        self.assertEqual(getargs_D(BadComplex2()), 4.25+0.5j)
+        self.assertEqual(getargs_D(BadComplex3(7.5+0.25j)), 7.5+0.25j)
+
+        for x in (DBL_MIN, -DBL_MIN, DBL_MAX, -DBL_MAX, INF, -INF):
+            c = complex(x, 1.0)
+            self.assertEqual(getargs_D(c), c)
+            c = complex(1.0, x)
+            self.assertEqual(getargs_D(c), c)
+        self.assertEqualWithSign(getargs_D(complex(0.0, 1.0)).real, 0.0)
+        self.assertEqualWithSign(getargs_D(complex(-0.0, 1.0)).real, -0.0)
+        self.assertEqualWithSign(getargs_D(complex(1.0, 0.0)).imag, 0.0)
+        self.assertEqualWithSign(getargs_D(complex(1.0, -0.0)).imag, -0.0)
+
+
 class Tuple_TestCase(unittest.TestCase):
     def test_args(self):
         from _testcapi import get_args
@@ -676,5 +805,40 @@
              Bytes_TestCase, String_TestCase, Unicode_TestCase]
     test_support.run_unittest(*tests)
 
+class Object_TestCase(unittest.TestCase):
+    def test_S(self):
+        from _testcapi import getargs_S
+        obj = 'str'
+        self.assertIs(getargs_S(obj), obj)
+        self.assertRaises(TypeError, getargs_S, bytearray('bytearray'))
+        if test_support.have_unicode:
+            self.assertRaises(TypeError, getargs_S, u'unicode')
+        self.assertRaises(TypeError, getargs_S, None)
+        self.assertRaises(TypeError, getargs_S, memoryview(obj))
+        self.assertRaises(TypeError, getargs_S, buffer(obj))
+
+    def test_Y(self):
+        from _testcapi import getargs_Y
+        obj = bytearray('bytearray')
+        self.assertIs(getargs_Y(obj), obj)
+        self.assertRaises(TypeError, getargs_Y, 'str')
+        if test_support.have_unicode:
+            self.assertRaises(TypeError, getargs_Y, u'unicode')
+        self.assertRaises(TypeError, getargs_Y, None)
+        self.assertRaises(TypeError, getargs_Y, memoryview(obj))
+        self.assertRaises(TypeError, getargs_Y, buffer(obj))
+
+    @test_support.requires_unicode
+    def test_U(self):
+        from _testcapi import getargs_U
+        obj = u'unicode'
+        self.assertIs(getargs_U(obj), obj)
+        self.assertRaises(TypeError, getargs_U, 'str')
+        self.assertRaises(TypeError, getargs_U, bytearray('bytearray'))
+        self.assertRaises(TypeError, getargs_U, None)
+        self.assertRaises(TypeError, getargs_U, memoryview(obj))
+        self.assertRaises(TypeError, getargs_U, buffer(obj))
+
+
 if __name__ == "__main__":
     test_main()
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -1136,6 +1136,65 @@
 }
 
 static PyObject *
+getargs_f(PyObject *self, PyObject *args)
+{
+    float f;
+    if (!PyArg_ParseTuple(args, "f", &f))
+        return NULL;
+    return PyFloat_FromDouble(f);
+}
+
+static PyObject *
+getargs_d(PyObject *self, PyObject *args)
+{
+    double d;
+    if (!PyArg_ParseTuple(args, "d", &d))
+        return NULL;
+    return PyFloat_FromDouble(d);
+}
+
+static PyObject *
+getargs_D(PyObject *self, PyObject *args)
+{
+    Py_complex cval;
+    if (!PyArg_ParseTuple(args, "D", &cval))
+        return NULL;
+    return PyComplex_FromCComplex(cval);
+}
+
+static PyObject *
+getargs_S(PyObject *self, PyObject *args)
+{
+    PyObject *obj;
+    if (!PyArg_ParseTuple(args, "S", &obj))
+        return NULL;
+    Py_INCREF(obj);
+    return obj;
+}
+
+static PyObject *
+getargs_Y(PyObject *self, PyObject *args)
+{
+    PyObject *obj;
+    if (!PyArg_ParseTuple(args, "Y", &obj))
+        return NULL;
+    Py_INCREF(obj);
+    return obj;
+}
+
+#ifdef Py_USING_UNICODE
+static PyObject *
+getargs_U(PyObject *self, PyObject *args)
+{
+    PyObject *obj;
+    if (!PyArg_ParseTuple(args, "U", &obj))
+        return NULL;
+    Py_INCREF(obj);
+    return obj;
+}
+#endif
+
+static PyObject *
 getargs_c(PyObject *self, PyObject *args)
 {
     char c;
@@ -2377,6 +2436,14 @@
         (PyCFunction)test_long_long_and_overflow, METH_NOARGS},
     {"test_L_code",             (PyCFunction)test_L_code,        METH_NOARGS},
 #endif
+    {"getargs_f",               getargs_f,                       METH_VARARGS},
+    {"getargs_d",               getargs_d,                       METH_VARARGS},
+    {"getargs_D",               getargs_D,                       METH_VARARGS},
+    {"getargs_S",               getargs_S,                       METH_VARARGS},
+    {"getargs_Y",               getargs_Y,                       METH_VARARGS},
+#ifdef Py_USING_UNICODE
+    {"getargs_U",               getargs_U,                       METH_VARARGS},
+#endif
     {"getargs_c",               getargs_c,                       METH_VARARGS},
     {"getargs_s",               getargs_s,                       METH_VARARGS},
     {"getargs_s_star",          getargs_s_star,                  METH_VARARGS},

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list