Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f95455d

Browse files
Issue #26995: Added tests for "f", "d", "D", "S", "Y", and "U" format codes
in PyArg_ParseTuple().
1 parent acef5de commit f95455d

2 files changed

Lines changed: 222 additions & 1 deletion

File tree

Lib/test/test_getargs2.py

Lines changed: 159 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import unittest
2+
import math
3+
import sys
24
from test import support
35
# Skip this test if the _testcapi module isn't available.
46
support.import_module('_testcapi')
@@ -43,7 +45,11 @@
4345

4446
from _testcapi import UCHAR_MAX, USHRT_MAX, UINT_MAX, ULONG_MAX, INT_MAX, \
4547
INT_MIN, LONG_MIN, LONG_MAX, PY_SSIZE_T_MIN, PY_SSIZE_T_MAX, \
46-
SHRT_MIN, SHRT_MAX
48+
SHRT_MIN, SHRT_MAX, FLT_MIN, FLT_MAX, DBL_MIN, DBL_MAX
49+
50+
DBL_MAX_EXP = sys.float_info.max_exp
51+
INF = float('inf')
52+
NAN = float('nan')
4753

4854
# fake, they are not defined in Python's header files
4955
LLONG_MAX = 2**63-1
@@ -70,6 +76,55 @@ class BadInt3(int):
7076
def __int__(self):
7177
return True
7278

79+
80+
class Float:
81+
def __float__(self):
82+
return 4.25
83+
84+
class FloatSubclass(float):
85+
pass
86+
87+
class FloatSubclass2(float):
88+
def __float__(self):
89+
return 4.25
90+
91+
class BadFloat:
92+
def __float__(self):
93+
return 687
94+
95+
class BadFloat2:
96+
def __float__(self):
97+
return FloatSubclass(4.25)
98+
99+
class BadFloat3(float):
100+
def __float__(self):
101+
return FloatSubclass(4.25)
102+
103+
104+
class Complex:
105+
def __complex__(self):
106+
return 4.25+0.5j
107+
108+
class ComplexSubclass(complex):
109+
pass
110+
111+
class ComplexSubclass2(complex):
112+
def __complex__(self):
113+
return 4.25+0.5j
114+
115+
class BadComplex:
116+
def __complex__(self):
117+
return 1.25
118+
119+
class BadComplex2:
120+
def __complex__(self):
121+
return ComplexSubclass(4.25+0.5j)
122+
123+
class BadComplex3(complex):
124+
def __complex__(self):
125+
return ComplexSubclass(4.25+0.5j)
126+
127+
73128
class TupleSubclass(tuple):
74129
pass
75130

@@ -295,6 +350,81 @@ def test_K(self):
295350

296351
self.assertEqual(VERY_LARGE & ULLONG_MAX, getargs_K(VERY_LARGE))
297352

353+
354+
class Float_TestCase(unittest.TestCase):
355+
def assertEqualWithSign(self, actual, expected):
356+
self.assertEqual(actual, expected)
357+
self.assertEqual(math.copysign(1, actual), math.copysign(1, expected))
358+
359+
def test_f(self):
360+
from _testcapi import getargs_f
361+
self.assertEqual(getargs_f(4.25), 4.25)
362+
self.assertEqual(getargs_f(4), 4.0)
363+
self.assertRaises(TypeError, getargs_f, 4.25+0j)
364+
self.assertEqual(getargs_f(Float()), 4.25)
365+
self.assertEqual(getargs_f(FloatSubclass(7.5)), 7.5)
366+
self.assertEqual(getargs_f(FloatSubclass2(7.5)), 7.5)
367+
self.assertRaises(TypeError, getargs_f, BadFloat())
368+
self.assertEqual(getargs_f(BadFloat2()), 4.25)
369+
self.assertEqual(getargs_f(BadFloat3(7.5)), 7.5)
370+
371+
for x in (FLT_MIN, -FLT_MIN, FLT_MAX, -FLT_MAX, INF, -INF):
372+
self.assertEqual(getargs_f(x), x)
373+
if FLT_MAX < DBL_MAX:
374+
self.assertEqual(getargs_f(DBL_MAX), INF)
375+
self.assertEqual(getargs_f(-DBL_MAX), -INF)
376+
if FLT_MIN > DBL_MIN:
377+
self.assertEqualWithSign(getargs_f(DBL_MIN), 0.0)
378+
self.assertEqualWithSign(getargs_f(-DBL_MIN), -0.0)
379+
self.assertEqualWithSign(getargs_f(0.0), 0.0)
380+
self.assertEqualWithSign(getargs_f(-0.0), -0.0)
381+
r = getargs_f(NAN)
382+
self.assertNotEqual(r, r)
383+
384+
def test_d(self):
385+
from _testcapi import getargs_d
386+
self.assertEqual(getargs_d(4.25), 4.25)
387+
self.assertEqual(getargs_d(4), 4.0)
388+
self.assertRaises(TypeError, getargs_d, 4.25+0j)
389+
self.assertEqual(getargs_d(Float()), 4.25)
390+
self.assertEqual(getargs_d(FloatSubclass(7.5)), 7.5)
391+
self.assertEqual(getargs_d(FloatSubclass2(7.5)), 7.5)
392+
self.assertRaises(TypeError, getargs_d, BadFloat())
393+
self.assertEqual(getargs_d(BadFloat2()), 4.25)
394+
self.assertEqual(getargs_d(BadFloat3(7.5)), 7.5)
395+
396+
for x in (DBL_MIN, -DBL_MIN, DBL_MAX, -DBL_MAX, INF, -INF):
397+
self.assertEqual(getargs_d(x), x)
398+
self.assertRaises(OverflowError, getargs_d, 1<<DBL_MAX_EXP)
399+
self.assertRaises(OverflowError, getargs_d, -1<<DBL_MAX_EXP)
400+
self.assertEqualWithSign(getargs_d(0.0), 0.0)
401+
self.assertEqualWithSign(getargs_d(-0.0), -0.0)
402+
r = getargs_d(NAN)
403+
self.assertNotEqual(r, r)
404+
405+
def test_D(self):
406+
from _testcapi import getargs_D
407+
self.assertEqual(getargs_D(4.25+0.5j), 4.25+0.5j)
408+
self.assertEqual(getargs_D(4.25), 4.25+0j)
409+
self.assertEqual(getargs_D(4), 4.0+0j)
410+
self.assertEqual(getargs_D(Complex()), 4.25+0.5j)
411+
self.assertEqual(getargs_D(ComplexSubclass(7.5+0.25j)), 7.5+0.25j)
412+
self.assertEqual(getargs_D(ComplexSubclass2(7.5+0.25j)), 7.5+0.25j)
413+
self.assertRaises(TypeError, getargs_D, BadComplex())
414+
self.assertEqual(getargs_D(BadComplex2()), 4.25+0.5j)
415+
self.assertEqual(getargs_D(BadComplex3(7.5+0.25j)), 7.5+0.25j)
416+
417+
for x in (DBL_MIN, -DBL_MIN, DBL_MAX, -DBL_MAX, INF, -INF):
418+
c = complex(x, 1.0)
419+
self.assertEqual(getargs_D(c), c)
420+
c = complex(1.0, x)
421+
self.assertEqual(getargs_D(c), c)
422+
self.assertEqualWithSign(getargs_D(complex(0.0, 1.0)).real, 0.0)
423+
self.assertEqualWithSign(getargs_D(complex(-0.0, 1.0)).real, -0.0)
424+
self.assertEqualWithSign(getargs_D(complex(1.0, 0.0)).imag, 0.0)
425+
self.assertEqualWithSign(getargs_D(complex(1.0, -0.0)).imag, -0.0)
426+
427+
298428
class Paradox:
299429
"This statement is false."
300430
def __bool__(self):
@@ -760,5 +890,33 @@ def test_Z_hash(self):
760890
self.assertIsNone(getargs_Z_hash(None))
761891

762892

893+
class Object_TestCase(unittest.TestCase):
894+
def test_S(self):
895+
from _testcapi import getargs_S
896+
obj = b'bytes'
897+
self.assertIs(getargs_S(obj), obj)
898+
self.assertRaises(TypeError, getargs_S, bytearray(b'bytearray'))
899+
self.assertRaises(TypeError, getargs_S, 'str')
900+
self.assertRaises(TypeError, getargs_S, None)
901+
self.assertRaises(TypeError, getargs_S, memoryview(obj))
902+
903+
def test_Y(self):
904+
from _testcapi import getargs_Y
905+
obj = bytearray(b'bytearray')
906+
self.assertIs(getargs_Y(obj), obj)
907+
self.assertRaises(TypeError, getargs_Y, b'bytes')
908+
self.assertRaises(TypeError, getargs_Y, 'str')
909+
self.assertRaises(TypeError, getargs_Y, None)
910+
self.assertRaises(TypeError, getargs_Y, memoryview(obj))
911+
912+
def test_U(self):
913+
from _testcapi import getargs_U
914+
obj = 'str'
915+
self.assertIs(getargs_U(obj), obj)
916+
self.assertRaises(TypeError, getargs_U, b'bytes')
917+
self.assertRaises(TypeError, getargs_U, bytearray(b'bytearray'))
918+
self.assertRaises(TypeError, getargs_U, None)
919+
920+
763921
if __name__ == "__main__":
764922
unittest.main()

Modules/_testcapimodule.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,63 @@ test_k_code(PyObject *self)
11021102
return Py_None;
11031103
}
11041104

1105+
static PyObject *
1106+
getargs_f(PyObject *self, PyObject *args)
1107+
{
1108+
float f;
1109+
if (!PyArg_ParseTuple(args, "f", &f))
1110+
return NULL;
1111+
return PyFloat_FromDouble(f);
1112+
}
1113+
1114+
static PyObject *
1115+
getargs_d(PyObject *self, PyObject *args)
1116+
{
1117+
double d;
1118+
if (!PyArg_ParseTuple(args, "d", &d))
1119+
return NULL;
1120+
return PyFloat_FromDouble(d);
1121+
}
1122+
1123+
static PyObject *
1124+
getargs_D(PyObject *self, PyObject *args)
1125+
{
1126+
Py_complex cval;
1127+
if (!PyArg_ParseTuple(args, "D", &cval))
1128+
return NULL;
1129+
return PyComplex_FromCComplex(cval);
1130+
}
1131+
1132+
static PyObject *
1133+
getargs_S(PyObject *self, PyObject *args)
1134+
{
1135+
PyObject *obj;
1136+
if (!PyArg_ParseTuple(args, "S", &obj))
1137+
return NULL;
1138+
Py_INCREF(obj);
1139+
return obj;
1140+
}
1141+
1142+
static PyObject *
1143+
getargs_Y(PyObject *self, PyObject *args)
1144+
{
1145+
PyObject *obj;
1146+
if (!PyArg_ParseTuple(args, "Y", &obj))
1147+
return NULL;
1148+
Py_INCREF(obj);
1149+
return obj;
1150+
}
1151+
1152+
static PyObject *
1153+
getargs_U(PyObject *self, PyObject *args)
1154+
{
1155+
PyObject *obj;
1156+
if (!PyArg_ParseTuple(args, "U", &obj))
1157+
return NULL;
1158+
Py_INCREF(obj);
1159+
return obj;
1160+
}
1161+
11051162
static PyObject *
11061163
getargs_c(PyObject *self, PyObject *args)
11071164
{
@@ -3696,6 +3753,12 @@ static PyMethodDef TestMethods[] = {
36963753
(PyCFunction)test_long_long_and_overflow, METH_NOARGS},
36973754
{"test_L_code", (PyCFunction)test_L_code, METH_NOARGS},
36983755
#endif
3756+
{"getargs_f", getargs_f, METH_VARARGS},
3757+
{"getargs_d", getargs_d, METH_VARARGS},
3758+
{"getargs_D", getargs_D, METH_VARARGS},
3759+
{"getargs_S", getargs_S, METH_VARARGS},
3760+
{"getargs_Y", getargs_Y, METH_VARARGS},
3761+
{"getargs_U", getargs_U, METH_VARARGS},
36993762
{"getargs_c", getargs_c, METH_VARARGS},
37003763
{"getargs_C", getargs_C, METH_VARARGS},
37013764
{"getargs_s", getargs_s, METH_VARARGS},

0 commit comments

Comments
 (0)