From 7cb7bcff20a386bba59cbc51e2419542de358bd2 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 26 Jul 2018 13:22:16 +0300 Subject: bpo-20260: Implement non-bitwise unsigned int converters for Argument Clinic. (GH-8434) --- Doc/howto/clinic.rst | 6 ++ Include/longobject.h | 8 ++ Lib/test/test_hashlib.py | 4 +- Lib/test/test_poll.py | 4 +- .../2018-07-24-00-11-44.bpo-20260.klmmqI.rst | 1 + Modules/_blake2/blake2b_impl.c | 31 ++----- Modules/_blake2/blake2s_impl.c | 31 ++----- Modules/_blake2/clinic/blake2b_impl.c.h | 18 ++-- Modules/_blake2/clinic/blake2s_impl.c.h | 18 ++-- Modules/clinic/selectmodule.c.h | 10 +-- Modules/selectmodule.c | 34 ++------ Objects/longobject.c | 96 ++++++++++++++++++++++ Tools/clinic/clinic.py | 34 +++++--- 13 files changed, 183 insertions(+), 112 deletions(-) create mode 100644 Misc/NEWS.d/next/Tools-Demos/2018-07-24-00-11-44.bpo-20260.klmmqI.rst diff --git a/Doc/howto/clinic.rst b/Doc/howto/clinic.rst index 695fbb1..c75c31c 100644 --- a/Doc/howto/clinic.rst +++ b/Doc/howto/clinic.rst @@ -878,6 +878,12 @@ converter:: Write a pickled representation of obj to the open file. [clinic start generated code]*/ +One advantage of real converters is that they're more flexible than legacy +converters. For example, the ``unsigned_int`` converter (and all the +``unsigned_`` converters) can be specified without ``bitwise=True``. Their +default behavior performs range checking on the value, and they won't accept +negative numbers. You just can't do that with a legacy converter! + Argument Clinic will show you all the converters it has available. For each converter it'll show you all the parameters it accepts, along with the default value for each parameter. diff --git a/Include/longobject.h b/Include/longobject.h index 7bdd047..82c06c9 100644 --- a/Include/longobject.h +++ b/Include/longobject.h @@ -65,6 +65,14 @@ PyAPI_FUNC(PyObject *) PyLong_GetInfo(void); # error "void* different in size from int, long and long long" #endif /* SIZEOF_VOID_P */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) _PyLong_UnsignedShort_Converter(PyObject *, void *); +PyAPI_FUNC(int) _PyLong_UnsignedInt_Converter(PyObject *, void *); +PyAPI_FUNC(int) _PyLong_UnsignedLong_Converter(PyObject *, void *); +PyAPI_FUNC(int) _PyLong_UnsignedLongLong_Converter(PyObject *, void *); +PyAPI_FUNC(int) _PyLong_Size_t_Converter(PyObject *, void *); +#endif + /* Used by Python/mystrtoul.c, _PyBytes_FromHex(), _PyBytes_DecodeEscapeRecode(), etc. */ #ifndef Py_LIMITED_API diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py index 5b0218b..0f76b24 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -560,12 +560,12 @@ class HashLibTestCase(unittest.TestCase): constructor(leaf_size=0) constructor(leaf_size=(1<<32)-1) - self.assertRaises(OverflowError, constructor, leaf_size=-1) + self.assertRaises(ValueError, constructor, leaf_size=-1) self.assertRaises(OverflowError, constructor, leaf_size=1<<32) constructor(node_offset=0) constructor(node_offset=max_offset) - self.assertRaises(OverflowError, constructor, node_offset=-1) + self.assertRaises(ValueError, constructor, node_offset=-1) self.assertRaises(OverflowError, constructor, node_offset=max_offset+1) constructor( diff --git a/Lib/test/test_poll.py b/Lib/test/test_poll.py index d593495..445032d 100644 --- a/Lib/test/test_poll.py +++ b/Lib/test/test_poll.py @@ -159,9 +159,9 @@ class PollTests(unittest.TestCase): self.fail('Overflow must have occurred') # Issues #15989, #17919 - self.assertRaises(OverflowError, pollster.register, 0, -1) + self.assertRaises(ValueError, pollster.register, 0, -1) self.assertRaises(OverflowError, pollster.register, 0, 1 << 64) - self.assertRaises(OverflowError, pollster.modify, 1, -1) + self.assertRaises(ValueError, pollster.modify, 1, -1) self.assertRaises(OverflowError, pollster.modify, 1, 1 << 64) @cpython_only diff --git a/Misc/NEWS.d/next/Tools-Demos/2018-07-24-00-11-44.bpo-20260.klmmqI.rst b/Misc/NEWS.d/next/Tools-Demos/2018-07-24-00-11-44.bpo-20260.klmmqI.rst new file mode 100644 index 0000000..f8d0df0 --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2018-07-24-00-11-44.bpo-20260.klmmqI.rst @@ -0,0 +1 @@ +Argument Clinic now has non-bitwise unsigned int converters. diff --git a/Modules/_blake2/blake2b_impl.c b/Modules/_blake2/blake2b_impl.c index 822b9f2..92d7c5c 100644 --- a/Modules/_blake2/blake2b_impl.c +++ b/Modules/_blake2/blake2b_impl.c @@ -75,8 +75,8 @@ _blake2b.blake2b.__new__ as py_blake2b_new person: Py_buffer = None fanout: int = 1 depth: int = 1 - leaf_size as leaf_size_obj: object = NULL - node_offset as node_offset_obj: object = NULL + leaf_size: unsigned_long = 0 + node_offset: unsigned_long_long = 0 node_depth: int = 0 inner_size: int = 0 last_node: bool = False @@ -87,17 +87,14 @@ Return a new BLAKE2b hash object. static PyObject * py_blake2b_new_impl(PyTypeObject *type, PyObject *data, int digest_size, Py_buffer *key, Py_buffer *salt, Py_buffer *person, - int fanout, int depth, PyObject *leaf_size_obj, - PyObject *node_offset_obj, int node_depth, + int fanout, int depth, unsigned long leaf_size, + unsigned long long node_offset, int node_depth, int inner_size, int last_node) -/*[clinic end generated code: output=7506d8d890e5f13b input=e41548dfa0866031]*/ +/*[clinic end generated code: output=65e732c66c2297a0 input=75ab5196b695adee]*/ { BLAKE2bObject *self = NULL; Py_buffer buf; - unsigned long leaf_size = 0; - unsigned long long node_offset = 0; - self = new_BLAKE2bObject(type); if (self == NULL) { goto error; @@ -152,25 +149,13 @@ py_blake2b_new_impl(PyTypeObject *type, PyObject *data, int digest_size, } self->param.depth = (uint8_t)depth; - if (leaf_size_obj != NULL) { - leaf_size = PyLong_AsUnsignedLong(leaf_size_obj); - if (leaf_size == (unsigned long) -1 && PyErr_Occurred()) { - goto error; - } - if (leaf_size > 0xFFFFFFFFU) { - PyErr_SetString(PyExc_OverflowError, "leaf_size is too large"); - goto error; - } + if (leaf_size > 0xFFFFFFFFU) { + PyErr_SetString(PyExc_OverflowError, "leaf_size is too large"); + goto error; } // NB: Simple assignment here would be incorrect on big endian platforms. store32(&(self->param.leaf_length), leaf_size); - if (node_offset_obj != NULL) { - node_offset = PyLong_AsUnsignedLongLong(node_offset_obj); - if (node_offset == (unsigned long long) -1 && PyErr_Occurred()) { - goto error; - } - } #ifdef HAVE_BLAKE2S if (node_offset > 0xFFFFFFFFFFFFULL) { /* maximum 2**48 - 1 */ diff --git a/Modules/_blake2/blake2s_impl.c b/Modules/_blake2/blake2s_impl.c index 3b76c9c..8c49082 100644 --- a/Modules/_blake2/blake2s_impl.c +++ b/Modules/_blake2/blake2s_impl.c @@ -75,8 +75,8 @@ _blake2s.blake2s.__new__ as py_blake2s_new person: Py_buffer = None fanout: int = 1 depth: int = 1 - leaf_size as leaf_size_obj: object = NULL - node_offset as node_offset_obj: object = NULL + leaf_size: unsigned_long = 0 + node_offset: unsigned_long_long = 0 node_depth: int = 0 inner_size: int = 0 last_node: bool = False @@ -87,17 +87,14 @@ Return a new BLAKE2s hash object. static PyObject * py_blake2s_new_impl(PyTypeObject *type, PyObject *data, int digest_size, Py_buffer *key, Py_buffer *salt, Py_buffer *person, - int fanout, int depth, PyObject *leaf_size_obj, - PyObject *node_offset_obj, int node_depth, + int fanout, int depth, unsigned long leaf_size, + unsigned long long node_offset, int node_depth, int inner_size, int last_node) -/*[clinic end generated code: output=fe060b258a8cbfc6 input=458cfdcb3d0d47ff]*/ +/*[clinic end generated code: output=b95806be0514dcf7 input=f18d6efd9b9a1271]*/ { BLAKE2sObject *self = NULL; Py_buffer buf; - unsigned long leaf_size = 0; - unsigned long long node_offset = 0; - self = new_BLAKE2sObject(type); if (self == NULL) { goto error; @@ -152,25 +149,13 @@ py_blake2s_new_impl(PyTypeObject *type, PyObject *data, int digest_size, } self->param.depth = (uint8_t)depth; - if (leaf_size_obj != NULL) { - leaf_size = PyLong_AsUnsignedLong(leaf_size_obj); - if (leaf_size == (unsigned long) -1 && PyErr_Occurred()) { - goto error; - } - if (leaf_size > 0xFFFFFFFFU) { - PyErr_SetString(PyExc_OverflowError, "leaf_size is too large"); - goto error; - } + if (leaf_size > 0xFFFFFFFFU) { + PyErr_SetString(PyExc_OverflowError, "leaf_size is too large"); + goto error; } // NB: Simple assignment here would be incorrect on big endian platforms. store32(&(self->param.leaf_length), leaf_size); - if (node_offset_obj != NULL) { - node_offset = PyLong_AsUnsignedLongLong(node_offset_obj); - if (node_offset == (unsigned long long) -1 && PyErr_Occurred()) { - goto error; - } - } #ifdef HAVE_BLAKE2S if (node_offset > 0xFFFFFFFFFFFFULL) { /* maximum 2**48 - 1 */ diff --git a/Modules/_blake2/clinic/blake2b_impl.c.h b/Modules/_blake2/clinic/blake2b_impl.c.h index 71c073a..3cb70fb 100644 --- a/Modules/_blake2/clinic/blake2b_impl.c.h +++ b/Modules/_blake2/clinic/blake2b_impl.c.h @@ -5,7 +5,7 @@ preserve PyDoc_STRVAR(py_blake2b_new__doc__, "blake2b(string=None, *, digest_size=_blake2b.blake2b.MAX_DIGEST_SIZE,\n" " key=None, salt=None, person=None, fanout=1, depth=1,\n" -" leaf_size=None, node_offset=None, node_depth=0, inner_size=0,\n" +" leaf_size=0, node_offset=0, node_depth=0, inner_size=0,\n" " last_node=False)\n" "--\n" "\n" @@ -14,8 +14,8 @@ PyDoc_STRVAR(py_blake2b_new__doc__, static PyObject * py_blake2b_new_impl(PyTypeObject *type, PyObject *data, int digest_size, Py_buffer *key, Py_buffer *salt, Py_buffer *person, - int fanout, int depth, PyObject *leaf_size_obj, - PyObject *node_offset_obj, int node_depth, + int fanout, int depth, unsigned long leaf_size, + unsigned long long node_offset, int node_depth, int inner_size, int last_node); static PyObject * @@ -23,7 +23,7 @@ py_blake2b_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; static const char * const _keywords[] = {"string", "digest_size", "key", "salt", "person", "fanout", "depth", "leaf_size", "node_offset", "node_depth", "inner_size", "last_node", NULL}; - static _PyArg_Parser _parser = {"|O$iy*y*y*iiOOiip:blake2b", _keywords, 0}; + static _PyArg_Parser _parser = {"|O$iy*y*y*iiO&O&iip:blake2b", _keywords, 0}; PyObject *data = NULL; int digest_size = BLAKE2B_OUTBYTES; Py_buffer key = {NULL, NULL}; @@ -31,17 +31,17 @@ py_blake2b_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) Py_buffer person = {NULL, NULL}; int fanout = 1; int depth = 1; - PyObject *leaf_size_obj = NULL; - PyObject *node_offset_obj = NULL; + unsigned long leaf_size = 0; + unsigned long long node_offset = 0; int node_depth = 0; int inner_size = 0; int last_node = 0; if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser, - &data, &digest_size, &key, &salt, &person, &fanout, &depth, &leaf_size_obj, &node_offset_obj, &node_depth, &inner_size, &last_node)) { + &data, &digest_size, &key, &salt, &person, &fanout, &depth, _PyLong_UnsignedLong_Converter, &leaf_size, _PyLong_UnsignedLongLong_Converter, &node_offset, &node_depth, &inner_size, &last_node)) { goto exit; } - return_value = py_blake2b_new_impl(type, data, digest_size, &key, &salt, &person, fanout, depth, leaf_size_obj, node_offset_obj, node_depth, inner_size, last_node); + return_value = py_blake2b_new_impl(type, data, digest_size, &key, &salt, &person, fanout, depth, leaf_size, node_offset, node_depth, inner_size, last_node); exit: /* Cleanup for key */ @@ -122,4 +122,4 @@ _blake2b_blake2b_hexdigest(BLAKE2bObject *self, PyObject *Py_UNUSED(ignored)) { return _blake2b_blake2b_hexdigest_impl(self); } -/*[clinic end generated code: output=535a54852c98e51c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=afc5c45dff0a24f9 input=a9049054013a1b77]*/ diff --git a/Modules/_blake2/clinic/blake2s_impl.c.h b/Modules/_blake2/clinic/blake2s_impl.c.h index ca908d3..b444f7b 100644 --- a/Modules/_blake2/clinic/blake2s_impl.c.h +++ b/Modules/_blake2/clinic/blake2s_impl.c.h @@ -5,7 +5,7 @@ preserve PyDoc_STRVAR(py_blake2s_new__doc__, "blake2s(string=None, *, digest_size=_blake2s.blake2s.MAX_DIGEST_SIZE,\n" " key=None, salt=None, person=None, fanout=1, depth=1,\n" -" leaf_size=None, node_offset=None, node_depth=0, inner_size=0,\n" +" leaf_size=0, node_offset=0, node_depth=0, inner_size=0,\n" " last_node=False)\n" "--\n" "\n" @@ -14,8 +14,8 @@ PyDoc_STRVAR(py_blake2s_new__doc__, static PyObject * py_blake2s_new_impl(PyTypeObject *type, PyObject *data, int digest_size, Py_buffer *key, Py_buffer *salt, Py_buffer *person, - int fanout, int depth, PyObject *leaf_size_obj, - PyObject *node_offset_obj, int node_depth, + int fanout, int depth, unsigned long leaf_size, + unsigned long long node_offset, int node_depth, int inner_size, int last_node); static PyObject * @@ -23,7 +23,7 @@ py_blake2s_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; static const char * const _keywords[] = {"string", "digest_size", "key", "salt", "person", "fanout", "depth", "leaf_size", "node_offset", "node_depth", "inner_size", "last_node", NULL}; - static _PyArg_Parser _parser = {"|O$iy*y*y*iiOOiip:blake2s", _keywords, 0}; + static _PyArg_Parser _parser = {"|O$iy*y*y*iiO&O&iip:blake2s", _keywords, 0}; PyObject *data = NULL; int digest_size = BLAKE2S_OUTBYTES; Py_buffer key = {NULL, NULL}; @@ -31,17 +31,17 @@ py_blake2s_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) Py_buffer person = {NULL, NULL}; int fanout = 1; int depth = 1; - PyObject *leaf_size_obj = NULL; - PyObject *node_offset_obj = NULL; + unsigned long leaf_size = 0; + unsigned long long node_offset = 0; int node_depth = 0; int inner_size = 0; int last_node = 0; if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser, - &data, &digest_size, &key, &salt, &person, &fanout, &depth, &leaf_size_obj, &node_offset_obj, &node_depth, &inner_size, &last_node)) { + &data, &digest_size, &key, &salt, &person, &fanout, &depth, _PyLong_UnsignedLong_Converter, &leaf_size, _PyLong_UnsignedLongLong_Converter, &node_offset, &node_depth, &inner_size, &last_node)) { goto exit; } - return_value = py_blake2s_new_impl(type, data, digest_size, &key, &salt, &person, fanout, depth, leaf_size_obj, node_offset_obj, node_depth, inner_size, last_node); + return_value = py_blake2s_new_impl(type, data, digest_size, &key, &salt, &person, fanout, depth, leaf_size, node_offset, node_depth, inner_size, last_node); exit: /* Cleanup for key */ @@ -122,4 +122,4 @@ _blake2s_blake2s_hexdigest(BLAKE2sObject *self, PyObject *Py_UNUSED(ignored)) { return _blake2s_blake2s_hexdigest_impl(self); } -/*[clinic end generated code: output=535ea7903f9ccf76 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b705723d16f21f57 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/selectmodule.c.h b/Modules/clinic/selectmodule.c.h index f66ceaa..b87b390 100644 --- a/Modules/clinic/selectmodule.c.h +++ b/Modules/clinic/selectmodule.c.h @@ -83,7 +83,7 @@ select_poll_register(pollObject *self, PyObject *const *args, Py_ssize_t nargs) unsigned short eventmask = POLLIN | POLLPRI | POLLOUT; if (!_PyArg_ParseStack(args, nargs, "O&|O&:register", - fildes_converter, &fd, ushort_converter, &eventmask)) { + fildes_converter, &fd, _PyLong_UnsignedShort_Converter, &eventmask)) { goto exit; } return_value = select_poll_register_impl(self, fd, eventmask); @@ -122,7 +122,7 @@ select_poll_modify(pollObject *self, PyObject *const *args, Py_ssize_t nargs) unsigned short eventmask; if (!_PyArg_ParseStack(args, nargs, "O&O&:modify", - fildes_converter, &fd, ushort_converter, &eventmask)) { + fildes_converter, &fd, _PyLong_UnsignedShort_Converter, &eventmask)) { goto exit; } return_value = select_poll_modify_impl(self, fd, eventmask); @@ -229,7 +229,7 @@ select_devpoll_register(devpollObject *self, PyObject *const *args, Py_ssize_t n unsigned short eventmask = POLLIN | POLLPRI | POLLOUT; if (!_PyArg_ParseStack(args, nargs, "O&|O&:register", - fildes_converter, &fd, ushort_converter, &eventmask)) { + fildes_converter, &fd, _PyLong_UnsignedShort_Converter, &eventmask)) { goto exit; } return_value = select_devpoll_register_impl(self, fd, eventmask); @@ -269,7 +269,7 @@ select_devpoll_modify(devpollObject *self, PyObject *const *args, Py_ssize_t nar unsigned short eventmask = POLLIN | POLLPRI | POLLOUT; if (!_PyArg_ParseStack(args, nargs, "O&|O&:modify", - fildes_converter, &fd, ushort_converter, &eventmask)) { + fildes_converter, &fd, _PyLong_UnsignedShort_Converter, &eventmask)) { goto exit; } return_value = select_devpoll_modify_impl(self, fd, eventmask); @@ -1047,4 +1047,4 @@ exit: #ifndef SELECT_KQUEUE_CONTROL_METHODDEF #define SELECT_KQUEUE_CONTROL_METHODDEF #endif /* !defined(SELECT_KQUEUE_CONTROL_METHODDEF) */ -/*[clinic end generated code: output=3e425445d49c49e2 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=561bec8bcb0e00c5 input=a9049054013a1b77]*/ diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index 9ad6f8b..15aca27 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -430,30 +430,12 @@ update_ufd_array(pollObject *self) return 1; } -static int -ushort_converter(PyObject *obj, void *ptr) -{ - unsigned long uval; - - uval = PyLong_AsUnsignedLong(obj); - if (uval == (unsigned long)-1 && PyErr_Occurred()) - return 0; - if (uval > USHRT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "Python int too large for C unsigned short"); - return 0; - } - - *(unsigned short *)ptr = Py_SAFE_DOWNCAST(uval, unsigned long, unsigned short); - return 1; -} - /*[clinic input] select.poll.register fd: fildes either an integer, or an object with a fileno() method returning an int - eventmask: object(converter="ushort_converter", type="unsigned short", c_default="POLLIN | POLLPRI | POLLOUT") = POLLIN | POLLPRI | POLLOUT + eventmask: unsigned_short(c_default="POLLIN | POLLPRI | POLLOUT") = POLLIN | POLLPRI | POLLOUT an optional bitmask describing the type of events to check for / @@ -462,7 +444,7 @@ Register a file descriptor with the polling object. static PyObject * select_poll_register_impl(pollObject *self, int fd, unsigned short eventmask) -/*[clinic end generated code: output=0dc7173c800a4a65 input=499d96a2836217f5]*/ +/*[clinic end generated code: output=0dc7173c800a4a65 input=f18711d9bb021e25]*/ { PyObject *key, *value; int err; @@ -495,7 +477,7 @@ select.poll.modify fd: fildes either an integer, or an object with a fileno() method returning an int - eventmask: object(converter="ushort_converter", type="unsigned short") + eventmask: unsigned_short a bitmask describing the type of events to check for / @@ -504,7 +486,7 @@ Modify an already registered file descriptor. static PyObject * select_poll_modify_impl(pollObject *self, int fd, unsigned short eventmask) -/*[clinic end generated code: output=1a7b88bf079eff17 input=b8e0e04a1264b78f]*/ +/*[clinic end generated code: output=1a7b88bf079eff17 input=a8e383df075c32cf]*/ { PyObject *key, *value; int err; @@ -832,7 +814,7 @@ select.devpoll.register fd: fildes either an integer, or an object with a fileno() method returning an int - eventmask: object(converter="ushort_converter", type="unsigned short", c_default="POLLIN | POLLPRI | POLLOUT") = POLLIN | POLLPRI | POLLOUT + eventmask: unsigned_short(c_default="POLLIN | POLLPRI | POLLOUT") = POLLIN | POLLPRI | POLLOUT an optional bitmask describing the type of events to check for / @@ -842,7 +824,7 @@ Register a file descriptor with the polling object. static PyObject * select_devpoll_register_impl(devpollObject *self, int fd, unsigned short eventmask) -/*[clinic end generated code: output=6e07fe8b74abba0c input=389a0785bb8feb57]*/ +/*[clinic end generated code: output=6e07fe8b74abba0c input=5bd7cacc47a8ee46]*/ { return internal_devpoll_register(self, fd, eventmask, 0); } @@ -853,7 +835,7 @@ select.devpoll.modify fd: fildes either an integer, or an object with a fileno() method returning an int - eventmask: object(converter="ushort_converter", type="unsigned short", c_default="POLLIN | POLLPRI | POLLOUT") = POLLIN | POLLPRI | POLLOUT + eventmask: unsigned_short(c_default="POLLIN | POLLPRI | POLLOUT") = POLLIN | POLLPRI | POLLOUT an optional bitmask describing the type of events to check for / @@ -863,7 +845,7 @@ Modify a possible already registered file descriptor. static PyObject * select_devpoll_modify_impl(devpollObject *self, int fd, unsigned short eventmask) -/*[clinic end generated code: output=bc2e6d23aaff98b4 input=f0d7de3889cc55fb]*/ +/*[clinic end generated code: output=bc2e6d23aaff98b4 input=48a820fc5967165d]*/ static PyObject * devpoll_modify(devpollObject *self, PyObject *args) { diff --git a/Objects/longobject.c b/Objects/longobject.c index ebf87a5..399d354 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -1439,6 +1439,102 @@ PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow) return res; } +int +_PyLong_UnsignedShort_Converter(PyObject *obj, void *ptr) +{ + unsigned long uval; + + if (PyLong_Check(obj) && _PyLong_Sign(obj) < 0) { + PyErr_SetString(PyExc_ValueError, "value must be positive"); + return 0; + } + uval = PyLong_AsUnsignedLong(obj); + if (uval == (unsigned long)-1 && PyErr_Occurred()) + return 0; + if (uval > USHRT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "Python int too large for C unsigned short"); + return 0; + } + + *(unsigned short *)ptr = Py_SAFE_DOWNCAST(uval, unsigned long, unsigned short); + return 1; +} + +int +_PyLong_UnsignedInt_Converter(PyObject *obj, void *ptr) +{ + unsigned long uval; + + if (PyLong_Check(obj) && _PyLong_Sign(obj) < 0) { + PyErr_SetString(PyExc_ValueError, "value must be positive"); + return 0; + } + uval = PyLong_AsUnsignedLong(obj); + if (uval == (unsigned long)-1 && PyErr_Occurred()) + return 0; + if (uval > UINT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "Python int too large for C unsigned int"); + return 0; + } + + *(unsigned int *)ptr = Py_SAFE_DOWNCAST(uval, unsigned long, unsigned int); + return 1; +} + +int +_PyLong_UnsignedLong_Converter(PyObject *obj, void *ptr) +{ + unsigned long uval; + + if (PyLong_Check(obj) && _PyLong_Sign(obj) < 0) { + PyErr_SetString(PyExc_ValueError, "value must be positive"); + return 0; + } + uval = PyLong_AsUnsignedLong(obj); + if (uval == (unsigned long)-1 && PyErr_Occurred()) + return 0; + + *(unsigned long *)ptr = uval; + return 1; +} + +int +_PyLong_UnsignedLongLong_Converter(PyObject *obj, void *ptr) +{ + unsigned long long uval; + + if (PyLong_Check(obj) && _PyLong_Sign(obj) < 0) { + PyErr_SetString(PyExc_ValueError, "value must be positive"); + return 0; + } + uval = PyLong_AsUnsignedLongLong(obj); + if (uval == (unsigned long long)-1 && PyErr_Occurred()) + return 0; + + *(unsigned long long *)ptr = uval; + return 1; +} + +int +_PyLong_Size_t_Converter(PyObject *obj, void *ptr) +{ + size_t uval; + + if (PyLong_Check(obj) && _PyLong_Sign(obj) < 0) { + PyErr_SetString(PyExc_ValueError, "value must be positive"); + return 0; + } + uval = PyLong_AsSize_t(obj); + if (uval == (size_t)-1 && PyErr_Occurred()) + return 0; + + *(size_t *)ptr = uval; + return 1; +} + + #define CHECK_BINOP(v,w) \ do { \ if (!PyLong_Check(v) || !PyLong_Check(w)) \ diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index e7c7eb4..653afbe 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -2603,12 +2603,13 @@ class short_converter(CConverter): class unsigned_short_converter(CConverter): type = 'unsigned short' default_type = int - format_unit = 'H' c_ignored_default = "0" def converter_init(self, *, bitwise=False): - if not bitwise: - fail("Unsigned shorts must be bitwise (for now).") + if bitwise: + self.format_unit = 'H' + else: + self.converter = '_PyLong_UnsignedShort_Converter' @add_legacy_c_converter('C', accept={str}) class int_converter(CConverter): @@ -2628,12 +2629,13 @@ class int_converter(CConverter): class unsigned_int_converter(CConverter): type = 'unsigned int' default_type = int - format_unit = 'I' c_ignored_default = "0" def converter_init(self, *, bitwise=False): - if not bitwise: - fail("Unsigned ints must be bitwise (for now).") + if bitwise: + self.format_unit = 'I' + else: + self.converter = '_PyLong_UnsignedInt_Converter' class long_converter(CConverter): type = 'long' @@ -2644,12 +2646,13 @@ class long_converter(CConverter): class unsigned_long_converter(CConverter): type = 'unsigned long' default_type = int - format_unit = 'k' c_ignored_default = "0" def converter_init(self, *, bitwise=False): - if not bitwise: - fail("Unsigned longs must be bitwise (for now).") + if bitwise: + self.format_unit = 'k' + else: + self.converter = '_PyLong_UnsignedLong_Converter' class long_long_converter(CConverter): type = 'long long' @@ -2660,13 +2663,13 @@ class long_long_converter(CConverter): class unsigned_long_long_converter(CConverter): type = 'unsigned long long' default_type = int - format_unit = 'K' c_ignored_default = "0" def converter_init(self, *, bitwise=False): - if not bitwise: - fail("Unsigned long long must be bitwise (for now).") - + if bitwise: + self.format_unit = 'K' + else: + self.converter = '_PyLong_UnsignedLongLong_Converter' class Py_ssize_t_converter(CConverter): type = 'Py_ssize_t' @@ -2693,6 +2696,11 @@ class slice_index_converter(CConverter): else: fail("slice_index_converter: illegal 'accept' argument " + repr(accept)) +class size_t_converter(CConverter): + type = 'size_t' + converter = '_PyLong_Size_t_Converter' + c_ignored_default = "0" + class float_converter(CConverter): type = 'float' -- cgit v0.12