Issue #26995: Added tests for "f", "d", "D", "S", "Y", and "U" format codes
in PyArg_ParseTuple().
This commit is contained in:
commit
c944c2dab8
|
@ -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()
|
||||
|
|
|
@ -1102,6 +1102,63 @@ test_k_code(PyObject *self)
|
|||
return Py_None;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -3829,6 +3886,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},
|
||||
|
|
Loading…
Reference in New Issue