diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2016-05-16 07:11:47 (GMT) |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2016-05-16 07:11:47 (GMT) |
commit | f95455da4c3c61a302d62322a4bcb17a629efd4b (patch) | |
tree | edce042440c577bea729621e113d7cc97fcad1ba | |
parent | acef5de6ecd1cb84420bb0ea8d0a8d6cd09682e2 (diff) | |
download | cpython-f95455da4c3c61a302d62322a4bcb17a629efd4b.zip cpython-f95455da4c3c61a302d62322a4bcb17a629efd4b.tar.gz cpython-f95455da4c3c61a302d62322a4bcb17a629efd4b.tar.bz2 |
Issue #26995: Added tests for "f", "d", "D", "S", "Y", and "U" format codes
in PyArg_ParseTuple().
-rw-r--r-- | Lib/test/test_getargs2.py | 160 | ||||
-rw-r--r-- | Modules/_testcapimodule.c | 63 |
2 files changed, 222 insertions, 1 deletions
diff --git a/Lib/test/test_getargs2.py b/Lib/test/test_getargs2.py index 2e98d65..984aac7 100644 --- 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 support # Skip this test if the _testcapi module isn't available. support.import_module('_testcapi') @@ -43,7 +45,11 @@ VERY_LARGE = 0xFF0000121212121212121242 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') # fake, they are not defined in Python's header files LLONG_MAX = 2**63-1 @@ -70,6 +76,55 @@ class BadInt3(int): def __int__(self): return True + +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 @@ -295,6 +350,81 @@ class LongLong_TestCase(unittest.TestCase): 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 Paradox: "This statement is false." def __bool__(self): @@ -760,5 +890,33 @@ class String_TestCase(unittest.TestCase): self.assertIsNone(getargs_Z_hash(None)) +class Object_TestCase(unittest.TestCase): + def test_S(self): + from _testcapi import getargs_S + obj = b'bytes' + self.assertIs(getargs_S(obj), obj) + self.assertRaises(TypeError, getargs_S, bytearray(b'bytearray')) + self.assertRaises(TypeError, getargs_S, 'str') + self.assertRaises(TypeError, getargs_S, None) + self.assertRaises(TypeError, getargs_S, memoryview(obj)) + + def test_Y(self): + from _testcapi import getargs_Y + obj = bytearray(b'bytearray') + self.assertIs(getargs_Y(obj), obj) + self.assertRaises(TypeError, getargs_Y, b'bytes') + self.assertRaises(TypeError, getargs_Y, 'str') + self.assertRaises(TypeError, getargs_Y, None) + self.assertRaises(TypeError, getargs_Y, memoryview(obj)) + + def test_U(self): + from _testcapi import getargs_U + obj = 'str' + self.assertIs(getargs_U(obj), obj) + self.assertRaises(TypeError, getargs_U, b'bytes') + self.assertRaises(TypeError, getargs_U, bytearray(b'bytearray')) + self.assertRaises(TypeError, getargs_U, None) + + if __name__ == "__main__": unittest.main() diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 19fea20..d86af15 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1103,6 +1103,63 @@ test_k_code(PyObject *self) } 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; +} + +static PyObject * +getargs_U(PyObject *self, PyObject *args) +{ + PyObject *obj; + if (!PyArg_ParseTuple(args, "U", &obj)) + return NULL; + Py_INCREF(obj); + return obj; +} + +static PyObject * getargs_c(PyObject *self, PyObject *args) { char c; @@ -3696,6 +3753,12 @@ static PyMethodDef TestMethods[] = { (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}, + {"getargs_U", getargs_U, METH_VARARGS}, {"getargs_c", getargs_c, METH_VARARGS}, {"getargs_C", getargs_C, METH_VARARGS}, {"getargs_s", getargs_s, METH_VARARGS}, |