mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	[3.14] Revert "gh-112068: C API: Add support of nullable arguments in PyArg_Parse (GH-121303)" (GH-136991) (#137006)
This commit is contained in:
		
							parent
							
								
									c328d140eb
								
							
						
					
					
						commit
						805daa2edb
					
				
					 12 changed files with 144 additions and 322 deletions
				
			
		|  | @ -113,18 +113,14 @@ There are three ways strings and buffers can be converted to C: | ||||||
| ``z`` (:class:`str` or ``None``) [const char \*] | ``z`` (:class:`str` or ``None``) [const char \*] | ||||||
|    Like ``s``, but the Python object may also be ``None``, in which case the C |    Like ``s``, but the Python object may also be ``None``, in which case the C | ||||||
|    pointer is set to ``NULL``. |    pointer is set to ``NULL``. | ||||||
|    It is the same as ``s?`` with the C pointer was initialized to ``NULL``. |  | ||||||
| 
 | 
 | ||||||
| ``z*`` (:class:`str`, :term:`bytes-like object` or ``None``) [Py_buffer] | ``z*`` (:class:`str`, :term:`bytes-like object` or ``None``) [Py_buffer] | ||||||
|    Like ``s*``, but the Python object may also be ``None``, in which case the |    Like ``s*``, but the Python object may also be ``None``, in which case the | ||||||
|    ``buf`` member of the :c:type:`Py_buffer` structure is set to ``NULL``. |    ``buf`` member of the :c:type:`Py_buffer` structure is set to ``NULL``. | ||||||
|    It is the same as ``s*?`` with the ``buf`` member of the :c:type:`Py_buffer` |  | ||||||
|    structure was initialized to ``NULL``. |  | ||||||
| 
 | 
 | ||||||
| ``z#`` (:class:`str`, read-only :term:`bytes-like object` or ``None``) [const char \*, :c:type:`Py_ssize_t`] | ``z#`` (:class:`str`, read-only :term:`bytes-like object` or ``None``) [const char \*, :c:type:`Py_ssize_t`] | ||||||
|    Like ``s#``, but the Python object may also be ``None``, in which case the C |    Like ``s#``, but the Python object may also be ``None``, in which case the C | ||||||
|    pointer is set to ``NULL``. |    pointer is set to ``NULL``. | ||||||
|    It is the same as ``s#?`` with the C pointer was initialized to ``NULL``. |  | ||||||
| 
 | 
 | ||||||
| ``y`` (read-only :term:`bytes-like object`) [const char \*] | ``y`` (read-only :term:`bytes-like object`) [const char \*] | ||||||
|    This format converts a bytes-like object to a C pointer to a |    This format converts a bytes-like object to a C pointer to a | ||||||
|  | @ -387,17 +383,6 @@ Other objects | ||||||
|       Non-tuple sequences are deprecated if *items* contains format units |       Non-tuple sequences are deprecated if *items* contains format units | ||||||
|       which store a borrowed buffer or a borrowed reference. |       which store a borrowed buffer or a borrowed reference. | ||||||
| 
 | 
 | ||||||
| ``unit?`` (anything or ``None``) [*matching-variable(s)*] |  | ||||||
|    ``?`` modifies the behavior of the preceding format unit. |  | ||||||
|    The C variable(s) corresponding to that parameter should be initialized |  | ||||||
|    to their default value --- when the argument is ``None``, |  | ||||||
|    :c:func:`PyArg_ParseTuple` does not touch the contents of the corresponding |  | ||||||
|    C variable(s). |  | ||||||
|    If the argument is not ``None``, it is parsed according to the specified |  | ||||||
|    format unit. |  | ||||||
| 
 |  | ||||||
|    .. versionadded:: 3.14 |  | ||||||
| 
 |  | ||||||
| A few other characters have a meaning in a format string.  These may not occur | A few other characters have a meaning in a format string.  These may not occur | ||||||
| inside nested parentheses.  They are: | inside nested parentheses.  They are: | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -2940,11 +2940,6 @@ New features | ||||||
|   file. |   file. | ||||||
|   (Contributed by Victor Stinner in :gh:`127350`.) |   (Contributed by Victor Stinner in :gh:`127350`.) | ||||||
| 
 | 
 | ||||||
| * Add support of nullable arguments in :c:func:`PyArg_ParseTuple` and |  | ||||||
|   similar functions. |  | ||||||
|   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 | * The ``k`` and ``K`` formats in :c:func:`PyArg_ParseTuple` and | ||||||
|   similar functions now use :meth:`~object.__index__` if available, |   similar functions now use :meth:`~object.__index__` if available, | ||||||
|   like all other integer formats. |   like all other integer formats. | ||||||
|  |  | ||||||
|  | @ -1389,123 +1389,6 @@ def test_nested_sequence(self): | ||||||
|                     "argument 1 must be sequence of length 1, not 0"): |                     "argument 1 must be sequence of length 1, not 0"): | ||||||
|                 parse(([],), {}, '(' + f + ')', ['a']) |                 parse(([],), {}, '(' + f + ')', ['a']) | ||||||
| 
 | 
 | ||||||
|     def test_specific_type_errors(self): |  | ||||||
|         parse = _testcapi.parse_tuple_and_keywords |  | ||||||
| 
 |  | ||||||
|         def check(format, arg, expected, got='list'): |  | ||||||
|             errmsg = f'must be {expected}, not {got}' |  | ||||||
|             with self.assertRaisesRegex(TypeError, errmsg): |  | ||||||
|                 parse((arg,), {}, format, ['a']) |  | ||||||
| 
 |  | ||||||
|         check('k', [], 'int') |  | ||||||
|         check('k?', [], 'int or None') |  | ||||||
|         check('K', [], 'int') |  | ||||||
|         check('K?', [], 'int or None') |  | ||||||
|         check('c', [], 'a byte string of length 1') |  | ||||||
|         check('c?', [], 'a byte string of length 1 or None') |  | ||||||
|         check('c', b'abc', 'a byte string of length 1', |  | ||||||
|               'a bytes object of length 3') |  | ||||||
|         check('c?', b'abc', 'a byte string of length 1 or None', |  | ||||||
|               'a bytes object of length 3') |  | ||||||
|         check('c', bytearray(b'abc'), 'a byte string of length 1', |  | ||||||
|               'a bytearray object of length 3') |  | ||||||
|         check('c?', bytearray(b'abc'), 'a byte string of length 1 or None', |  | ||||||
|               'a bytearray object of length 3') |  | ||||||
|         check('C', [], 'a unicode character') |  | ||||||
|         check('C?', [], 'a unicode character or None') |  | ||||||
|         check('C', 'abc', 'a unicode character', |  | ||||||
|               'a string of length 3') |  | ||||||
|         check('C?', 'abc', 'a unicode character or None', |  | ||||||
|               'a string of length 3') |  | ||||||
|         check('s', [], 'str') |  | ||||||
|         check('s?', [], 'str or None') |  | ||||||
|         check('z', [], 'str or None') |  | ||||||
|         check('z?', [], 'str or None') |  | ||||||
|         check('es', [], 'str') |  | ||||||
|         check('es?', [], 'str or None') |  | ||||||
|         check('es#', [], 'str') |  | ||||||
|         check('es#?', [], 'str or None') |  | ||||||
|         check('et', [], 'str, bytes or bytearray') |  | ||||||
|         check('et?', [], 'str, bytes, bytearray or None') |  | ||||||
|         check('et#', [], 'str, bytes or bytearray') |  | ||||||
|         check('et#?', [], 'str, bytes, bytearray or None') |  | ||||||
|         check('w*', [], 'read-write bytes-like object') |  | ||||||
|         check('w*?', [], 'read-write bytes-like object or None') |  | ||||||
|         check('S', [], 'bytes') |  | ||||||
|         check('S?', [], 'bytes or None') |  | ||||||
|         check('U', [], 'str') |  | ||||||
|         check('U?', [], 'str or None') |  | ||||||
|         check('Y', [], 'bytearray') |  | ||||||
|         check('Y?', [], 'bytearray or None') |  | ||||||
|         check('(OO)', 42, '2-item tuple', 'int') |  | ||||||
|         check('(OO)?', 42, '2-item tuple or None', 'int') |  | ||||||
|         check('(OO)', (1, 2, 3), 'tuple of length 2', '3') |  | ||||||
| 
 |  | ||||||
|     def test_nullable(self): |  | ||||||
|         parse = _testcapi.parse_tuple_and_keywords |  | ||||||
| 
 |  | ||||||
|         def check(format, arg, allows_none=False): |  | ||||||
|             # Because some format units (such as y*) require cleanup, |  | ||||||
|             # we force the parsing code to perform the cleanup by adding |  | ||||||
|             # an argument that always fails. |  | ||||||
|             # By checking for an exception, we ensure that the parsing |  | ||||||
|             # of the first argument was successful. |  | ||||||
|             self.assertRaises(OverflowError, parse, |  | ||||||
|                               (arg, 256), {}, format + '?b', ['a', 'b']) |  | ||||||
|             self.assertRaises(OverflowError, parse, |  | ||||||
|                               (None, 256), {}, format + '?b', ['a', 'b']) |  | ||||||
|             self.assertRaises(OverflowError, parse, |  | ||||||
|                               (arg, 256), {}, format + 'b', ['a', 'b']) |  | ||||||
|             self.assertRaises(OverflowError if allows_none else TypeError, parse, |  | ||||||
|                               (None, 256), {}, format + 'b', ['a', 'b']) |  | ||||||
| 
 |  | ||||||
|         check('b', 42) |  | ||||||
|         check('B', 42) |  | ||||||
|         check('h', 42) |  | ||||||
|         check('H', 42) |  | ||||||
|         check('i', 42) |  | ||||||
|         check('I', 42) |  | ||||||
|         check('n', 42) |  | ||||||
|         check('l', 42) |  | ||||||
|         check('k', 42) |  | ||||||
|         check('L', 42) |  | ||||||
|         check('K', 42) |  | ||||||
|         check('f', 2.5) |  | ||||||
|         check('d', 2.5) |  | ||||||
|         check('D', 2.5j) |  | ||||||
|         check('c', b'a') |  | ||||||
|         check('C', 'a') |  | ||||||
|         check('p', True, allows_none=True) |  | ||||||
|         check('y', b'buffer') |  | ||||||
|         check('y*', b'buffer') |  | ||||||
|         check('y#', b'buffer') |  | ||||||
|         check('s', 'string') |  | ||||||
|         check('s*', 'string') |  | ||||||
|         check('s#', 'string') |  | ||||||
|         check('z', 'string', allows_none=True) |  | ||||||
|         check('z*', 'string', allows_none=True) |  | ||||||
|         check('z#', 'string', allows_none=True) |  | ||||||
|         check('w*', bytearray(b'buffer')) |  | ||||||
|         check('U', 'string') |  | ||||||
|         check('S', b'bytes') |  | ||||||
|         check('Y', bytearray(b'bytearray')) |  | ||||||
|         check('O', object, allows_none=True) |  | ||||||
| 
 |  | ||||||
|         check('(OO)', (1, 2)) |  | ||||||
|         self.assertEqual(parse((((1, 2), 3),), {}, '((OO)?O)', ['a']), (1, 2, 3)) |  | ||||||
|         self.assertEqual(parse(((None, 3),), {}, '((OO)?O)', ['a']), (NULL, NULL, 3)) |  | ||||||
|         self.assertEqual(parse((((1, 2), 3),), {}, '((OO)O)', ['a']), (1, 2, 3)) |  | ||||||
|         self.assertRaises(TypeError, parse, ((None, 3),), {}, '((OO)O)', ['a']) |  | ||||||
| 
 |  | ||||||
|         parse((None,), {}, 'es?', ['a']) |  | ||||||
|         parse((None,), {}, 'es#?', ['a']) |  | ||||||
|         parse((None,), {}, 'et?', ['a']) |  | ||||||
|         parse((None,), {}, 'et#?', ['a']) |  | ||||||
|         parse((None,), {}, 'O!?', ['a']) |  | ||||||
|         parse((None,), {}, 'O&?', ['a']) |  | ||||||
| 
 |  | ||||||
|         # TODO: More tests for es?, es#?, et?, et#?, O!, O& |  | ||||||
| 
 |  | ||||||
|     @unittest.skipIf(_testinternalcapi is None, 'needs _testinternalcapi') |     @unittest.skipIf(_testinternalcapi is None, 'needs _testinternalcapi') | ||||||
|     def test_gh_119213(self): |     def test_gh_119213(self): | ||||||
|         rc, out, err = script_helper.assert_python_ok("-c", """if True: |         rc, out, err = script_helper.assert_python_ok("-c", """if True: | ||||||
|  |  | ||||||
|  | @ -732,7 +732,7 @@ def test_tagname(self): | ||||||
|         m2.close() |         m2.close() | ||||||
|         m1.close() |         m1.close() | ||||||
| 
 | 
 | ||||||
|         with self.assertRaisesRegex(TypeError, 'must be str or None'): |         with self.assertRaisesRegex(TypeError, 'tagname'): | ||||||
|             mmap.mmap(-1, 8, tagname=1) |             mmap.mmap(-1, 8, tagname=1) | ||||||
| 
 | 
 | ||||||
|     @cpython_only |     @cpython_only | ||||||
|  |  | ||||||
|  | @ -2012,7 +2012,7 @@ interpreter. | ||||||
| .. nonce: ofI5Fl | .. nonce: ofI5Fl | ||||||
| .. section: C API | .. section: C API | ||||||
| 
 | 
 | ||||||
| Add support of nullable arguments in :c:func:`PyArg_Parse` and similar | [Reverted in :gh:`136991`] Add support of nullable arguments in :c:func:`PyArg_Parse` and similar | ||||||
| functions. Adding ``?`` after any format unit makes ``None`` be accepted as | functions. Adding ``?`` after any format unit makes ``None`` be accepted as | ||||||
| a value. | a value. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | Revert support of nullable arguments in :c:func:`PyArg_Parse`. | ||||||
|  | @ -3918,7 +3918,9 @@ _validate_paramflags(ctypes_state *st, PyTypeObject *type, PyObject *paramflags) | ||||||
|         PyObject *name = Py_None; |         PyObject *name = Py_None; | ||||||
|         PyObject *defval; |         PyObject *defval; | ||||||
|         PyObject *typ; |         PyObject *typ; | ||||||
|         if (!PyArg_ParseTuple(item, "i|U?O", &flag, &name, &defval)) { |         if (!PyArg_ParseTuple(item, "i|OO", &flag, &name, &defval) || | ||||||
|  |             !(name == Py_None || PyUnicode_Check(name))) | ||||||
|  |         { | ||||||
|             PyErr_SetString(PyExc_TypeError, |             PyErr_SetString(PyExc_TypeError, | ||||||
|                    "paramflags must be a sequence of (int [,string [,value]]) tuples"); |                    "paramflags must be a sequence of (int [,string [,value]]) tuples"); | ||||||
|             return 0; |             return 0; | ||||||
|  | @ -3983,8 +3985,10 @@ PyCFuncPtr_FromDll(PyTypeObject *type, PyObject *args, PyObject *kwds) | ||||||
|     void *handle; |     void *handle; | ||||||
|     PyObject *paramflags = NULL; |     PyObject *paramflags = NULL; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "O|O?", &ftuple, ¶mflags)) |     if (!PyArg_ParseTuple(args, "O|O", &ftuple, ¶mflags)) | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     if (paramflags == Py_None) | ||||||
|  |         paramflags = NULL; | ||||||
| 
 | 
 | ||||||
|     ftuple = PySequence_Tuple(ftuple); |     ftuple = PySequence_Tuple(ftuple); | ||||||
|     if (!ftuple) |     if (!ftuple) | ||||||
|  | @ -4116,8 +4120,10 @@ PyCFuncPtr_FromVtblIndex(PyTypeObject *type, PyObject *args, PyObject *kwds) | ||||||
|     GUID *iid = NULL; |     GUID *iid = NULL; | ||||||
|     Py_ssize_t iid_len = 0; |     Py_ssize_t iid_len = 0; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTuple(args, "is|O?z#", &index, &name, ¶mflags, &iid, &iid_len)) |     if (!PyArg_ParseTuple(args, "is|Oz#", &index, &name, ¶mflags, &iid, &iid_len)) | ||||||
|         return NULL; |         return NULL; | ||||||
|  |     if (paramflags == Py_None) | ||||||
|  |         paramflags = NULL; | ||||||
| 
 | 
 | ||||||
|     ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); |     ctypes_state *st = get_module_state_by_def(Py_TYPE(type)); | ||||||
|     if (!_validate_paramflags(st, type, paramflags)) { |     if (!_validate_paramflags(st, type, paramflags)) { | ||||||
|  |  | ||||||
|  | @ -1415,11 +1415,14 @@ interp_get_config(PyObject *self, PyObject *args, PyObject *kwds) | ||||||
|     PyObject *idobj = NULL; |     PyObject *idobj = NULL; | ||||||
|     int restricted = 0; |     int restricted = 0; | ||||||
|     if (!PyArg_ParseTupleAndKeywords(args, kwds, |     if (!PyArg_ParseTupleAndKeywords(args, kwds, | ||||||
|                                      "O?|$p:get_config", kwlist, |                                      "O|$p:get_config", kwlist, | ||||||
|                                      &idobj, &restricted)) |                                      &idobj, &restricted)) | ||||||
|     { |     { | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
|  |     if (idobj == Py_None) { | ||||||
|  |         idobj = NULL; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     int reqready = 0; |     int reqready = 0; | ||||||
|     PyInterpreterState *interp = \ |     PyInterpreterState *interp = \ | ||||||
|  | @ -1536,14 +1539,14 @@ capture_exception(PyObject *self, PyObject *args, PyObject *kwds) | ||||||
|     static char *kwlist[] = {"exc", NULL}; |     static char *kwlist[] = {"exc", NULL}; | ||||||
|     PyObject *exc_arg = NULL; |     PyObject *exc_arg = NULL; | ||||||
|     if (!PyArg_ParseTupleAndKeywords(args, kwds, |     if (!PyArg_ParseTupleAndKeywords(args, kwds, | ||||||
|                                      "|O?:capture_exception", kwlist, |                                      "|O:capture_exception", kwlist, | ||||||
|                                      &exc_arg)) |                                      &exc_arg)) | ||||||
|     { |     { | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     PyObject *exc = exc_arg; |     PyObject *exc = exc_arg; | ||||||
|     if (exc == NULL) { |     if (exc == NULL || exc == Py_None) { | ||||||
|         exc = PyErr_GetRaisedException(); |         exc = PyErr_GetRaisedException(); | ||||||
|         if (exc == NULL) { |         if (exc == NULL) { | ||||||
|             Py_RETURN_NONE; |             Py_RETURN_NONE; | ||||||
|  |  | ||||||
|  | @ -1228,16 +1228,23 @@ encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | ||||||
|     static char *kwlist[] = {"markers", "default", "encoder", "indent", "key_separator", "item_separator", "sort_keys", "skipkeys", "allow_nan", NULL}; |     static char *kwlist[] = {"markers", "default", "encoder", "indent", "key_separator", "item_separator", "sort_keys", "skipkeys", "allow_nan", NULL}; | ||||||
| 
 | 
 | ||||||
|     PyEncoderObject *s; |     PyEncoderObject *s; | ||||||
|     PyObject *markers = Py_None, *defaultfn, *encoder, *indent, *key_separator; |     PyObject *markers, *defaultfn, *encoder, *indent, *key_separator; | ||||||
|     PyObject *item_separator; |     PyObject *item_separator; | ||||||
|     int sort_keys, skipkeys, allow_nan; |     int sort_keys, skipkeys, allow_nan; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!?OOOUUppp:make_encoder", kwlist, |     if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOUUppp:make_encoder", kwlist, | ||||||
|         &PyDict_Type, &markers, &defaultfn, &encoder, &indent, |         &markers, &defaultfn, &encoder, &indent, | ||||||
|         &key_separator, &item_separator, |         &key_separator, &item_separator, | ||||||
|         &sort_keys, &skipkeys, &allow_nan)) |         &sort_keys, &skipkeys, &allow_nan)) | ||||||
|         return NULL; |         return NULL; | ||||||
| 
 | 
 | ||||||
|  |     if (markers != Py_None && !PyDict_Check(markers)) { | ||||||
|  |         PyErr_Format(PyExc_TypeError, | ||||||
|  |                      "make_encoder() argument 1 must be dict or None, " | ||||||
|  |                      "not %.200s", Py_TYPE(markers)->tp_name); | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     s = (PyEncoderObject *)type->tp_alloc(type, 0); |     s = (PyEncoderObject *)type->tp_alloc(type, 0); | ||||||
|     if (s == NULL) |     if (s == NULL) | ||||||
|         return NULL; |         return NULL; | ||||||
|  |  | ||||||
|  | @ -667,12 +667,12 @@ PyThreadHandleObject_join(PyObject *op, PyObject *args) | ||||||
|     PyThreadHandleObject *self = PyThreadHandleObject_CAST(op); |     PyThreadHandleObject *self = PyThreadHandleObject_CAST(op); | ||||||
| 
 | 
 | ||||||
|     PyObject *timeout_obj = NULL; |     PyObject *timeout_obj = NULL; | ||||||
|     if (!PyArg_ParseTuple(args, "|O?:join", &timeout_obj)) { |     if (!PyArg_ParseTuple(args, "|O:join", &timeout_obj)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     PyTime_t timeout_ns = -1; |     PyTime_t timeout_ns = -1; | ||||||
|     if (timeout_obj != NULL) { |     if (timeout_obj != NULL && timeout_obj != Py_None) { | ||||||
|         if (_PyTime_FromSecondsObject(&timeout_ns, timeout_obj, |         if (_PyTime_FromSecondsObject(&timeout_ns, timeout_obj, | ||||||
|                                       _PyTime_ROUND_TIMEOUT) < 0) { |                                       _PyTime_ROUND_TIMEOUT) < 0) { | ||||||
|             return NULL; |             return NULL; | ||||||
|  | @ -1945,10 +1945,10 @@ thread_PyThread_start_joinable_thread(PyObject *module, PyObject *fargs, | ||||||
|     PyObject *func = NULL; |     PyObject *func = NULL; | ||||||
|     int daemon = 1; |     int daemon = 1; | ||||||
|     thread_module_state *state = get_thread_state(module); |     thread_module_state *state = get_thread_state(module); | ||||||
|     PyObject *hobj = Py_None; |     PyObject *hobj = NULL; | ||||||
|     if (!PyArg_ParseTupleAndKeywords(fargs, fkwargs, |     if (!PyArg_ParseTupleAndKeywords(fargs, fkwargs, | ||||||
|                                      "O|O!?p:start_joinable_thread", keywords, |                                      "O|Op:start_joinable_thread", keywords, | ||||||
|                                      &func, state->thread_handle_type, &hobj, &daemon)) { |                                      &func, &hobj, &daemon)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -1958,6 +1958,14 @@ thread_PyThread_start_joinable_thread(PyObject *module, PyObject *fargs, | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     if (hobj == NULL) { | ||||||
|  |         hobj = Py_None; | ||||||
|  |     } | ||||||
|  |     else if (hobj != Py_None && !Py_IS_TYPE(hobj, state->thread_handle_type)) { | ||||||
|  |         PyErr_SetString(PyExc_TypeError, "'handle' must be a _ThreadHandle"); | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     if (PySys_Audit("_thread.start_joinable_thread", "OiO", func, daemon, |     if (PySys_Audit("_thread.start_joinable_thread", "OiO", func, daemon, | ||||||
|                     hobj) < 0) { |                     hobj) < 0) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  |  | ||||||
|  | @ -23,6 +23,7 @@ | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #include <Python.h> | #include <Python.h> | ||||||
|  | #include "pycore_abstract.h"      // _Py_convert_optional_to_ssize_t() | ||||||
| #include "pycore_bytesobject.h"   // _PyBytes_Find() | #include "pycore_bytesobject.h"   // _PyBytes_Find() | ||||||
| #include "pycore_fileutils.h"     // _Py_stat_struct | #include "pycore_fileutils.h"     // _Py_stat_struct | ||||||
| #include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS() | #include "pycore_weakref.h"       // FT_CLEAR_WEAKREFS() | ||||||
|  | @ -515,7 +516,7 @@ mmap_read_method(PyObject *op, PyObject *args) | ||||||
|     mmap_object *self = mmap_object_CAST(op); |     mmap_object *self = mmap_object_CAST(op); | ||||||
| 
 | 
 | ||||||
|     CHECK_VALID(NULL); |     CHECK_VALID(NULL); | ||||||
|     if (!PyArg_ParseTuple(args, "|n?:read", &num_bytes)) |     if (!PyArg_ParseTuple(args, "|O&:read", _Py_convert_optional_to_ssize_t, &num_bytes)) | ||||||
|         return NULL; |         return NULL; | ||||||
|     CHECK_VALID(NULL); |     CHECK_VALID(NULL); | ||||||
| 
 | 
 | ||||||
|  | @ -1709,7 +1710,7 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict) | ||||||
|     DWORD off_lo;       /* lower 32 bits of offset */ |     DWORD off_lo;       /* lower 32 bits of offset */ | ||||||
|     DWORD size_hi;      /* upper 32 bits of size */ |     DWORD size_hi;      /* upper 32 bits of size */ | ||||||
|     DWORD size_lo;      /* lower 32 bits of size */ |     DWORD size_lo;      /* lower 32 bits of size */ | ||||||
|     PyObject *tagname = NULL; |     PyObject *tagname = Py_None; | ||||||
|     DWORD dwErr = 0; |     DWORD dwErr = 0; | ||||||
|     int fileno; |     int fileno; | ||||||
|     HANDLE fh = 0; |     HANDLE fh = 0; | ||||||
|  | @ -1719,7 +1720,7 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict) | ||||||
|                                 "tagname", |                                 "tagname", | ||||||
|                                 "access", "offset", NULL }; |                                 "access", "offset", NULL }; | ||||||
| 
 | 
 | ||||||
|     if (!PyArg_ParseTupleAndKeywords(args, kwdict, "in|U?iL", keywords, |     if (!PyArg_ParseTupleAndKeywords(args, kwdict, "in|OiL", keywords, | ||||||
|                                      &fileno, &map_size, |                                      &fileno, &map_size, | ||||||
|                                      &tagname, &access, &offset)) { |                                      &tagname, &access, &offset)) { | ||||||
|         return NULL; |         return NULL; | ||||||
|  | @ -1852,7 +1853,13 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict) | ||||||
|     m_obj->weakreflist = NULL; |     m_obj->weakreflist = NULL; | ||||||
|     m_obj->exports = 0; |     m_obj->exports = 0; | ||||||
|     /* set the tag name */ |     /* set the tag name */ | ||||||
|     if (tagname != NULL) { |     if (!Py_IsNone(tagname)) { | ||||||
|  |         if (!PyUnicode_Check(tagname)) { | ||||||
|  |             Py_DECREF(m_obj); | ||||||
|  |             return PyErr_Format(PyExc_TypeError, "expected str or None for " | ||||||
|  |                                 "'tagname', not %.200s", | ||||||
|  |                                 Py_TYPE(tagname)->tp_name); | ||||||
|  |         } | ||||||
|         m_obj->tagname = PyUnicode_AsWideCharString(tagname, NULL); |         m_obj->tagname = PyUnicode_AsWideCharString(tagname, NULL); | ||||||
|         if (m_obj->tagname == NULL) { |         if (m_obj->tagname == NULL) { | ||||||
|             Py_DECREF(m_obj); |             Py_DECREF(m_obj); | ||||||
|  |  | ||||||
							
								
								
									
										257
									
								
								Python/getargs.c
									
										
									
									
									
								
							
							
						
						
									
										257
									
								
								Python/getargs.c
									
										
									
									
									
								
							|  | @ -1,8 +1,6 @@ | ||||||
| 
 | 
 | ||||||
| /* New getargs implementation */ | /* New getargs implementation */ | ||||||
| 
 | 
 | ||||||
| #include <stdbool.h> |  | ||||||
| 
 |  | ||||||
| #define PY_CXX_CONST const | #define PY_CXX_CONST const | ||||||
| #include "Python.h" | #include "Python.h" | ||||||
| #include "pycore_abstract.h"      // _PyNumber_Index() | #include "pycore_abstract.h"      // _PyNumber_Index() | ||||||
|  | @ -468,12 +466,9 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|     const char *format = *p_format; |     const char *format = *p_format; | ||||||
|     int i; |     int i; | ||||||
|     Py_ssize_t len; |     Py_ssize_t len; | ||||||
|     bool nullable = false; |  | ||||||
|     int istuple = PyTuple_Check(arg); |     int istuple = PyTuple_Check(arg); | ||||||
|     int mustbetuple = istuple; |     int mustbetuple = istuple; | ||||||
| 
 | 
 | ||||||
|     assert(*format == '('); |  | ||||||
|     format++; |  | ||||||
|     for (;;) { |     for (;;) { | ||||||
|         int c = *format++; |         int c = *format++; | ||||||
|         if (c == '(') { |         if (c == '(') { | ||||||
|  | @ -482,12 +477,8 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|             level++; |             level++; | ||||||
|         } |         } | ||||||
|         else if (c == ')') { |         else if (c == ')') { | ||||||
|             if (level == 0) { |             if (level == 0) | ||||||
|                 if (*format == '?') { |  | ||||||
|                     nullable = true; |  | ||||||
|                 } |  | ||||||
|                 break; |                 break; | ||||||
|             } |  | ||||||
|             level--; |             level--; | ||||||
|         } |         } | ||||||
|         else if (c == ':' || c == ';' || c == '\0') |         else if (c == ':' || c == ';' || c == '\0') | ||||||
|  | @ -524,13 +515,6 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (arg == Py_None && nullable) { |  | ||||||
|         const char *msg = skipitem(p_format, p_va, flags); |  | ||||||
|         if (msg != NULL) { |  | ||||||
|             levels[0] = 0; |  | ||||||
|         } |  | ||||||
|         return msg; |  | ||||||
|     } |  | ||||||
|     if (istuple) { |     if (istuple) { | ||||||
|         /* fallthrough */ |         /* fallthrough */ | ||||||
|     } |     } | ||||||
|  | @ -539,10 +523,9 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|     { |     { | ||||||
|         levels[0] = 0; |         levels[0] = 0; | ||||||
|         PyOS_snprintf(msgbuf, bufsize, |         PyOS_snprintf(msgbuf, bufsize, | ||||||
|                       "must be %d-item tuple%s, not %.50s", |                       "must be %d-item tuple, not %.50s", | ||||||
|                       n, |                   n, | ||||||
|                       nullable ? " or None" : "", |                   arg == Py_None ? "None" : Py_TYPE(arg)->tp_name); | ||||||
|                       arg == Py_None ? "None" : Py_TYPE(arg)->tp_name); |  | ||||||
|         return msgbuf; |         return msgbuf; | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|  | @ -579,7 +562,7 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|         return msgbuf; |         return msgbuf; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     format = *p_format + 1; |     format = *p_format; | ||||||
|     for (i = 0; i < n; i++) { |     for (i = 0; i < n; i++) { | ||||||
|         const char *msg; |         const char *msg; | ||||||
|         PyObject *item = PyTuple_GET_ITEM(arg, i); |         PyObject *item = PyTuple_GET_ITEM(arg, i); | ||||||
|  | @ -594,10 +577,6 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     format++; |  | ||||||
|     if (*format == '?') { |  | ||||||
|         format++; |  | ||||||
|     } |  | ||||||
|     *p_format = format; |     *p_format = format; | ||||||
|     if (!istuple) { |     if (!istuple) { | ||||||
|         Py_DECREF(arg); |         Py_DECREF(arg); | ||||||
|  | @ -616,8 +595,11 @@ convertitem(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|     const char *format = *p_format; |     const char *format = *p_format; | ||||||
| 
 | 
 | ||||||
|     if (*format == '(' /* ')' */) { |     if (*format == '(' /* ')' */) { | ||||||
|  |         format++; | ||||||
|         msg = converttuple(arg, &format, p_va, flags, levels, msgbuf, |         msg = converttuple(arg, &format, p_va, flags, levels, msgbuf, | ||||||
|                            bufsize, freelist); |                            bufsize, freelist); | ||||||
|  |         if (msg == NULL) | ||||||
|  |             format++; | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|         msg = convertsimple(arg, &format, p_va, flags, |         msg = convertsimple(arg, &format, p_va, flags, | ||||||
|  | @ -647,7 +629,7 @@ _PyArg_BadArgument(const char *fname, const char *displayname, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static const char * | static const char * | ||||||
| converterr(bool nullable, const char *expected, PyObject *arg, char *msgbuf, size_t bufsize) | converterr(const char *expected, PyObject *arg, char *msgbuf, size_t bufsize) | ||||||
| { | { | ||||||
|     assert(expected != NULL); |     assert(expected != NULL); | ||||||
|     assert(arg != NULL); |     assert(arg != NULL); | ||||||
|  | @ -657,23 +639,20 @@ converterr(bool nullable, const char *expected, PyObject *arg, char *msgbuf, siz | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|         PyOS_snprintf(msgbuf, bufsize, |         PyOS_snprintf(msgbuf, bufsize, | ||||||
|                       "must be %.50s%s, not %.50s", expected, |                       "must be %.50s, not %.50s", expected, | ||||||
|                       nullable ? " or None" : "", |  | ||||||
|                       arg == Py_None ? "None" : Py_TYPE(arg)->tp_name); |                       arg == Py_None ? "None" : Py_TYPE(arg)->tp_name); | ||||||
|     } |     } | ||||||
|     return msgbuf; |     return msgbuf; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static const char * | static const char * | ||||||
| convertcharerr(bool nullable, const char *expected, const char *what, Py_ssize_t size, | convertcharerr(const char *expected, const char *what, Py_ssize_t size, | ||||||
|                char *msgbuf, size_t bufsize) |                char *msgbuf, size_t bufsize) | ||||||
| { | { | ||||||
|     assert(expected != NULL); |     assert(expected != NULL); | ||||||
|     PyOS_snprintf(msgbuf, bufsize, |     PyOS_snprintf(msgbuf, bufsize, | ||||||
|                   "must be %.50s%s, not %.50s of length %zd", |                   "must be %.50s, not %.50s of length %zd", | ||||||
|                   expected, |                   expected, what, size); | ||||||
|                   nullable ? " or None" : "", |  | ||||||
|                   what, size); |  | ||||||
|     return msgbuf; |     return msgbuf; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -693,26 +672,15 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|               char *msgbuf, size_t bufsize, freelist_t *freelist) |               char *msgbuf, size_t bufsize, freelist_t *freelist) | ||||||
| { | { | ||||||
| #define RETURN_ERR_OCCURRED return msgbuf | #define RETURN_ERR_OCCURRED return msgbuf | ||||||
| #define HANDLE_NULLABLE                 \ |  | ||||||
|         if (*format == '?') {           \ |  | ||||||
|             format++;                   \ |  | ||||||
|             if (arg == Py_None) {       \ |  | ||||||
|                 break;                  \ |  | ||||||
|             }                           \ |  | ||||||
|             nullable = true;            \ |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
|     const char *format = *p_format; |     const char *format = *p_format; | ||||||
|     char c = *format++; |     char c = *format++; | ||||||
|     const char *sarg; |     const char *sarg; | ||||||
|     bool nullable = false; |  | ||||||
| 
 | 
 | ||||||
|     switch (c) { |     switch (c) { | ||||||
| 
 | 
 | ||||||
|     case 'b': { /* unsigned byte -- very short int */ |     case 'b': { /* unsigned byte -- very short int */ | ||||||
|         unsigned char *p = va_arg(*p_va, unsigned char *); |         unsigned char *p = va_arg(*p_va, unsigned char *); | ||||||
|         HANDLE_NULLABLE; |  | ||||||
|         long ival = PyLong_AsLong(arg); |         long ival = PyLong_AsLong(arg); | ||||||
|         if (ival == -1 && PyErr_Occurred()) |         if (ival == -1 && PyErr_Occurred()) | ||||||
|             RETURN_ERR_OCCURRED; |             RETURN_ERR_OCCURRED; | ||||||
|  | @ -726,6 +694,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|                             "unsigned byte integer is greater than maximum"); |                             "unsigned byte integer is greater than maximum"); | ||||||
|             RETURN_ERR_OCCURRED; |             RETURN_ERR_OCCURRED; | ||||||
|         } |         } | ||||||
|  |         else | ||||||
|             *p = (unsigned char) ival; |             *p = (unsigned char) ival; | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|  | @ -733,7 +702,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|     case 'B': {/* byte sized bitfield - both signed and unsigned
 |     case 'B': {/* byte sized bitfield - both signed and unsigned
 | ||||||
|                   values allowed */ |                   values allowed */ | ||||||
|         unsigned char *p = va_arg(*p_va, unsigned char *); |         unsigned char *p = va_arg(*p_va, unsigned char *); | ||||||
|         HANDLE_NULLABLE; |  | ||||||
|         unsigned long ival = PyLong_AsUnsignedLongMask(arg); |         unsigned long ival = PyLong_AsUnsignedLongMask(arg); | ||||||
|         if (ival == (unsigned long)-1 && PyErr_Occurred()) |         if (ival == (unsigned long)-1 && PyErr_Occurred()) | ||||||
|             RETURN_ERR_OCCURRED; |             RETURN_ERR_OCCURRED; | ||||||
|  | @ -744,7 +712,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
| 
 | 
 | ||||||
|     case 'h': {/* signed short int */ |     case 'h': {/* signed short int */ | ||||||
|         short *p = va_arg(*p_va, short *); |         short *p = va_arg(*p_va, short *); | ||||||
|         HANDLE_NULLABLE; |  | ||||||
|         long ival = PyLong_AsLong(arg); |         long ival = PyLong_AsLong(arg); | ||||||
|         if (ival == -1 && PyErr_Occurred()) |         if (ival == -1 && PyErr_Occurred()) | ||||||
|             RETURN_ERR_OCCURRED; |             RETURN_ERR_OCCURRED; | ||||||
|  | @ -766,7 +733,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|     case 'H': { /* short int sized bitfield, both signed and
 |     case 'H': { /* short int sized bitfield, both signed and
 | ||||||
|                    unsigned allowed */ |                    unsigned allowed */ | ||||||
|         unsigned short *p = va_arg(*p_va, unsigned short *); |         unsigned short *p = va_arg(*p_va, unsigned short *); | ||||||
|         HANDLE_NULLABLE; |  | ||||||
|         unsigned long ival = PyLong_AsUnsignedLongMask(arg); |         unsigned long ival = PyLong_AsUnsignedLongMask(arg); | ||||||
|         if (ival == (unsigned long)-1 && PyErr_Occurred()) |         if (ival == (unsigned long)-1 && PyErr_Occurred()) | ||||||
|             RETURN_ERR_OCCURRED; |             RETURN_ERR_OCCURRED; | ||||||
|  | @ -777,7 +743,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
| 
 | 
 | ||||||
|     case 'i': {/* signed int */ |     case 'i': {/* signed int */ | ||||||
|         int *p = va_arg(*p_va, int *); |         int *p = va_arg(*p_va, int *); | ||||||
|         HANDLE_NULLABLE; |  | ||||||
|         long ival = PyLong_AsLong(arg); |         long ival = PyLong_AsLong(arg); | ||||||
|         if (ival == -1 && PyErr_Occurred()) |         if (ival == -1 && PyErr_Occurred()) | ||||||
|             RETURN_ERR_OCCURRED; |             RETURN_ERR_OCCURRED; | ||||||
|  | @ -799,7 +764,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|     case 'I': { /* int sized bitfield, both signed and
 |     case 'I': { /* int sized bitfield, both signed and
 | ||||||
|                    unsigned allowed */ |                    unsigned allowed */ | ||||||
|         unsigned int *p = va_arg(*p_va, unsigned int *); |         unsigned int *p = va_arg(*p_va, unsigned int *); | ||||||
|         HANDLE_NULLABLE; |  | ||||||
|         unsigned long ival = PyLong_AsUnsignedLongMask(arg); |         unsigned long ival = PyLong_AsUnsignedLongMask(arg); | ||||||
|         if (ival == (unsigned long)-1 && PyErr_Occurred()) |         if (ival == (unsigned long)-1 && PyErr_Occurred()) | ||||||
|             RETURN_ERR_OCCURRED; |             RETURN_ERR_OCCURRED; | ||||||
|  | @ -812,7 +776,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|     { |     { | ||||||
|         PyObject *iobj; |         PyObject *iobj; | ||||||
|         Py_ssize_t *p = va_arg(*p_va, Py_ssize_t *); |         Py_ssize_t *p = va_arg(*p_va, Py_ssize_t *); | ||||||
|         HANDLE_NULLABLE; |  | ||||||
|         Py_ssize_t ival = -1; |         Py_ssize_t ival = -1; | ||||||
|         iobj = _PyNumber_Index(arg); |         iobj = _PyNumber_Index(arg); | ||||||
|         if (iobj != NULL) { |         if (iobj != NULL) { | ||||||
|  | @ -826,7 +789,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|     } |     } | ||||||
|     case 'l': {/* long int */ |     case 'l': {/* long int */ | ||||||
|         long *p = va_arg(*p_va, long *); |         long *p = va_arg(*p_va, long *); | ||||||
|         HANDLE_NULLABLE; |  | ||||||
|         long ival = PyLong_AsLong(arg); |         long ival = PyLong_AsLong(arg); | ||||||
|         if (ival == -1 && PyErr_Occurred()) |         if (ival == -1 && PyErr_Occurred()) | ||||||
|             RETURN_ERR_OCCURRED; |             RETURN_ERR_OCCURRED; | ||||||
|  | @ -837,10 +799,9 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
| 
 | 
 | ||||||
|     case 'k': { /* long sized bitfield */ |     case 'k': { /* long sized bitfield */ | ||||||
|         unsigned long *p = va_arg(*p_va, unsigned long *); |         unsigned long *p = va_arg(*p_va, unsigned long *); | ||||||
|         HANDLE_NULLABLE; |  | ||||||
|         unsigned long ival; |         unsigned long ival; | ||||||
|         if (!PyIndex_Check(arg)) { |         if (!PyIndex_Check(arg)) { | ||||||
|             return converterr(nullable, "int", arg, msgbuf, bufsize); |             return converterr("int", arg, msgbuf, bufsize); | ||||||
|         } |         } | ||||||
|         ival = PyLong_AsUnsignedLongMask(arg); |         ival = PyLong_AsUnsignedLongMask(arg); | ||||||
|         if (ival == (unsigned long)(long)-1 && PyErr_Occurred()) { |         if (ival == (unsigned long)(long)-1 && PyErr_Occurred()) { | ||||||
|  | @ -852,7 +813,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
| 
 | 
 | ||||||
|     case 'L': {/* long long */ |     case 'L': {/* long long */ | ||||||
|         long long *p = va_arg( *p_va, long long * ); |         long long *p = va_arg( *p_va, long long * ); | ||||||
|         HANDLE_NULLABLE; |  | ||||||
|         long long ival = PyLong_AsLongLong(arg); |         long long ival = PyLong_AsLongLong(arg); | ||||||
|         if (ival == (long long)-1 && PyErr_Occurred()) |         if (ival == (long long)-1 && PyErr_Occurred()) | ||||||
|             RETURN_ERR_OCCURRED; |             RETURN_ERR_OCCURRED; | ||||||
|  | @ -863,10 +823,9 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
| 
 | 
 | ||||||
|     case 'K': { /* long long sized bitfield */ |     case 'K': { /* long long sized bitfield */ | ||||||
|         unsigned long long *p = va_arg(*p_va, unsigned long long *); |         unsigned long long *p = va_arg(*p_va, unsigned long long *); | ||||||
|         HANDLE_NULLABLE; |  | ||||||
|         unsigned long long ival; |         unsigned long long ival; | ||||||
|         if (!PyIndex_Check(arg)) { |         if (!PyIndex_Check(arg)) { | ||||||
|             return converterr(nullable, "int", arg, msgbuf, bufsize); |             return converterr("int", arg, msgbuf, bufsize); | ||||||
|         } |         } | ||||||
|         ival = PyLong_AsUnsignedLongLongMask(arg); |         ival = PyLong_AsUnsignedLongLongMask(arg); | ||||||
|         if (ival == (unsigned long long)(long long)-1 && PyErr_Occurred()) { |         if (ival == (unsigned long long)(long long)-1 && PyErr_Occurred()) { | ||||||
|  | @ -878,7 +837,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
| 
 | 
 | ||||||
|     case 'f': {/* float */ |     case 'f': {/* float */ | ||||||
|         float *p = va_arg(*p_va, float *); |         float *p = va_arg(*p_va, float *); | ||||||
|         HANDLE_NULLABLE; |  | ||||||
|         double dval = PyFloat_AsDouble(arg); |         double dval = PyFloat_AsDouble(arg); | ||||||
|         if (dval == -1.0 && PyErr_Occurred()) |         if (dval == -1.0 && PyErr_Occurred()) | ||||||
|             RETURN_ERR_OCCURRED; |             RETURN_ERR_OCCURRED; | ||||||
|  | @ -889,7 +847,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
| 
 | 
 | ||||||
|     case 'd': {/* double */ |     case 'd': {/* double */ | ||||||
|         double *p = va_arg(*p_va, double *); |         double *p = va_arg(*p_va, double *); | ||||||
|         HANDLE_NULLABLE; |  | ||||||
|         double dval = PyFloat_AsDouble(arg); |         double dval = PyFloat_AsDouble(arg); | ||||||
|         if (dval == -1.0 && PyErr_Occurred()) |         if (dval == -1.0 && PyErr_Occurred()) | ||||||
|             RETURN_ERR_OCCURRED; |             RETURN_ERR_OCCURRED; | ||||||
|  | @ -900,7 +857,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
| 
 | 
 | ||||||
|     case 'D': {/* complex double */ |     case 'D': {/* complex double */ | ||||||
|         Py_complex *p = va_arg(*p_va, Py_complex *); |         Py_complex *p = va_arg(*p_va, Py_complex *); | ||||||
|         HANDLE_NULLABLE; |  | ||||||
|         Py_complex cval; |         Py_complex cval; | ||||||
|         cval = PyComplex_AsCComplex(arg); |         cval = PyComplex_AsCComplex(arg); | ||||||
|         if (PyErr_Occurred()) |         if (PyErr_Occurred()) | ||||||
|  | @ -912,10 +868,9 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
| 
 | 
 | ||||||
|     case 'c': {/* char */ |     case 'c': {/* char */ | ||||||
|         char *p = va_arg(*p_va, char *); |         char *p = va_arg(*p_va, char *); | ||||||
|         HANDLE_NULLABLE; |  | ||||||
|         if (PyBytes_Check(arg)) { |         if (PyBytes_Check(arg)) { | ||||||
|             if (PyBytes_GET_SIZE(arg) != 1) { |             if (PyBytes_GET_SIZE(arg) != 1) { | ||||||
|                 return convertcharerr(nullable, "a byte string of length 1", |                 return convertcharerr("a byte string of length 1", | ||||||
|                                       "a bytes object", PyBytes_GET_SIZE(arg), |                                       "a bytes object", PyBytes_GET_SIZE(arg), | ||||||
|                                       msgbuf, bufsize); |                                       msgbuf, bufsize); | ||||||
|             } |             } | ||||||
|  | @ -923,28 +878,27 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|         } |         } | ||||||
|         else if (PyByteArray_Check(arg)) { |         else if (PyByteArray_Check(arg)) { | ||||||
|             if (PyByteArray_GET_SIZE(arg) != 1) { |             if (PyByteArray_GET_SIZE(arg) != 1) { | ||||||
|                 return convertcharerr(nullable, "a byte string of length 1", |                 return convertcharerr("a byte string of length 1", | ||||||
|                                       "a bytearray object", PyByteArray_GET_SIZE(arg), |                                       "a bytearray object", PyByteArray_GET_SIZE(arg), | ||||||
|                                       msgbuf, bufsize); |                                       msgbuf, bufsize); | ||||||
|             } |             } | ||||||
|             *p = PyByteArray_AS_STRING(arg)[0]; |             *p = PyByteArray_AS_STRING(arg)[0]; | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|             return converterr(nullable, "a byte string of length 1", arg, msgbuf, bufsize); |             return converterr("a byte string of length 1", arg, msgbuf, bufsize); | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     case 'C': {/* unicode char */ |     case 'C': {/* unicode char */ | ||||||
|         int *p = va_arg(*p_va, int *); |         int *p = va_arg(*p_va, int *); | ||||||
|         HANDLE_NULLABLE; |  | ||||||
|         int kind; |         int kind; | ||||||
|         const void *data; |         const void *data; | ||||||
| 
 | 
 | ||||||
|         if (!PyUnicode_Check(arg)) |         if (!PyUnicode_Check(arg)) | ||||||
|             return converterr(nullable, "a unicode character", arg, msgbuf, bufsize); |             return converterr("a unicode character", arg, msgbuf, bufsize); | ||||||
| 
 | 
 | ||||||
|         if (PyUnicode_GET_LENGTH(arg) != 1) { |         if (PyUnicode_GET_LENGTH(arg) != 1) { | ||||||
|             return convertcharerr(nullable, "a unicode character", |             return convertcharerr("a unicode character", | ||||||
|                                   "a string", PyUnicode_GET_LENGTH(arg), |                                   "a string", PyUnicode_GET_LENGTH(arg), | ||||||
|                                   msgbuf, bufsize); |                                   msgbuf, bufsize); | ||||||
|         } |         } | ||||||
|  | @ -957,7 +911,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
| 
 | 
 | ||||||
|     case 'p': {/* boolean *p*redicate */ |     case 'p': {/* boolean *p*redicate */ | ||||||
|         int *p = va_arg(*p_va, int *); |         int *p = va_arg(*p_va, int *); | ||||||
|         HANDLE_NULLABLE; |  | ||||||
|         int val = PyObject_IsTrue(arg); |         int val = PyObject_IsTrue(arg); | ||||||
|         if (val > 0) |         if (val > 0) | ||||||
|             *p = 1; |             *p = 1; | ||||||
|  | @ -976,31 +929,24 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|         const char *buf; |         const char *buf; | ||||||
|         Py_ssize_t count; |         Py_ssize_t count; | ||||||
|         if (*format == '*') { |         if (*format == '*') { | ||||||
|             format++; |  | ||||||
|             HANDLE_NULLABLE; |  | ||||||
|             if (getbuffer(arg, (Py_buffer*)p, &buf) < 0) |             if (getbuffer(arg, (Py_buffer*)p, &buf) < 0) | ||||||
|                 return converterr(nullable, buf, arg, msgbuf, bufsize); |                 return converterr(buf, arg, msgbuf, bufsize); | ||||||
|  |             format++; | ||||||
|             if (addcleanup(p, freelist, cleanup_buffer)) { |             if (addcleanup(p, freelist, cleanup_buffer)) { | ||||||
|                 return converterr( |                 return converterr( | ||||||
|                     nullable, "(cleanup problem)", |                     "(cleanup problem)", | ||||||
|                     arg, msgbuf, bufsize); |                     arg, msgbuf, bufsize); | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         else if (*format == '#') { |         count = convertbuffer(arg, (const void **)p, &buf); | ||||||
|  |         if (count < 0) | ||||||
|  |             return converterr(buf, arg, msgbuf, bufsize); | ||||||
|  |         if (*format == '#') { | ||||||
|             Py_ssize_t *psize = va_arg(*p_va, Py_ssize_t*); |             Py_ssize_t *psize = va_arg(*p_va, Py_ssize_t*); | ||||||
|             format++; |  | ||||||
|             HANDLE_NULLABLE; |  | ||||||
|             count = convertbuffer(arg, (const void **)p, &buf); |  | ||||||
|             if (count < 0) |  | ||||||
|                 return converterr(nullable, buf, arg, msgbuf, bufsize); |  | ||||||
|             *psize = count; |             *psize = count; | ||||||
|         } |             format++; | ||||||
|         else { |         } else { | ||||||
|             HANDLE_NULLABLE; |  | ||||||
|             count = convertbuffer(arg, (const void **)p, &buf); |  | ||||||
|             if (count < 0) |  | ||||||
|                 return converterr(nullable, buf, arg, msgbuf, bufsize); |  | ||||||
|             if (strlen(*p) != (size_t)count) { |             if (strlen(*p) != (size_t)count) { | ||||||
|                 PyErr_SetString(PyExc_ValueError, "embedded null byte"); |                 PyErr_SetString(PyExc_ValueError, "embedded null byte"); | ||||||
|                 RETURN_ERR_OCCURRED; |                 RETURN_ERR_OCCURRED; | ||||||
|  | @ -1016,35 +962,32 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|             /* "s*" or "z*" */ |             /* "s*" or "z*" */ | ||||||
|             Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *); |             Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *); | ||||||
| 
 | 
 | ||||||
|             format++; |  | ||||||
|             HANDLE_NULLABLE; |  | ||||||
|             if (c == 'z' && arg == Py_None) |             if (c == 'z' && arg == Py_None) | ||||||
|                 PyBuffer_FillInfo(p, NULL, NULL, 0, 1, 0); |                 PyBuffer_FillInfo(p, NULL, NULL, 0, 1, 0); | ||||||
|             else if (PyUnicode_Check(arg)) { |             else if (PyUnicode_Check(arg)) { | ||||||
|                 Py_ssize_t len; |                 Py_ssize_t len; | ||||||
|                 sarg = PyUnicode_AsUTF8AndSize(arg, &len); |                 sarg = PyUnicode_AsUTF8AndSize(arg, &len); | ||||||
|                 if (sarg == NULL) |                 if (sarg == NULL) | ||||||
|                     return converterr(nullable, CONV_UNICODE, |                     return converterr(CONV_UNICODE, | ||||||
|                                       arg, msgbuf, bufsize); |                                       arg, msgbuf, bufsize); | ||||||
|                 PyBuffer_FillInfo(p, arg, (void *)sarg, len, 1, 0); |                 PyBuffer_FillInfo(p, arg, (void *)sarg, len, 1, 0); | ||||||
|             } |             } | ||||||
|             else { /* any bytes-like object */ |             else { /* any bytes-like object */ | ||||||
|                 const char *buf; |                 const char *buf; | ||||||
|                 if (getbuffer(arg, p, &buf) < 0) |                 if (getbuffer(arg, p, &buf) < 0) | ||||||
|                     return converterr(nullable, buf, arg, msgbuf, bufsize); |                     return converterr(buf, arg, msgbuf, bufsize); | ||||||
|             } |             } | ||||||
|             if (addcleanup(p, freelist, cleanup_buffer)) { |             if (addcleanup(p, freelist, cleanup_buffer)) { | ||||||
|                 return converterr( |                 return converterr( | ||||||
|                     nullable, "(cleanup problem)", |                     "(cleanup problem)", | ||||||
|                     arg, msgbuf, bufsize); |                     arg, msgbuf, bufsize); | ||||||
|             } |             } | ||||||
|  |             format++; | ||||||
|         } else if (*format == '#') { /* a string or read-only bytes-like object */ |         } else if (*format == '#') { /* a string or read-only bytes-like object */ | ||||||
|             /* "s#" or "z#" */ |             /* "s#" or "z#" */ | ||||||
|             const void **p = (const void **)va_arg(*p_va, const char **); |             const void **p = (const void **)va_arg(*p_va, const char **); | ||||||
|             Py_ssize_t *psize = va_arg(*p_va, Py_ssize_t*); |             Py_ssize_t *psize = va_arg(*p_va, Py_ssize_t*); | ||||||
| 
 | 
 | ||||||
|             format++; |  | ||||||
|             HANDLE_NULLABLE; |  | ||||||
|             if (c == 'z' && arg == Py_None) { |             if (c == 'z' && arg == Py_None) { | ||||||
|                 *p = NULL; |                 *p = NULL; | ||||||
|                 *psize = 0; |                 *psize = 0; | ||||||
|  | @ -1053,7 +996,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|                 Py_ssize_t len; |                 Py_ssize_t len; | ||||||
|                 sarg = PyUnicode_AsUTF8AndSize(arg, &len); |                 sarg = PyUnicode_AsUTF8AndSize(arg, &len); | ||||||
|                 if (sarg == NULL) |                 if (sarg == NULL) | ||||||
|                     return converterr(nullable, CONV_UNICODE, |                     return converterr(CONV_UNICODE, | ||||||
|                                       arg, msgbuf, bufsize); |                                       arg, msgbuf, bufsize); | ||||||
|                 *p = sarg; |                 *p = sarg; | ||||||
|                 *psize = len; |                 *psize = len; | ||||||
|  | @ -1063,22 +1006,22 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|                 const char *buf; |                 const char *buf; | ||||||
|                 Py_ssize_t count = convertbuffer(arg, p, &buf); |                 Py_ssize_t count = convertbuffer(arg, p, &buf); | ||||||
|                 if (count < 0) |                 if (count < 0) | ||||||
|                     return converterr(nullable, buf, arg, msgbuf, bufsize); |                     return converterr(buf, arg, msgbuf, bufsize); | ||||||
|                 *psize = count; |                 *psize = count; | ||||||
|             } |             } | ||||||
|  |             format++; | ||||||
|         } else { |         } else { | ||||||
|             /* "s" or "z" */ |             /* "s" or "z" */ | ||||||
|             const char **p = va_arg(*p_va, const char **); |             const char **p = va_arg(*p_va, const char **); | ||||||
|             Py_ssize_t len; |             Py_ssize_t len; | ||||||
|             sarg = NULL; |             sarg = NULL; | ||||||
| 
 | 
 | ||||||
|             HANDLE_NULLABLE; |  | ||||||
|             if (c == 'z' && arg == Py_None) |             if (c == 'z' && arg == Py_None) | ||||||
|                 *p = NULL; |                 *p = NULL; | ||||||
|             else if (PyUnicode_Check(arg)) { |             else if (PyUnicode_Check(arg)) { | ||||||
|                 sarg = PyUnicode_AsUTF8AndSize(arg, &len); |                 sarg = PyUnicode_AsUTF8AndSize(arg, &len); | ||||||
|                 if (sarg == NULL) |                 if (sarg == NULL) | ||||||
|                     return converterr(nullable, CONV_UNICODE, |                     return converterr(CONV_UNICODE, | ||||||
|                                       arg, msgbuf, bufsize); |                                       arg, msgbuf, bufsize); | ||||||
|                 if (strlen(sarg) != (size_t)len) { |                 if (strlen(sarg) != (size_t)len) { | ||||||
|                     PyErr_SetString(PyExc_ValueError, "embedded null character"); |                     PyErr_SetString(PyExc_ValueError, "embedded null character"); | ||||||
|  | @ -1087,7 +1030,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|                 *p = sarg; |                 *p = sarg; | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|                 return converterr(c == 'z' || nullable, "str", |                 return converterr(c == 'z' ? "str or None" : "str", | ||||||
|                                   arg, msgbuf, bufsize); |                                   arg, msgbuf, bufsize); | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|  | @ -1116,14 +1059,48 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|             recode_strings = 0; |             recode_strings = 0; | ||||||
|         else |         else | ||||||
|             return converterr( |             return converterr( | ||||||
|                 nullable, "(unknown parser marker combination)", |                 "(unknown parser marker combination)", | ||||||
|                 arg, msgbuf, bufsize); |                 arg, msgbuf, bufsize); | ||||||
|         buffer = (char **)va_arg(*p_va, char **); |         buffer = (char **)va_arg(*p_va, char **); | ||||||
|         format++; |         format++; | ||||||
|         if (buffer == NULL) |         if (buffer == NULL) | ||||||
|             return converterr(nullable, "(buffer is NULL)", |             return converterr("(buffer is NULL)", | ||||||
|                               arg, msgbuf, bufsize); |                               arg, msgbuf, bufsize); | ||||||
|         Py_ssize_t *psize = NULL; | 
 | ||||||
|  |         /* Encode object */ | ||||||
|  |         if (!recode_strings && | ||||||
|  |             (PyBytes_Check(arg) || PyByteArray_Check(arg))) { | ||||||
|  |             s = Py_NewRef(arg); | ||||||
|  |             if (PyBytes_Check(arg)) { | ||||||
|  |                 size = PyBytes_GET_SIZE(s); | ||||||
|  |                 ptr = PyBytes_AS_STRING(s); | ||||||
|  |             } | ||||||
|  |             else { | ||||||
|  |                 size = PyByteArray_GET_SIZE(s); | ||||||
|  |                 ptr = PyByteArray_AS_STRING(s); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         else if (PyUnicode_Check(arg)) { | ||||||
|  |             /* Encode object; use default error handling */ | ||||||
|  |             s = PyUnicode_AsEncodedString(arg, | ||||||
|  |                                           encoding, | ||||||
|  |                                           NULL); | ||||||
|  |             if (s == NULL) | ||||||
|  |                 return converterr("(encoding failed)", | ||||||
|  |                                   arg, msgbuf, bufsize); | ||||||
|  |             assert(PyBytes_Check(s)); | ||||||
|  |             size = PyBytes_GET_SIZE(s); | ||||||
|  |             ptr = PyBytes_AS_STRING(s); | ||||||
|  |             if (ptr == NULL) | ||||||
|  |                 ptr = ""; | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             return converterr( | ||||||
|  |                 recode_strings ? "str" : "str, bytes or bytearray", | ||||||
|  |                 arg, msgbuf, bufsize); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /* Write output; output is guaranteed to be 0-terminated */ | ||||||
|         if (*format == '#') { |         if (*format == '#') { | ||||||
|             /* Using buffer length parameter '#':
 |             /* Using buffer length parameter '#':
 | ||||||
| 
 | 
 | ||||||
|  | @ -1146,55 +1123,15 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|                trailing 0-byte |                trailing 0-byte | ||||||
| 
 | 
 | ||||||
|             */ |             */ | ||||||
|             psize = va_arg(*p_va, Py_ssize_t*); |             Py_ssize_t *psize = va_arg(*p_va, Py_ssize_t*); | ||||||
| 
 | 
 | ||||||
|             format++; |             format++; | ||||||
|             if (psize == NULL) { |             if (psize == NULL) { | ||||||
|  |                 Py_DECREF(s); | ||||||
|                 return converterr( |                 return converterr( | ||||||
|                     nullable, "(buffer_len is NULL)", |                     "(buffer_len is NULL)", | ||||||
|                     arg, msgbuf, bufsize); |                     arg, msgbuf, bufsize); | ||||||
|             } |             } | ||||||
|         } |  | ||||||
|         HANDLE_NULLABLE; |  | ||||||
| 
 |  | ||||||
|         /* Encode object */ |  | ||||||
|         if (!recode_strings && |  | ||||||
|             (PyBytes_Check(arg) || PyByteArray_Check(arg))) { |  | ||||||
|             s = Py_NewRef(arg); |  | ||||||
|             if (PyBytes_Check(arg)) { |  | ||||||
|                 size = PyBytes_GET_SIZE(s); |  | ||||||
|                 ptr = PyBytes_AS_STRING(s); |  | ||||||
|             } |  | ||||||
|             else { |  | ||||||
|                 size = PyByteArray_GET_SIZE(s); |  | ||||||
|                 ptr = PyByteArray_AS_STRING(s); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         else if (PyUnicode_Check(arg)) { |  | ||||||
|             /* Encode object; use default error handling */ |  | ||||||
|             s = PyUnicode_AsEncodedString(arg, |  | ||||||
|                                           encoding, |  | ||||||
|                                           NULL); |  | ||||||
|             if (s == NULL) |  | ||||||
|                 return converterr(nullable, "(encoding failed)", |  | ||||||
|                                   arg, msgbuf, bufsize); |  | ||||||
|             assert(PyBytes_Check(s)); |  | ||||||
|             size = PyBytes_GET_SIZE(s); |  | ||||||
|             ptr = PyBytes_AS_STRING(s); |  | ||||||
|             if (ptr == NULL) |  | ||||||
|                 ptr = ""; |  | ||||||
|         } |  | ||||||
|         else { |  | ||||||
|             return converterr( |  | ||||||
|                 nullable, |  | ||||||
|                 recode_strings ? "str" |  | ||||||
|                 : nullable ? "str, bytes, bytearray" |  | ||||||
|                 : "str, bytes or bytearray", |  | ||||||
|                 arg, msgbuf, bufsize); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /* Write output; output is guaranteed to be 0-terminated */ |  | ||||||
|         if (psize != NULL) { |  | ||||||
|             if (*buffer == NULL) { |             if (*buffer == NULL) { | ||||||
|                 *buffer = PyMem_NEW(char, size + 1); |                 *buffer = PyMem_NEW(char, size + 1); | ||||||
|                 if (*buffer == NULL) { |                 if (*buffer == NULL) { | ||||||
|  | @ -1205,7 +1142,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|                 if (addcleanup(buffer, freelist, cleanup_ptr)) { |                 if (addcleanup(buffer, freelist, cleanup_ptr)) { | ||||||
|                     Py_DECREF(s); |                     Py_DECREF(s); | ||||||
|                     return converterr( |                     return converterr( | ||||||
|                         nullable, "(cleanup problem)", |                         "(cleanup problem)", | ||||||
|                         arg, msgbuf, bufsize); |                         arg, msgbuf, bufsize); | ||||||
|                 } |                 } | ||||||
|             } else { |             } else { | ||||||
|  | @ -1239,7 +1176,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|             if ((Py_ssize_t)strlen(ptr) != size) { |             if ((Py_ssize_t)strlen(ptr) != size) { | ||||||
|                 Py_DECREF(s); |                 Py_DECREF(s); | ||||||
|                 return converterr( |                 return converterr( | ||||||
|                     nullable, "encoded string without null bytes", |                     "encoded string without null bytes", | ||||||
|                     arg, msgbuf, bufsize); |                     arg, msgbuf, bufsize); | ||||||
|             } |             } | ||||||
|             *buffer = PyMem_NEW(char, size + 1); |             *buffer = PyMem_NEW(char, size + 1); | ||||||
|  | @ -1250,7 +1187,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|             } |             } | ||||||
|             if (addcleanup(buffer, freelist, cleanup_ptr)) { |             if (addcleanup(buffer, freelist, cleanup_ptr)) { | ||||||
|                 Py_DECREF(s); |                 Py_DECREF(s); | ||||||
|                 return converterr(nullable, "(cleanup problem)", |                 return converterr("(cleanup problem)", | ||||||
|                                 arg, msgbuf, bufsize); |                                 arg, msgbuf, bufsize); | ||||||
|             } |             } | ||||||
|             memcpy(*buffer, ptr, size+1); |             memcpy(*buffer, ptr, size+1); | ||||||
|  | @ -1261,32 +1198,29 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
| 
 | 
 | ||||||
|     case 'S': { /* PyBytes object */ |     case 'S': { /* PyBytes object */ | ||||||
|         PyObject **p = va_arg(*p_va, PyObject **); |         PyObject **p = va_arg(*p_va, PyObject **); | ||||||
|         HANDLE_NULLABLE; |  | ||||||
|         if (PyBytes_Check(arg)) |         if (PyBytes_Check(arg)) | ||||||
|             *p = arg; |             *p = arg; | ||||||
|         else |         else | ||||||
|             return converterr(nullable, "bytes", arg, msgbuf, bufsize); |             return converterr("bytes", arg, msgbuf, bufsize); | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     case 'Y': { /* PyByteArray object */ |     case 'Y': { /* PyByteArray object */ | ||||||
|         PyObject **p = va_arg(*p_va, PyObject **); |         PyObject **p = va_arg(*p_va, PyObject **); | ||||||
|         HANDLE_NULLABLE; |  | ||||||
|         if (PyByteArray_Check(arg)) |         if (PyByteArray_Check(arg)) | ||||||
|             *p = arg; |             *p = arg; | ||||||
|         else |         else | ||||||
|             return converterr(nullable, "bytearray", arg, msgbuf, bufsize); |             return converterr("bytearray", arg, msgbuf, bufsize); | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     case 'U': { /* PyUnicode object */ |     case 'U': { /* PyUnicode object */ | ||||||
|         PyObject **p = va_arg(*p_va, PyObject **); |         PyObject **p = va_arg(*p_va, PyObject **); | ||||||
|         HANDLE_NULLABLE; |  | ||||||
|         if (PyUnicode_Check(arg)) { |         if (PyUnicode_Check(arg)) { | ||||||
|             *p = arg; |             *p = arg; | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|             return converterr(nullable, "str", arg, msgbuf, bufsize); |             return converterr("str", arg, msgbuf, bufsize); | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -1297,11 +1231,10 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|             type = va_arg(*p_va, PyTypeObject*); |             type = va_arg(*p_va, PyTypeObject*); | ||||||
|             p = va_arg(*p_va, PyObject **); |             p = va_arg(*p_va, PyObject **); | ||||||
|             format++; |             format++; | ||||||
|             HANDLE_NULLABLE; |  | ||||||
|             if (PyType_IsSubtype(Py_TYPE(arg), type)) |             if (PyType_IsSubtype(Py_TYPE(arg), type)) | ||||||
|                 *p = arg; |                 *p = arg; | ||||||
|             else |             else | ||||||
|                 return converterr(nullable, type->tp_name, arg, msgbuf, bufsize); |                 return converterr(type->tp_name, arg, msgbuf, bufsize); | ||||||
| 
 | 
 | ||||||
|         } |         } | ||||||
|         else if (*format == '&') { |         else if (*format == '&') { | ||||||
|  | @ -1310,18 +1243,16 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
|             void *addr = va_arg(*p_va, void *); |             void *addr = va_arg(*p_va, void *); | ||||||
|             int res; |             int res; | ||||||
|             format++; |             format++; | ||||||
|             HANDLE_NULLABLE; |  | ||||||
|             if (! (res = (*convert)(arg, addr))) |             if (! (res = (*convert)(arg, addr))) | ||||||
|                 return converterr(nullable, "(unspecified)", |                 return converterr("(unspecified)", | ||||||
|                                   arg, msgbuf, bufsize); |                                   arg, msgbuf, bufsize); | ||||||
|             if (res == Py_CLEANUP_SUPPORTED && |             if (res == Py_CLEANUP_SUPPORTED && | ||||||
|                 addcleanup(addr, freelist, convert) == -1) |                 addcleanup(addr, freelist, convert) == -1) | ||||||
|                 return converterr(nullable, "(cleanup problem)", |                 return converterr("(cleanup problem)", | ||||||
|                                 arg, msgbuf, bufsize); |                                 arg, msgbuf, bufsize); | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|             p = va_arg(*p_va, PyObject **); |             p = va_arg(*p_va, PyObject **); | ||||||
|             HANDLE_NULLABLE; |  | ||||||
|             *p = arg; |             *p = arg; | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|  | @ -1333,30 +1264,29 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, | ||||||
| 
 | 
 | ||||||
|         if (*format != '*') |         if (*format != '*') | ||||||
|             return converterr( |             return converterr( | ||||||
|                 nullable, "(invalid use of 'w' format character)", |                 "(invalid use of 'w' format character)", | ||||||
|                 arg, msgbuf, bufsize); |                 arg, msgbuf, bufsize); | ||||||
|         format++; |         format++; | ||||||
|         HANDLE_NULLABLE; |  | ||||||
| 
 | 
 | ||||||
|         /* Caller is interested in Py_buffer, and the object supports it
 |         /* Caller is interested in Py_buffer, and the object supports it
 | ||||||
|            directly. The request implicitly asks for PyBUF_SIMPLE, so the |            directly. The request implicitly asks for PyBUF_SIMPLE, so the | ||||||
|            result is C-contiguous with format 'B'. */ |            result is C-contiguous with format 'B'. */ | ||||||
|         if (PyObject_GetBuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) { |         if (PyObject_GetBuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) { | ||||||
|             PyErr_Clear(); |             PyErr_Clear(); | ||||||
|             return converterr(nullable, "read-write bytes-like object", |             return converterr("read-write bytes-like object", | ||||||
|                               arg, msgbuf, bufsize); |                               arg, msgbuf, bufsize); | ||||||
|         } |         } | ||||||
|         assert(PyBuffer_IsContiguous((Py_buffer *)p, 'C')); |         assert(PyBuffer_IsContiguous((Py_buffer *)p, 'C')); | ||||||
|         if (addcleanup(p, freelist, cleanup_buffer)) { |         if (addcleanup(p, freelist, cleanup_buffer)) { | ||||||
|             return converterr( |             return converterr( | ||||||
|                 nullable, "(cleanup problem)", |                 "(cleanup problem)", | ||||||
|                 arg, msgbuf, bufsize); |                 arg, msgbuf, bufsize); | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     default: |     default: | ||||||
|         return converterr(nullable, "(impossible<bad format char>)", arg, msgbuf, bufsize); |         return converterr("(impossible<bad format char>)", arg, msgbuf, bufsize); | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -2751,9 +2681,6 @@ skipitem(const char **p_format, va_list *p_va, int flags) | ||||||
|         return "impossible<bad format char>"; |         return "impossible<bad format char>"; | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
|     if (*format == '?') { |  | ||||||
|         format++; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     *p_format = format; |     *p_format = format; | ||||||
|     return NULL; |     return NULL; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Serhiy Storchaka
						Serhiy Storchaka