mirror of
https://github.com/python/cpython.git
synced 2025-07-07 11:25:30 +00:00
gh-132987: Support __index__() for "k" and "K" formats in PyArg_Parse (GH-132988)
This commit is contained in:
parent
e714ead7a2
commit
632524a5cb
12 changed files with 51 additions and 30 deletions
|
@ -274,6 +274,9 @@ small to receive the value.
|
|||
Convert a Python integer to a C :c:expr:`unsigned long` without
|
||||
overflow checking.
|
||||
|
||||
.. versionchanged:: next
|
||||
Use :meth:`~object.__index__` if available.
|
||||
|
||||
``L`` (:class:`int`) [long long]
|
||||
Convert a Python integer to a C :c:expr:`long long`.
|
||||
|
||||
|
@ -281,6 +284,9 @@ small to receive the value.
|
|||
Convert a Python integer to a C :c:expr:`unsigned long long`
|
||||
without overflow checking.
|
||||
|
||||
.. versionchanged:: next
|
||||
Use :meth:`~object.__index__` if available.
|
||||
|
||||
``n`` (:class:`int`) [:c:type:`Py_ssize_t`]
|
||||
Convert a Python integer to a C :c:type:`Py_ssize_t`.
|
||||
|
||||
|
|
|
@ -2073,6 +2073,11 @@ New features
|
|||
Adding ``?`` after any format unit makes ``None`` be accepted as a value.
|
||||
(Contributed by Serhiy Storchaka in :gh:`112068`.)
|
||||
|
||||
* The ``k`` and ``K`` formats in :c:func:`PyArg_ParseTuple` and
|
||||
similar functions now use :meth:`~object.__index__` if available,
|
||||
like all other integer formats.
|
||||
(Contributed by Serhiy Storchaka in :gh:`112068`.)
|
||||
|
||||
* Add macros :c:func:`Py_PACK_VERSION` and :c:func:`Py_PACK_FULL_VERSION` for
|
||||
bit-packing Python version numbers.
|
||||
(Contributed by Petr Viktorin in :gh:`128629`.)
|
||||
|
|
|
@ -1410,7 +1410,7 @@ test_unsigned_long_converter(PyObject *module, PyObject *const *args, Py_ssize_t
|
|||
if (nargs < 3) {
|
||||
goto skip_optional;
|
||||
}
|
||||
if (!PyLong_Check(args[2])) {
|
||||
if (!PyIndex_Check(args[2])) {
|
||||
_PyArg_BadArgument("test_unsigned_long_converter", "argument 3", "int", args[2]);
|
||||
goto exit;
|
||||
}
|
||||
|
@ -1425,7 +1425,7 @@ exit:
|
|||
static PyObject *
|
||||
test_unsigned_long_converter_impl(PyObject *module, unsigned long a,
|
||||
unsigned long b, unsigned long c)
|
||||
/*[clinic end generated code: output=540bb0ba2894e1fe input=f450d94cae1ef73b]*/
|
||||
/*[clinic end generated code: output=d74eed227d77a31b input=f450d94cae1ef73b]*/
|
||||
|
||||
|
||||
/*[clinic input]
|
||||
|
@ -1525,7 +1525,7 @@ test_unsigned_long_long_converter(PyObject *module, PyObject *const *args, Py_ss
|
|||
if (nargs < 3) {
|
||||
goto skip_optional;
|
||||
}
|
||||
if (!PyLong_Check(args[2])) {
|
||||
if (!PyIndex_Check(args[2])) {
|
||||
_PyArg_BadArgument("test_unsigned_long_long_converter", "argument 3", "int", args[2]);
|
||||
goto exit;
|
||||
}
|
||||
|
@ -1542,7 +1542,7 @@ test_unsigned_long_long_converter_impl(PyObject *module,
|
|||
unsigned long long a,
|
||||
unsigned long long b,
|
||||
unsigned long long c)
|
||||
/*[clinic end generated code: output=3d69994f618b46bb input=a15115dc41866ff4]*/
|
||||
/*[clinic end generated code: output=5ca4e4dfb3db644b input=a15115dc41866ff4]*/
|
||||
|
||||
|
||||
/*[clinic input]
|
||||
|
|
|
@ -267,12 +267,12 @@ class Unsigned_TestCase(unittest.TestCase):
|
|||
def test_k(self):
|
||||
from _testcapi import getargs_k
|
||||
# k returns 'unsigned long', no range checking
|
||||
# it does not accept float, or instances with __int__
|
||||
self.assertRaises(TypeError, getargs_k, 3.14)
|
||||
self.assertRaises(TypeError, getargs_k, Index())
|
||||
self.assertEqual(99, getargs_k(Index()))
|
||||
self.assertEqual(0, getargs_k(IndexIntSubclass()))
|
||||
self.assertRaises(TypeError, getargs_k, BadIndex())
|
||||
self.assertRaises(TypeError, getargs_k, BadIndex2())
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.assertEqual(1, getargs_k(BadIndex2()))
|
||||
self.assertEqual(0, getargs_k(BadIndex3()))
|
||||
self.assertRaises(TypeError, getargs_k, Int())
|
||||
self.assertEqual(0, getargs_k(IntSubclass()))
|
||||
|
@ -419,10 +419,11 @@ class LongLong_TestCase(unittest.TestCase):
|
|||
from _testcapi import getargs_K
|
||||
# K return 'unsigned long long', no range checking
|
||||
self.assertRaises(TypeError, getargs_K, 3.14)
|
||||
self.assertRaises(TypeError, getargs_K, Index())
|
||||
self.assertEqual(99, getargs_K(Index()))
|
||||
self.assertEqual(0, getargs_K(IndexIntSubclass()))
|
||||
self.assertRaises(TypeError, getargs_K, BadIndex())
|
||||
self.assertRaises(TypeError, getargs_K, BadIndex2())
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.assertEqual(1, getargs_K(BadIndex2()))
|
||||
self.assertEqual(0, getargs_K(BadIndex3()))
|
||||
self.assertRaises(TypeError, getargs_K, Int())
|
||||
self.assertEqual(0, getargs_K(IntSubclass()))
|
||||
|
@ -432,6 +433,7 @@ class LongLong_TestCase(unittest.TestCase):
|
|||
|
||||
self.assertEqual(ULLONG_MAX, getargs_K(ULLONG_MAX))
|
||||
self.assertEqual(0, getargs_K(0))
|
||||
self.assertEqual(ULLONG_MAX, getargs_K(ULLONG_MAX))
|
||||
self.assertEqual(0, getargs_K(ULLONG_MAX+1))
|
||||
|
||||
self.assertEqual(42, getargs_K(42))
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
The ``k`` and ``K`` formats in :c:func:`PyArg_Parse` now support the
|
||||
:meth:`~object.__index__` special method, like all other integer formats.
|
6
Modules/clinic/_cursesmodule.c.h
generated
6
Modules/clinic/_cursesmodule.c.h
generated
|
@ -2388,7 +2388,7 @@ _curses_ungetmouse(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
|||
if (z == -1 && PyErr_Occurred()) {
|
||||
goto exit;
|
||||
}
|
||||
if (!PyLong_Check(args[4])) {
|
||||
if (!PyIndex_Check(args[4])) {
|
||||
_PyArg_BadArgument("ungetmouse", "argument 5", "int", args[4]);
|
||||
goto exit;
|
||||
}
|
||||
|
@ -3154,7 +3154,7 @@ _curses_mousemask(PyObject *module, PyObject *arg)
|
|||
PyObject *return_value = NULL;
|
||||
unsigned long newmask;
|
||||
|
||||
if (!PyLong_Check(arg)) {
|
||||
if (!PyIndex_Check(arg)) {
|
||||
_PyArg_BadArgument("mousemask", "argument", "int", arg);
|
||||
goto exit;
|
||||
}
|
||||
|
@ -4394,4 +4394,4 @@ _curses_has_extended_color_support(PyObject *module, PyObject *Py_UNUSED(ignored
|
|||
#ifndef _CURSES_USE_DEFAULT_COLORS_METHODDEF
|
||||
#define _CURSES_USE_DEFAULT_COLORS_METHODDEF
|
||||
#endif /* !defined(_CURSES_USE_DEFAULT_COLORS_METHODDEF) */
|
||||
/*[clinic end generated code: output=acae2eb9cf75e76d input=a9049054013a1b77]*/
|
||||
/*[clinic end generated code: output=dbbbe86a4171799a input=a9049054013a1b77]*/
|
||||
|
|
6
Modules/clinic/_testclinic.c.h
generated
6
Modules/clinic/_testclinic.c.h
generated
|
@ -1038,7 +1038,7 @@ unsigned_long_converter(PyObject *module, PyObject *const *args, Py_ssize_t narg
|
|||
if (nargs < 3) {
|
||||
goto skip_optional;
|
||||
}
|
||||
if (!PyLong_Check(args[2])) {
|
||||
if (!PyIndex_Check(args[2])) {
|
||||
_PyArg_BadArgument("unsigned_long_converter", "argument 3", "int", args[2]);
|
||||
goto exit;
|
||||
}
|
||||
|
@ -1122,7 +1122,7 @@ unsigned_long_long_converter(PyObject *module, PyObject *const *args, Py_ssize_t
|
|||
if (nargs < 3) {
|
||||
goto skip_optional;
|
||||
}
|
||||
if (!PyLong_Check(args[2])) {
|
||||
if (!PyIndex_Check(args[2])) {
|
||||
_PyArg_BadArgument("unsigned_long_long_converter", "argument 3", "int", args[2]);
|
||||
goto exit;
|
||||
}
|
||||
|
@ -4481,4 +4481,4 @@ _testclinic_TestClass_posonly_poskw_varpos_array_no_fastcall(PyObject *type, PyO
|
|||
exit:
|
||||
return return_value;
|
||||
}
|
||||
/*[clinic end generated code: output=b57b94aeba0882b4 input=a9049054013a1b77]*/
|
||||
/*[clinic end generated code: output=84ffc31f27215baa input=a9049054013a1b77]*/
|
||||
|
|
4
Modules/clinic/fcntlmodule.c.h
generated
4
Modules/clinic/fcntlmodule.c.h
generated
|
@ -120,7 +120,7 @@ fcntl_ioctl(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
|||
if (fd < 0) {
|
||||
goto exit;
|
||||
}
|
||||
if (!PyLong_Check(args[1])) {
|
||||
if (!PyIndex_Check(args[1])) {
|
||||
PyErr_Format(PyExc_TypeError, "ioctl() argument 2 must be int, not %T", args[1]);
|
||||
goto exit;
|
||||
}
|
||||
|
@ -264,4 +264,4 @@ skip_optional:
|
|||
exit:
|
||||
return return_value;
|
||||
}
|
||||
/*[clinic end generated code: output=30c01b46bfa840c1 input=a9049054013a1b77]*/
|
||||
/*[clinic end generated code: output=65a16bc64c7b4de4 input=a9049054013a1b77]*/
|
||||
|
|
6
Modules/clinic/posixmodule.c.h
generated
6
Modules/clinic/posixmodule.c.h
generated
|
@ -840,7 +840,7 @@ os_chflags(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *
|
|||
if (!path_converter(args[0], &path)) {
|
||||
goto exit;
|
||||
}
|
||||
if (!PyLong_Check(args[1])) {
|
||||
if (!PyIndex_Check(args[1])) {
|
||||
_PyArg_BadArgument("chflags", "argument 'flags'", "int", args[1]);
|
||||
goto exit;
|
||||
}
|
||||
|
@ -924,7 +924,7 @@ os_lchflags(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
|
|||
if (!path_converter(args[0], &path)) {
|
||||
goto exit;
|
||||
}
|
||||
if (!PyLong_Check(args[1])) {
|
||||
if (!PyIndex_Check(args[1])) {
|
||||
_PyArg_BadArgument("lchflags", "argument 'flags'", "int", args[1]);
|
||||
goto exit;
|
||||
}
|
||||
|
@ -13398,4 +13398,4 @@ os__emscripten_debugger(PyObject *module, PyObject *Py_UNUSED(ignored))
|
|||
#ifndef OS__EMSCRIPTEN_DEBUGGER_METHODDEF
|
||||
#define OS__EMSCRIPTEN_DEBUGGER_METHODDEF
|
||||
#endif /* !defined(OS__EMSCRIPTEN_DEBUGGER_METHODDEF) */
|
||||
/*[clinic end generated code: output=35dd8edb53b50537 input=a9049054013a1b77]*/
|
||||
/*[clinic end generated code: output=a5ca2541f2af5462 input=a9049054013a1b77]*/
|
||||
|
|
4
Modules/clinic/signalmodule.c.h
generated
4
Modules/clinic/signalmodule.c.h
generated
|
@ -656,7 +656,7 @@ signal_pthread_kill(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
|||
if (!_PyArg_CheckPositional("pthread_kill", nargs, 2, 2)) {
|
||||
goto exit;
|
||||
}
|
||||
if (!PyLong_Check(args[0])) {
|
||||
if (!PyIndex_Check(args[0])) {
|
||||
_PyArg_BadArgument("pthread_kill", "argument 1", "int", args[0]);
|
||||
goto exit;
|
||||
}
|
||||
|
@ -779,4 +779,4 @@ exit:
|
|||
#ifndef SIGNAL_PIDFD_SEND_SIGNAL_METHODDEF
|
||||
#define SIGNAL_PIDFD_SEND_SIGNAL_METHODDEF
|
||||
#endif /* !defined(SIGNAL_PIDFD_SEND_SIGNAL_METHODDEF) */
|
||||
/*[clinic end generated code: output=a8b1ac2fc44a007e input=a9049054013a1b77]*/
|
||||
/*[clinic end generated code: output=48bfaffeb25df5d2 input=a9049054013a1b77]*/
|
||||
|
|
|
@ -839,10 +839,13 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
|
|||
unsigned long *p = va_arg(*p_va, unsigned long *);
|
||||
HANDLE_NULLABLE;
|
||||
unsigned long ival;
|
||||
if (PyLong_Check(arg))
|
||||
ival = PyLong_AsUnsignedLongMask(arg);
|
||||
else
|
||||
if (!PyIndex_Check(arg)) {
|
||||
return converterr(nullable, "int", arg, msgbuf, bufsize);
|
||||
}
|
||||
ival = PyLong_AsUnsignedLongMask(arg);
|
||||
if (ival == (unsigned long)(long)-1 && PyErr_Occurred()) {
|
||||
RETURN_ERR_OCCURRED;
|
||||
}
|
||||
*p = ival;
|
||||
break;
|
||||
}
|
||||
|
@ -862,10 +865,13 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
|
|||
unsigned long long *p = va_arg(*p_va, unsigned long long *);
|
||||
HANDLE_NULLABLE;
|
||||
unsigned long long ival;
|
||||
if (PyLong_Check(arg))
|
||||
ival = PyLong_AsUnsignedLongLongMask(arg);
|
||||
else
|
||||
if (!PyIndex_Check(arg)) {
|
||||
return converterr(nullable, "int", arg, msgbuf, bufsize);
|
||||
}
|
||||
ival = PyLong_AsUnsignedLongLongMask(arg);
|
||||
if (ival == (unsigned long long)(long long)-1 && PyErr_Occurred()) {
|
||||
RETURN_ERR_OCCURRED;
|
||||
}
|
||||
*p = ival;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -386,7 +386,7 @@ class unsigned_long_converter(CConverter):
|
|||
def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None:
|
||||
if self.format_unit == 'k':
|
||||
return self.format_code("""
|
||||
if (!PyLong_Check({argname})) {{{{
|
||||
if (!PyIndex_Check({argname})) {{{{
|
||||
{bad_argument}
|
||||
goto exit;
|
||||
}}}}
|
||||
|
@ -444,7 +444,7 @@ class unsigned_long_long_converter(CConverter):
|
|||
def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None:
|
||||
if self.format_unit == 'K':
|
||||
return self.format_code("""
|
||||
if (!PyLong_Check({argname})) {{{{
|
||||
if (!PyIndex_Check({argname})) {{{{
|
||||
{bad_argument}
|
||||
goto exit;
|
||||
}}}}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue