diff options
author | shadchin <shadchin@yandex-team.ru> | 2022-04-18 12:39:32 +0300 |
---|---|---|
committer | shadchin <shadchin@yandex-team.ru> | 2022-04-18 12:39:32 +0300 |
commit | d4be68e361f4258cf0848fc70018dfe37a2acc24 (patch) | |
tree | 153e294cd97ac8b5d7a989612704a0c1f58e8ad4 /contrib/tools/python3/src/Modules | |
parent | 260c02f5ccf242d9d9b8a873afaf6588c00237d6 (diff) | |
download | ydb-d4be68e361f4258cf0848fc70018dfe37a2acc24.tar.gz |
IGNIETFERRO-1816 Update Python 3 from 3.9.12 to 3.10.4
ref:9f96be6d02ee8044fdd6f124b799b270c20ce641
Diffstat (limited to 'contrib/tools/python3/src/Modules')
199 files changed, 21620 insertions, 15245 deletions
diff --git a/contrib/tools/python3/src/Modules/_abc.c b/contrib/tools/python3/src/Modules/_abc.c index 709b52ff96..8aa6835903 100644 --- a/contrib/tools/python3/src/Modules/_abc.c +++ b/contrib/tools/python3/src/Modules/_abc.c @@ -1,6 +1,7 @@ /* ABCMeta implementation */ #include "Python.h" +#include "pycore_moduleobject.h" // _PyModule_GetState() #include "clinic/_abc.c.h" /*[clinic input] @@ -14,6 +15,7 @@ PyDoc_STRVAR(_abc__doc__, _Py_IDENTIFIER(__abstractmethods__); _Py_IDENTIFIER(__class__); _Py_IDENTIFIER(__dict__); +_Py_IDENTIFIER(__abc_tpflags__); _Py_IDENTIFIER(__bases__); _Py_IDENTIFIER(_abc_impl); _Py_IDENTIFIER(__subclasscheck__); @@ -27,7 +29,7 @@ typedef struct { static inline _abcmodule_state* get_abc_state(PyObject *module) { - void *state = PyModule_GetState(module); + void *state = _PyModule_GetState(module); assert(state != NULL); return (_abcmodule_state *)state; } @@ -416,6 +418,8 @@ error: return ret; } +#define COLLECTION_FLAGS (Py_TPFLAGS_SEQUENCE | Py_TPFLAGS_MAPPING) + /*[clinic input] _abc._abc_init @@ -445,9 +449,64 @@ _abc__abc_init(PyObject *module, PyObject *self) return NULL; } Py_DECREF(data); + /* If __abc_tpflags__ & COLLECTION_FLAGS is set, then set the corresponding bit(s) + * in the new class. + * Used by collections.abc.Sequence and collections.abc.Mapping to indicate + * their special status w.r.t. pattern matching. */ + if (PyType_Check(self)) { + PyTypeObject *cls = (PyTypeObject *)self; + PyObject *flags = _PyDict_GetItemIdWithError(cls->tp_dict, &PyId___abc_tpflags__); + if (flags == NULL) { + if (PyErr_Occurred()) { + return NULL; + } + } + else { + if (PyLong_CheckExact(flags)) { + long val = PyLong_AsLong(flags); + if (val == -1 && PyErr_Occurred()) { + return NULL; + } + if ((val & COLLECTION_FLAGS) == COLLECTION_FLAGS) { + PyErr_SetString(PyExc_TypeError, "__abc_tpflags__ cannot be both Py_TPFLAGS_SEQUENCE and Py_TPFLAGS_MAPPING"); + return NULL; + } + ((PyTypeObject *)self)->tp_flags |= (val & COLLECTION_FLAGS); + } + if (_PyDict_DelItemId(cls->tp_dict, &PyId___abc_tpflags__) < 0) { + return NULL; + } + } + } Py_RETURN_NONE; } +static void +set_collection_flag_recursive(PyTypeObject *child, unsigned long flag) +{ + assert(flag == Py_TPFLAGS_MAPPING || flag == Py_TPFLAGS_SEQUENCE); + if (PyType_HasFeature(child, Py_TPFLAGS_IMMUTABLETYPE) || + (child->tp_flags & COLLECTION_FLAGS) == flag) + { + return; + } + child->tp_flags &= ~COLLECTION_FLAGS; + child->tp_flags |= flag; + PyObject *grandchildren = child->tp_subclasses; + if (grandchildren == NULL) { + return; + } + assert(PyDict_CheckExact(grandchildren)); + Py_ssize_t i = 0; + while (PyDict_Next(grandchildren, &i, NULL, &grandchildren)) { + assert(PyWeakref_CheckRef(grandchildren)); + PyObject *grandchild = PyWeakref_GET_OBJECT(grandchildren); + if (PyType_Check(grandchild)) { + set_collection_flag_recursive((PyTypeObject *)grandchild, flag); + } + } +} + /*[clinic input] _abc._abc_register @@ -498,6 +557,13 @@ _abc__abc_register_impl(PyObject *module, PyObject *self, PyObject *subclass) /* Invalidate negative cache */ get_abc_state(module)->abc_invalidation_counter++; + /* Set Py_TPFLAGS_SEQUENCE or Py_TPFLAGS_MAPPING flag */ + if (PyType_Check(self)) { + unsigned long collection_flag = ((PyTypeObject *)self)->tp_flags & COLLECTION_FLAGS; + if (collection_flag) { + set_collection_flag_recursive((PyTypeObject *)subclass, collection_flag); + } + } Py_INCREF(subclass); return subclass; } @@ -891,14 +957,14 @@ static PyModuleDef_Slot _abcmodule_slots[] = { static struct PyModuleDef _abcmodule = { PyModuleDef_HEAD_INIT, - "_abc", - _abc__doc__, - sizeof(_abcmodule_state), - _abcmodule_methods, - _abcmodule_slots, - _abcmodule_traverse, - _abcmodule_clear, - _abcmodule_free, + .m_name = "_abc", + .m_doc = _abc__doc__, + .m_size = sizeof(_abcmodule_state), + .m_methods = _abcmodule_methods, + .m_slots = _abcmodule_slots, + .m_traverse = _abcmodule_traverse, + .m_clear = _abcmodule_clear, + .m_free = _abcmodule_free, }; PyMODINIT_FUNC diff --git a/contrib/tools/python3/src/Modules/_asynciomodule.c b/contrib/tools/python3/src/Modules/_asynciomodule.c index b64069a25a..392e0e7c73 100644 --- a/contrib/tools/python3/src/Modules/_asynciomodule.c +++ b/contrib/tools/python3/src/Modules/_asynciomodule.c @@ -16,7 +16,6 @@ _Py_IDENTIFIER(add_done_callback); _Py_IDENTIFIER(call_soon); _Py_IDENTIFIER(cancel); _Py_IDENTIFIER(get_event_loop); -_Py_IDENTIFIER(send); _Py_IDENTIFIER(throw); @@ -96,11 +95,6 @@ typedef struct { typedef struct { PyObject_HEAD - TaskObj *ww_task; -} TaskWakeupMethWrapper; - -typedef struct { - PyObject_HEAD PyObject *rl_loop; #if defined(HAVE_GETPID) && !defined(MS_WINDOWS) pid_t rl_pid; @@ -325,7 +319,7 @@ set_running_loop(PyObject *loop) static PyObject * -get_event_loop(void) +get_event_loop(int stacklevel) { PyObject *loop; PyObject *policy; @@ -337,6 +331,13 @@ get_event_loop(void) return loop; } + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "There is no current event loop", + stacklevel)) + { + return NULL; + } + policy = PyObject_CallNoArgs(asyncio_get_event_loop_policy); if (policy == NULL) { return NULL; @@ -495,7 +496,7 @@ future_init(FutureObj *fut, PyObject *loop) fut->fut_blocking = 0; if (loop == Py_None) { - loop = get_event_loop(); + loop = get_event_loop(1); if (loop == NULL) { return -1; } @@ -714,6 +715,7 @@ future_add_done_callback(FutureObj *fut, PyObject *arg, PyObject *ctx) else { fut->fut_callbacks = PyList_New(1); if (fut->fut_callbacks == NULL) { + Py_DECREF(tup); return NULL; } @@ -1477,7 +1479,8 @@ finally: static PyAsyncMethods FutureType_as_async = { (unaryfunc)future_new_iter, /* am_await */ 0, /* am_aiter */ - 0 /* am_anext */ + 0, /* am_anext */ + 0, /* am_send */ }; static PyMethodDef FutureType_methods[] = { @@ -1595,37 +1598,61 @@ FutureIter_dealloc(futureiterobject *it) } } -static PyObject * -FutureIter_iternext(futureiterobject *it) +static PySendResult +FutureIter_am_send(futureiterobject *it, + PyObject *Py_UNUSED(arg), + PyObject **result) { + /* arg is unused, see the comment on FutureIter_send for clarification */ + PyObject *res; FutureObj *fut = it->future; + *result = NULL; if (fut == NULL) { - return NULL; + return PYGEN_ERROR; } if (fut->fut_state == STATE_PENDING) { if (!fut->fut_blocking) { fut->fut_blocking = 1; Py_INCREF(fut); - return (PyObject *)fut; + *result = (PyObject *)fut; + return PYGEN_NEXT; } PyErr_SetString(PyExc_RuntimeError, "await wasn't used with future"); - return NULL; + return PYGEN_ERROR; } it->future = NULL; res = _asyncio_Future_result_impl(fut); if (res != NULL) { - /* The result of the Future is not an exception. */ - (void)_PyGen_SetStopIterationValue(res); - Py_DECREF(res); + Py_DECREF(fut); + *result = res; + return PYGEN_RETURN; } Py_DECREF(fut); - return NULL; + return PYGEN_ERROR; +} + +static PyObject * +FutureIter_iternext(futureiterobject *it) +{ + PyObject *result; + switch (FutureIter_am_send(it, Py_None, &result)) { + case PYGEN_RETURN: + (void)_PyGen_SetStopIterationValue(result); + Py_DECREF(result); + return NULL; + case PYGEN_NEXT: + return result; + case PYGEN_ERROR: + return NULL; + default: + Py_UNREACHABLE(); + } } static PyObject * @@ -1714,12 +1741,21 @@ static PyMethodDef FutureIter_methods[] = { {NULL, NULL} /* Sentinel */ }; +static PyAsyncMethods FutureIterType_as_async = { + 0, /* am_await */ + 0, /* am_aiter */ + 0, /* am_anext */ + (sendfunc)FutureIter_am_send, /* am_send */ +}; + + static PyTypeObject FutureIterType = { PyVarObject_HEAD_INIT(NULL, 0) "_asyncio.FutureIter", .tp_basicsize = sizeof(futureiterobject), .tp_itemsize = 0, .tp_dealloc = (destructor)FutureIter_dealloc, + .tp_as_async = &FutureIterType_as_async, .tp_getattro = PyObject_GenericGetAttr, .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, .tp_traverse = (traverseproc)FutureIter_traverse, @@ -1863,93 +1899,15 @@ TaskStepMethWrapper_new(TaskObj *task, PyObject *arg) return (PyObject*) o; } -/* ----- Task._wakeup wrapper */ - -static PyObject * -TaskWakeupMethWrapper_call(TaskWakeupMethWrapper *o, - PyObject *args, PyObject *kwds) -{ - PyObject *fut; - - if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) { - PyErr_SetString(PyExc_TypeError, "function takes no keyword arguments"); - return NULL; - } - if (!PyArg_ParseTuple(args, "O", &fut)) { - return NULL; - } - - return task_wakeup(o->ww_task, fut); -} - -static int -TaskWakeupMethWrapper_clear(TaskWakeupMethWrapper *o) -{ - Py_CLEAR(o->ww_task); - return 0; -} - -static int -TaskWakeupMethWrapper_traverse(TaskWakeupMethWrapper *o, - visitproc visit, void *arg) -{ - Py_VISIT(o->ww_task); - return 0; -} - -static void -TaskWakeupMethWrapper_dealloc(TaskWakeupMethWrapper *o) -{ - PyObject_GC_UnTrack(o); - (void)TaskWakeupMethWrapper_clear(o); - Py_TYPE(o)->tp_free(o); -} - -static PyObject * -TaskWakeupMethWrapper_get___self__(TaskWakeupMethWrapper *o, void *Py_UNUSED(ignored)) -{ - if (o->ww_task) { - Py_INCREF(o->ww_task); - return (PyObject*)o->ww_task; - } - Py_RETURN_NONE; -} - -static PyGetSetDef TaskWakeupMethWrapper_getsetlist[] = { - {"__self__", (getter)TaskWakeupMethWrapper_get___self__, NULL, NULL}, - {NULL} /* Sentinel */ -}; +/* ----- Task._wakeup implementation */ -static PyTypeObject TaskWakeupMethWrapper_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "TaskWakeupMethWrapper", - .tp_basicsize = sizeof(TaskWakeupMethWrapper), - .tp_itemsize = 0, - .tp_dealloc = (destructor)TaskWakeupMethWrapper_dealloc, - .tp_call = (ternaryfunc)TaskWakeupMethWrapper_call, - .tp_getattro = PyObject_GenericGetAttr, - .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, - .tp_traverse = (traverseproc)TaskWakeupMethWrapper_traverse, - .tp_clear = (inquiry)TaskWakeupMethWrapper_clear, - .tp_getset = TaskWakeupMethWrapper_getsetlist, +static PyMethodDef TaskWakeupDef = { + "task_wakeup", + (PyCFunction)task_wakeup, + METH_O, + NULL }; -static PyObject * -TaskWakeupMethWrapper_new(TaskObj *task) -{ - TaskWakeupMethWrapper *o; - o = PyObject_GC_New(TaskWakeupMethWrapper, &TaskWakeupMethWrapper_Type); - if (o == NULL) { - return NULL; - } - - Py_INCREF(task); - o->ww_task = task; - - PyObject_GC_Track(o); - return (PyObject*) o; -} - /* ----- Task introspection helpers */ static int @@ -2606,6 +2564,20 @@ task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...) Py_RETURN_NONE; } +static inline int +gen_status_from_result(PyObject **result) +{ + if (*result != NULL) { + return PYGEN_NEXT; + } + if (_PyGen_FetchStopIterationValue(result) == 0) { + return PYGEN_RETURN; + } + + assert(PyErr_Occurred()); + return PYGEN_ERROR; +} + static PyObject * task_step_impl(TaskObj *task, PyObject *exc) { @@ -2664,26 +2636,23 @@ task_step_impl(TaskObj *task, PyObject *exc) return NULL; } + int gen_status = PYGEN_ERROR; if (exc == NULL) { - if (PyGen_CheckExact(coro) || PyCoro_CheckExact(coro)) { - result = _PyGen_Send((PyGenObject*)coro, Py_None); - } - else { - result = _PyObject_CallMethodIdOneArg(coro, &PyId_send, Py_None); - } + gen_status = PyIter_Send(coro, Py_None, &result); } else { result = _PyObject_CallMethodIdOneArg(coro, &PyId_throw, exc); + gen_status = gen_status_from_result(&result); if (clear_exc) { /* We created 'exc' during this call */ Py_DECREF(exc); } } - if (result == NULL) { + if (gen_status == PYGEN_RETURN || gen_status == PYGEN_ERROR) { PyObject *et, *ev, *tb; - if (_PyGen_FetchStopIterationValue(&o) == 0) { + if (result != NULL) { /* The error is StopIteration and that means that the underlying coroutine has resolved */ @@ -2694,10 +2663,10 @@ task_step_impl(TaskObj *task, PyObject *exc) res = future_cancel((FutureObj*)task, task->task_cancel_msg); } else { - res = future_set_result((FutureObj*)task, o); + res = future_set_result((FutureObj*)task, result); } - Py_DECREF(o); + Py_DECREF(result); if (res == NULL) { return NULL; @@ -2778,7 +2747,7 @@ task_step_impl(TaskObj *task, PyObject *exc) fut->fut_blocking = 0; /* result.add_done_callback(task._wakeup) */ - wrapper = TaskWakeupMethWrapper_new(task); + wrapper = PyCFunction_New(&TaskWakeupDef, (PyObject *)task); if (wrapper == NULL) { goto fail; } @@ -2859,7 +2828,7 @@ task_step_impl(TaskObj *task, PyObject *exc) goto fail; } - wrapper = TaskWakeupMethWrapper_new(task); + wrapper = PyCFunction_New(&TaskWakeupDef, (PyObject *)task); if (wrapper == NULL) { goto fail; } @@ -3101,7 +3070,19 @@ static PyObject * _asyncio_get_event_loop_impl(PyObject *module) /*[clinic end generated code: output=2a2d8b2f824c648b input=9364bf2916c8655d]*/ { - return get_event_loop(); + return get_event_loop(1); +} + +/*[clinic input] +_asyncio._get_event_loop + stacklevel: int = 3 +[clinic start generated code]*/ + +static PyObject * +_asyncio__get_event_loop_impl(PyObject *module, int stacklevel) +/*[clinic end generated code: output=9c1d6d3c802e67c9 input=d17aebbd686f711d]*/ +{ + return get_event_loop(stacklevel-1); } /*[clinic input] @@ -3399,6 +3380,7 @@ PyDoc_STRVAR(module_doc, "Accelerator module for asyncio"); static PyMethodDef asyncio_methods[] = { _ASYNCIO_GET_EVENT_LOOP_METHODDEF + _ASYNCIO__GET_EVENT_LOOP_METHODDEF _ASYNCIO_GET_RUNNING_LOOP_METHODDEF _ASYNCIO__GET_RUNNING_LOOP_METHODDEF _ASYNCIO__SET_RUNNING_LOOP_METHODDEF @@ -3434,9 +3416,6 @@ PyInit__asyncio(void) if (PyType_Ready(&TaskStepMethWrapper_Type) < 0) { return NULL; } - if (PyType_Ready(&TaskWakeupMethWrapper_Type) < 0) { - return NULL; - } if (PyType_Ready(&PyRunningLoopHolder_Type) < 0) { return NULL; } diff --git a/contrib/tools/python3/src/Modules/_bisectmodule.c b/contrib/tools/python3/src/Modules/_bisectmodule.c index 82d800d9a8..26c4b9bfb2 100644 --- a/contrib/tools/python3/src/Modules/_bisectmodule.c +++ b/contrib/tools/python3/src/Modules/_bisectmodule.c @@ -16,7 +16,8 @@ module _bisect _Py_IDENTIFIER(insert); static inline Py_ssize_t -internal_bisect_right(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t hi) +internal_bisect_right(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t hi, + PyObject* key) { PyObject *litem; Py_ssize_t mid; @@ -39,6 +40,14 @@ internal_bisect_right(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t litem = PySequence_GetItem(list, mid); if (litem == NULL) return -1; + if (key != Py_None) { + PyObject *newitem = PyObject_CallOneArg(key, litem); + if (newitem == NULL) { + Py_DECREF(litem); + return -1; + } + Py_SETREF(litem, newitem); + } res = PyObject_RichCompareBool(item, litem, Py_LT); Py_DECREF(litem); if (res < 0) @@ -58,12 +67,14 @@ _bisect.bisect_right -> Py_ssize_t x: object lo: Py_ssize_t = 0 hi: Py_ssize_t(c_default='-1', accept={int, NoneType}) = None + * + key: object = None Return the index where to insert item x in list a, assuming a is sorted. The return value i is such that all e in a[:i] have e <= x, and all e in -a[i:] have e > x. So if x already appears in the list, i points just -beyond the rightmost x already there +a[i:] have e > x. So if x already appears in the list, a.insert(i, x) will +insert just after the rightmost x already there. Optional args lo (default 0) and hi (default len(a)) bound the slice of a to be searched. @@ -71,10 +82,10 @@ slice of a to be searched. static Py_ssize_t _bisect_bisect_right_impl(PyObject *module, PyObject *a, PyObject *x, - Py_ssize_t lo, Py_ssize_t hi) -/*[clinic end generated code: output=419e150cf1d2a235 input=e72212b282c83375]*/ + Py_ssize_t lo, Py_ssize_t hi, PyObject *key) +/*[clinic end generated code: output=3a4bc09cc7c8a73d input=40fcc5afa06ae593]*/ { - return internal_bisect_right(a, x, lo, hi); + return internal_bisect_right(a, x, lo, hi, key); } /*[clinic input] @@ -84,6 +95,8 @@ _bisect.insort_right x: object lo: Py_ssize_t = 0 hi: Py_ssize_t(c_default='-1', accept={int, NoneType}) = None + * + key: object = None Insert item x in list a, and keep it sorted assuming a is sorted. @@ -95,11 +108,22 @@ slice of a to be searched. static PyObject * _bisect_insort_right_impl(PyObject *module, PyObject *a, PyObject *x, - Py_ssize_t lo, Py_ssize_t hi) -/*[clinic end generated code: output=c2caa3d4cd02035a input=d1c45bfa68182669]*/ + Py_ssize_t lo, Py_ssize_t hi, PyObject *key) +/*[clinic end generated code: output=ac3bf26d07aedda2 input=44e1708e26b7b802]*/ { - PyObject *result; - Py_ssize_t index = internal_bisect_right(a, x, lo, hi); + PyObject *result, *key_x; + Py_ssize_t index; + + if (key == Py_None) { + index = internal_bisect_right(a, x, lo, hi, key); + } else { + key_x = PyObject_CallOneArg(key, x); + if (x == NULL) { + return NULL; + } + index = internal_bisect_right(a, key_x, lo, hi, key); + Py_DECREF(key_x); + } if (index < 0) return NULL; if (PyList_CheckExact(a)) { @@ -117,7 +141,8 @@ _bisect_insort_right_impl(PyObject *module, PyObject *a, PyObject *x, } static inline Py_ssize_t -internal_bisect_left(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t hi) +internal_bisect_left(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t hi, + PyObject *key) { PyObject *litem; Py_ssize_t mid; @@ -140,6 +165,14 @@ internal_bisect_left(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t h litem = PySequence_GetItem(list, mid); if (litem == NULL) return -1; + if (key != Py_None) { + PyObject *newitem = PyObject_CallOneArg(key, litem); + if (newitem == NULL) { + Py_DECREF(litem); + return -1; + } + Py_SETREF(litem, newitem); + } res = PyObject_RichCompareBool(litem, item, Py_LT); Py_DECREF(litem); if (res < 0) @@ -160,12 +193,14 @@ _bisect.bisect_left -> Py_ssize_t x: object lo: Py_ssize_t = 0 hi: Py_ssize_t(c_default='-1', accept={int, NoneType}) = None + * + key: object = None Return the index where to insert item x in list a, assuming a is sorted. The return value i is such that all e in a[:i] have e < x, and all e in -a[i:] have e >= x. So if x already appears in the list, i points just -before the leftmost x already there. +a[i:] have e >= x. So if x already appears in the list, a.insert(i, x) will +insert just before the leftmost x already there. Optional args lo (default 0) and hi (default len(a)) bound the slice of a to be searched. @@ -173,10 +208,10 @@ slice of a to be searched. static Py_ssize_t _bisect_bisect_left_impl(PyObject *module, PyObject *a, PyObject *x, - Py_ssize_t lo, Py_ssize_t hi) -/*[clinic end generated code: output=af82168bc2856f24 input=2bd90f34afe5609f]*/ + Py_ssize_t lo, Py_ssize_t hi, PyObject *key) +/*[clinic end generated code: output=70749d6e5cae9284 input=90dd35b50ceb05e3]*/ { - return internal_bisect_left(a, x, lo, hi); + return internal_bisect_left(a, x, lo, hi, key); } @@ -187,6 +222,8 @@ _bisect.insort_left x: object lo: Py_ssize_t = 0 hi: Py_ssize_t(c_default='-1', accept={int, NoneType}) = None + * + key: object = None Insert item x in list a, and keep it sorted assuming a is sorted. @@ -198,11 +235,22 @@ slice of a to be searched. static PyObject * _bisect_insort_left_impl(PyObject *module, PyObject *a, PyObject *x, - Py_ssize_t lo, Py_ssize_t hi) -/*[clinic end generated code: output=9e8356c0844a182b input=bc4583308bce00cc]*/ + Py_ssize_t lo, Py_ssize_t hi, PyObject *key) +/*[clinic end generated code: output=b1d33e5e7ffff11e input=3ab65d8784f585b1]*/ { - PyObject *result; - Py_ssize_t index = internal_bisect_left(a, x, lo, hi); + PyObject *result, *key_x; + Py_ssize_t index; + + if (key == Py_None) { + index = internal_bisect_left(a, x, lo, hi, key); + } else { + key_x = PyObject_CallOneArg(key, x); + if (x == NULL) { + return NULL; + } + index = internal_bisect_left(a, key_x, lo, hi, key); + Py_DECREF(key_x); + } if (index < 0) return NULL; if (PyList_CheckExact(a)) { @@ -237,18 +285,14 @@ common approach.\n"); static struct PyModuleDef _bisectmodule = { PyModuleDef_HEAD_INIT, - "_bisect", - module_doc, - -1, - bisect_methods, - NULL, - NULL, - NULL, - NULL + .m_name = "_bisect", + .m_doc = module_doc, + .m_methods = bisect_methods, + .m_size = 0 }; PyMODINIT_FUNC PyInit__bisect(void) { - return PyModule_Create(&_bisectmodule); + return PyModuleDef_Init(&_bisectmodule); } diff --git a/contrib/tools/python3/src/Modules/_blake2/blake2b_impl.c b/contrib/tools/python3/src/Modules/_blake2/blake2b_impl.c index 7fb1296f8b..8b0d60d02a 100644 --- a/contrib/tools/python3/src/Modules/_blake2/blake2b_impl.c +++ b/contrib/tools/python3/src/Modules/_blake2/blake2b_impl.c @@ -34,7 +34,7 @@ #endif -extern PyTypeObject PyBlake2_BLAKE2bType; +extern PyType_Spec blake2b_type_spec; typedef struct { PyObject_HEAD @@ -391,47 +391,24 @@ py_blake2b_dealloc(PyObject *self) PyThread_free_lock(obj->lock); obj->lock = NULL; } - PyObject_Del(self); + + PyTypeObject *type = Py_TYPE(self); + PyObject_Free(self); + Py_DECREF(type); } +static PyType_Slot blake2b_type_slots[] = { + {Py_tp_dealloc, py_blake2b_dealloc}, + {Py_tp_doc, (char *)py_blake2b_new__doc__}, + {Py_tp_methods, py_blake2b_methods}, + {Py_tp_getset, py_blake2b_getsetters}, + {Py_tp_new, py_blake2b_new}, + {0,0} +}; -PyTypeObject PyBlake2_BLAKE2bType = { - PyVarObject_HEAD_INIT(NULL, 0) - "_blake2.blake2b", /* tp_name */ - sizeof(BLAKE2bObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - py_blake2b_dealloc, /* tp_dealloc */ - 0, /*tp_vectorcall_offset*/ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - py_blake2b_new__doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - py_blake2b_methods, /* tp_methods */ - 0, /* tp_members */ - py_blake2b_getsetters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - py_blake2b_new, /* tp_new */ +PyType_Spec blake2b_type_spec = { + .name = "_blake2.blake2b", + .basicsize = sizeof(BLAKE2bObject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, + .slots = blake2b_type_slots }; diff --git a/contrib/tools/python3/src/Modules/_blake2/blake2module.c b/contrib/tools/python3/src/Modules/_blake2/blake2module.c index ff142c9f3e..631de2cc0a 100644 --- a/contrib/tools/python3/src/Modules/_blake2/blake2module.c +++ b/contrib/tools/python3/src/Modules/_blake2/blake2module.c @@ -12,62 +12,81 @@ #include "impl/blake2.h" -extern PyTypeObject PyBlake2_BLAKE2bType; -extern PyTypeObject PyBlake2_BLAKE2sType; - +extern PyType_Spec blake2b_type_spec; +extern PyType_Spec blake2s_type_spec; PyDoc_STRVAR(blake2mod__doc__, "_blake2b provides BLAKE2b for hashlib\n" ); +typedef struct { + PyTypeObject* blake2b_type; + PyTypeObject* blake2s_type; +} Blake2State; + +static inline Blake2State* +blake2_get_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (Blake2State *)state; +} static struct PyMethodDef blake2mod_functions[] = { {NULL, NULL} }; -static struct PyModuleDef blake2_module = { - PyModuleDef_HEAD_INIT, - "_blake2", - blake2mod__doc__, - -1, - blake2mod_functions, - NULL, - NULL, - NULL, - NULL -}; +static int +_blake2_traverse(PyObject *module, visitproc visit, void *arg) +{ + Blake2State *state = blake2_get_state(module); + Py_VISIT(state->blake2b_type); + Py_VISIT(state->blake2s_type); + return 0; +} + +static int +_blake2_clear(PyObject *module) +{ + Blake2State *state = blake2_get_state(module); + Py_CLEAR(state->blake2b_type); + Py_CLEAR(state->blake2s_type); + return 0; +} + +static void +_blake2_free(void *module) +{ + _blake2_clear((PyObject *)module); +} #define ADD_INT(d, name, value) do { \ PyObject *x = PyLong_FromLong(value); \ - if (!x) { \ - Py_DECREF(m); \ - return NULL; \ - } \ + if (!x) \ + return -1; \ if (PyDict_SetItemString(d, name, x) < 0) { \ - Py_DECREF(m); \ - return NULL; \ + Py_DECREF(x); \ + return -1; \ } \ Py_DECREF(x); \ } while(0) - -PyMODINIT_FUNC -PyInit__blake2(void) +static int +blake2_exec(PyObject *m) { - PyObject *m; - PyObject *d; + Blake2State* st = blake2_get_state(m); - m = PyModule_Create(&blake2_module); - if (m == NULL) - return NULL; + st->blake2b_type = (PyTypeObject *)PyType_FromModuleAndSpec( + m, &blake2b_type_spec, NULL); + if (NULL == st->blake2b_type) + return -1; /* BLAKE2b */ - Py_SET_TYPE(&PyBlake2_BLAKE2bType, &PyType_Type); - if (PyModule_AddType(m, &PyBlake2_BLAKE2bType) < 0) { - return NULL; + if (PyModule_AddType(m, st->blake2b_type) < 0) { + return -1; } - d = PyBlake2_BLAKE2bType.tp_dict; + PyObject *d = st->blake2b_type->tp_dict; ADD_INT(d, "SALT_SIZE", BLAKE2B_SALTBYTES); ADD_INT(d, "PERSON_SIZE", BLAKE2B_PERSONALBYTES); ADD_INT(d, "MAX_KEY_SIZE", BLAKE2B_KEYBYTES); @@ -79,12 +98,17 @@ PyInit__blake2(void) PyModule_AddIntConstant(m, "BLAKE2B_MAX_DIGEST_SIZE", BLAKE2B_OUTBYTES); /* BLAKE2s */ - Py_SET_TYPE(&PyBlake2_BLAKE2sType, &PyType_Type); - if (PyModule_AddType(m, &PyBlake2_BLAKE2sType) < 0) { - return NULL; + st->blake2s_type = (PyTypeObject *)PyType_FromModuleAndSpec( + m, &blake2s_type_spec, NULL); + + if (NULL == st->blake2s_type) + return -1; + + if (PyModule_AddType(m, st->blake2s_type) < 0) { + return -1; } - d = PyBlake2_BLAKE2sType.tp_dict; + d = st->blake2s_type->tp_dict; ADD_INT(d, "SALT_SIZE", BLAKE2S_SALTBYTES); ADD_INT(d, "PERSON_SIZE", BLAKE2S_PERSONALBYTES); ADD_INT(d, "MAX_KEY_SIZE", BLAKE2S_KEYBYTES); @@ -95,5 +119,28 @@ PyInit__blake2(void) PyModule_AddIntConstant(m, "BLAKE2S_MAX_KEY_SIZE", BLAKE2S_KEYBYTES); PyModule_AddIntConstant(m, "BLAKE2S_MAX_DIGEST_SIZE", BLAKE2S_OUTBYTES); - return m; + return 0; } + +static PyModuleDef_Slot _blake2_slots[] = { + {Py_mod_exec, blake2_exec}, + {0, NULL} +}; + +static struct PyModuleDef blake2_module = { + PyModuleDef_HEAD_INIT, + "_blake2", + .m_doc = blake2mod__doc__, + .m_size = sizeof(Blake2State), + .m_methods = blake2mod_functions, + .m_slots = _blake2_slots, + .m_traverse = _blake2_traverse, + .m_clear = _blake2_clear, + .m_free = _blake2_free, +}; + +PyMODINIT_FUNC +PyInit__blake2(void) +{ + return PyModuleDef_Init(&blake2_module); +}
\ No newline at end of file diff --git a/contrib/tools/python3/src/Modules/_blake2/blake2s_impl.c b/contrib/tools/python3/src/Modules/_blake2/blake2s_impl.c index e3e90d0587..7ab3917aa1 100644 --- a/contrib/tools/python3/src/Modules/_blake2/blake2s_impl.c +++ b/contrib/tools/python3/src/Modules/_blake2/blake2s_impl.c @@ -33,8 +33,7 @@ #include "impl/blake2s-ref.c" #endif - -extern PyTypeObject PyBlake2_BLAKE2sType; +extern PyType_Spec blake2s_type_spec; typedef struct { PyObject_HEAD @@ -391,47 +390,24 @@ py_blake2s_dealloc(PyObject *self) PyThread_free_lock(obj->lock); obj->lock = NULL; } - PyObject_Del(self); + + PyTypeObject *type = Py_TYPE(self); + PyObject_Free(self); + Py_DECREF(type); } +static PyType_Slot blake2s_type_slots[] = { + {Py_tp_dealloc, py_blake2s_dealloc}, + {Py_tp_doc, (char *)py_blake2s_new__doc__}, + {Py_tp_methods, py_blake2s_methods}, + {Py_tp_getset, py_blake2s_getsetters}, + {Py_tp_new, py_blake2s_new}, + {0,0} +}; -PyTypeObject PyBlake2_BLAKE2sType = { - PyVarObject_HEAD_INIT(NULL, 0) - "_blake2.blake2s", /* tp_name */ - sizeof(BLAKE2sObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - py_blake2s_dealloc, /* tp_dealloc */ - 0, /*tp_vectorcall_offset*/ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - py_blake2s_new__doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - py_blake2s_methods, /* tp_methods */ - 0, /* tp_members */ - py_blake2s_getsetters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - py_blake2s_new, /* tp_new */ +PyType_Spec blake2s_type_spec = { + .name = "_blake2.blake2s", + .basicsize = sizeof(BLAKE2sObject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, + .slots = blake2s_type_slots }; diff --git a/contrib/tools/python3/src/Modules/_blake2/clinic/blake2b_impl.c.h b/contrib/tools/python3/src/Modules/_blake2/clinic/blake2b_impl.c.h index 07258c31c9..4e74e0885c 100644 --- a/contrib/tools/python3/src/Modules/_blake2/clinic/blake2b_impl.c.h +++ b/contrib/tools/python3/src/Modules/_blake2/clinic/blake2b_impl.c.h @@ -56,11 +56,6 @@ skip_optional_posonly: goto skip_optional_kwonly; } if (fastargs[1]) { - if (PyFloat_Check(fastargs[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } digest_size = _PyLong_AsInt(fastargs[1]); if (digest_size == -1 && PyErr_Occurred()) { goto exit; @@ -106,11 +101,6 @@ skip_optional_posonly: } } if (fastargs[5]) { - if (PyFloat_Check(fastargs[5])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fanout = _PyLong_AsInt(fastargs[5]); if (fanout == -1 && PyErr_Occurred()) { goto exit; @@ -120,11 +110,6 @@ skip_optional_posonly: } } if (fastargs[6]) { - if (PyFloat_Check(fastargs[6])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } depth = _PyLong_AsInt(fastargs[6]); if (depth == -1 && PyErr_Occurred()) { goto exit; @@ -150,11 +135,6 @@ skip_optional_posonly: } } if (fastargs[9]) { - if (PyFloat_Check(fastargs[9])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } node_depth = _PyLong_AsInt(fastargs[9]); if (node_depth == -1 && PyErr_Occurred()) { goto exit; @@ -164,11 +144,6 @@ skip_optional_posonly: } } if (fastargs[10]) { - if (PyFloat_Check(fastargs[10])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } inner_size = _PyLong_AsInt(fastargs[10]); if (inner_size == -1 && PyErr_Occurred()) { goto exit; @@ -272,4 +247,4 @@ _blake2_blake2b_hexdigest(BLAKE2bObject *self, PyObject *Py_UNUSED(ignored)) { return _blake2_blake2b_hexdigest_impl(self); } -/*[clinic end generated code: output=2d6d0fe9aa42a42a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=10eb47aba77f192d input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/_blake2/clinic/blake2s_impl.c.h b/contrib/tools/python3/src/Modules/_blake2/clinic/blake2s_impl.c.h index 71c5706fb6..0f0d9835fb 100644 --- a/contrib/tools/python3/src/Modules/_blake2/clinic/blake2s_impl.c.h +++ b/contrib/tools/python3/src/Modules/_blake2/clinic/blake2s_impl.c.h @@ -56,11 +56,6 @@ skip_optional_posonly: goto skip_optional_kwonly; } if (fastargs[1]) { - if (PyFloat_Check(fastargs[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } digest_size = _PyLong_AsInt(fastargs[1]); if (digest_size == -1 && PyErr_Occurred()) { goto exit; @@ -106,11 +101,6 @@ skip_optional_posonly: } } if (fastargs[5]) { - if (PyFloat_Check(fastargs[5])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fanout = _PyLong_AsInt(fastargs[5]); if (fanout == -1 && PyErr_Occurred()) { goto exit; @@ -120,11 +110,6 @@ skip_optional_posonly: } } if (fastargs[6]) { - if (PyFloat_Check(fastargs[6])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } depth = _PyLong_AsInt(fastargs[6]); if (depth == -1 && PyErr_Occurred()) { goto exit; @@ -150,11 +135,6 @@ skip_optional_posonly: } } if (fastargs[9]) { - if (PyFloat_Check(fastargs[9])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } node_depth = _PyLong_AsInt(fastargs[9]); if (node_depth == -1 && PyErr_Occurred()) { goto exit; @@ -164,11 +144,6 @@ skip_optional_posonly: } } if (fastargs[10]) { - if (PyFloat_Check(fastargs[10])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } inner_size = _PyLong_AsInt(fastargs[10]); if (inner_size == -1 && PyErr_Occurred()) { goto exit; @@ -272,4 +247,4 @@ _blake2_blake2s_hexdigest(BLAKE2sObject *self, PyObject *Py_UNUSED(ignored)) { return _blake2_blake2s_hexdigest_impl(self); } -/*[clinic end generated code: output=c80d8d06ce40a192 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f7ee8092ed67e9c7 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/_bz2module.c b/contrib/tools/python3/src/Modules/_bz2module.c index 880632c623..798e9efc62 100644 --- a/contrib/tools/python3/src/Modules/_bz2module.c +++ b/contrib/tools/python3/src/Modules/_bz2module.c @@ -8,6 +8,59 @@ #include <bzlib.h> #include <stdio.h> +// Blocks output buffer wrappers +#include "pycore_blocks_output_buffer.h" + +#if OUTPUT_BUFFER_MAX_BLOCK_SIZE > UINT32_MAX + #error "The maximum block size accepted by libbzip2 is UINT32_MAX." +#endif + +/* On success, return value >= 0 + On failure, return -1 */ +static inline Py_ssize_t +OutputBuffer_InitAndGrow(_BlocksOutputBuffer *buffer, Py_ssize_t max_length, + char **next_out, uint32_t *avail_out) +{ + Py_ssize_t allocated; + + allocated = _BlocksOutputBuffer_InitAndGrow( + buffer, max_length, (void**) next_out); + *avail_out = (uint32_t) allocated; + return allocated; +} + +/* On success, return value >= 0 + On failure, return -1 */ +static inline Py_ssize_t +OutputBuffer_Grow(_BlocksOutputBuffer *buffer, + char **next_out, uint32_t *avail_out) +{ + Py_ssize_t allocated; + + allocated = _BlocksOutputBuffer_Grow( + buffer, (void**) next_out, (Py_ssize_t) *avail_out); + *avail_out = (uint32_t) allocated; + return allocated; +} + +static inline Py_ssize_t +OutputBuffer_GetDataSize(_BlocksOutputBuffer *buffer, uint32_t avail_out) +{ + return _BlocksOutputBuffer_GetDataSize(buffer, (Py_ssize_t) avail_out); +} + +static inline PyObject * +OutputBuffer_Finish(_BlocksOutputBuffer *buffer, uint32_t avail_out) +{ + return _BlocksOutputBuffer_Finish(buffer, (Py_ssize_t) avail_out); +} + +static inline void +OutputBuffer_OnError(_BlocksOutputBuffer *buffer) +{ + _BlocksOutputBuffer_OnError(buffer); +} + #ifndef BZ_CONFIG_ERROR #define BZ2_bzCompress bzCompress @@ -29,6 +82,19 @@ typedef struct { + PyTypeObject *bz2_compressor_type; + PyTypeObject *bz2_decompressor_type; +} _bz2_state; + +static inline _bz2_state* +get_bz2_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (_bz2_state *)state; +} + +typedef struct { PyObject_HEAD bz_stream bzs; int flushed; @@ -51,9 +117,6 @@ typedef struct { PyThread_type_lock lock; } BZ2Decompressor; -static PyTypeObject BZ2Compressor_Type; -static PyTypeObject BZ2Decompressor_Type; - /* Helper functions. */ static int @@ -105,52 +168,22 @@ catch_bz2_error(int bzerror) } } -#if BUFSIZ < 8192 -#define INITIAL_BUFFER_SIZE 8192 -#else -#define INITIAL_BUFFER_SIZE BUFSIZ -#endif - -static int -grow_buffer(PyObject **buf, Py_ssize_t max_length) -{ - /* Expand the buffer by an amount proportional to the current size, - giving us amortized linear-time behavior. Use a less-than-double - growth factor to avoid excessive allocation. */ - size_t size = PyBytes_GET_SIZE(*buf); - size_t new_size = size + (size >> 3) + 6; - - if (max_length > 0 && new_size > (size_t) max_length) - new_size = (size_t) max_length; - - if (new_size > size) { - return _PyBytes_Resize(buf, new_size); - } else { /* overflow */ - PyErr_SetString(PyExc_OverflowError, - "Unable to allocate buffer - output too large"); - return -1; - } -} - /* BZ2Compressor class. */ static PyObject * compress(BZ2Compressor *c, char *data, size_t len, int action) { - size_t data_size = 0; PyObject *result; + _BlocksOutputBuffer buffer = {.list = NULL}; - result = PyBytes_FromStringAndSize(NULL, INITIAL_BUFFER_SIZE); - if (result == NULL) - return NULL; - + if (OutputBuffer_InitAndGrow(&buffer, -1, &c->bzs.next_out, &c->bzs.avail_out) < 0) { + goto error; + } c->bzs.next_in = data; c->bzs.avail_in = 0; - c->bzs.next_out = PyBytes_AS_STRING(result); - c->bzs.avail_out = INITIAL_BUFFER_SIZE; + for (;;) { - char *this_out; int bzerror; /* On a 64-bit system, len might not fit in avail_in (an unsigned int). @@ -165,21 +198,15 @@ compress(BZ2Compressor *c, char *data, size_t len, int action) break; if (c->bzs.avail_out == 0) { - size_t buffer_left = PyBytes_GET_SIZE(result) - data_size; - if (buffer_left == 0) { - if (grow_buffer(&result, -1) < 0) - goto error; - c->bzs.next_out = PyBytes_AS_STRING(result) + data_size; - buffer_left = PyBytes_GET_SIZE(result) - data_size; + if (OutputBuffer_Grow(&buffer, &c->bzs.next_out, &c->bzs.avail_out) < 0) { + goto error; } - c->bzs.avail_out = (unsigned int)Py_MIN(buffer_left, UINT_MAX); } Py_BEGIN_ALLOW_THREADS - this_out = c->bzs.next_out; bzerror = BZ2_bzCompress(&c->bzs, action); - data_size += c->bzs.next_out - this_out; Py_END_ALLOW_THREADS + if (catch_bz2_error(bzerror)) goto error; @@ -187,13 +214,14 @@ compress(BZ2Compressor *c, char *data, size_t len, int action) if (action == BZ_FINISH && bzerror == BZ_STREAM_END) break; } - if (data_size != (size_t)PyBytes_GET_SIZE(result)) - if (_PyBytes_Resize(&result, data_size) < 0) - goto error; - return result; + + result = OutputBuffer_Finish(&buffer, c->bzs.avail_out); + if (result != NULL) { + return result; + } error: - Py_XDECREF(result); + OutputBuffer_OnError(&buffer); return NULL; } @@ -280,21 +308,11 @@ BZ2_Free(void* ctx, void *ptr) PyMem_RawFree(ptr); } -/*[clinic input] -_bz2.BZ2Compressor.__init__ - - compresslevel: int = 9 - Compression level, as a number between 1 and 9. - / - -Create a compressor object for compressing data incrementally. - -For one-shot compression, use the compress() function instead. -[clinic start generated code]*/ +/* Argument Clinic is not used since the Argument Clinic always want to + check the type which would be wrong here */ static int _bz2_BZ2Compressor___init___impl(BZ2Compressor *self, int compresslevel) -/*[clinic end generated code: output=c4e6adfd02963827 input=4e1ff7b8394b6e9a]*/ { int bzerror; @@ -325,13 +343,60 @@ error: return -1; } +PyDoc_STRVAR(_bz2_BZ2Compressor___init____doc__, +"BZ2Compressor(compresslevel=9, /)\n" +"--\n" +"\n" +"Create a compressor object for compressing data incrementally.\n" +"\n" +" compresslevel\n" +" Compression level, as a number between 1 and 9.\n" +"\n" +"For one-shot compression, use the compress() function instead."); + +static int +_bz2_BZ2Compressor___init__(PyObject *self, PyObject *args, PyObject *kwargs) +{ + int return_value = -1; + int compresslevel = 9; + + if (!_PyArg_NoKeywords("BZ2Compressor", kwargs)) { + goto exit; + } + if (!_PyArg_CheckPositional("BZ2Compressor", PyTuple_GET_SIZE(args), 0, 1)) { + goto exit; + } + if (PyTuple_GET_SIZE(args) < 1) { + goto skip_optional; + } + compresslevel = _PyLong_AsInt(PyTuple_GET_ITEM(args, 0)); + if (compresslevel == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = _bz2_BZ2Compressor___init___impl((BZ2Compressor *)self, compresslevel); + +exit: + return return_value; +} + static void BZ2Compressor_dealloc(BZ2Compressor *self) { BZ2_bzCompressEnd(&self->bzs); - if (self->lock != NULL) + if (self->lock != NULL) { PyThread_free_lock(self->lock); - Py_TYPE(self)->tp_free((PyObject *)self); + } + PyTypeObject *tp = Py_TYPE(self); + tp->tp_free((PyObject *)self); + Py_DECREF(tp); +} + +static int +BZ2Compressor_traverse(BZ2Compressor *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + return 0; } static PyMethodDef BZ2Compressor_methods[] = { @@ -340,48 +405,26 @@ static PyMethodDef BZ2Compressor_methods[] = { {NULL} }; - -static PyTypeObject BZ2Compressor_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_bz2.BZ2Compressor", /* tp_name */ - sizeof(BZ2Compressor), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)BZ2Compressor_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - _bz2_BZ2Compressor___init____doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - BZ2Compressor_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - _bz2_BZ2Compressor___init__, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ +static PyType_Slot bz2_compressor_type_slots[] = { + {Py_tp_dealloc, BZ2Compressor_dealloc}, + {Py_tp_methods, BZ2Compressor_methods}, + {Py_tp_init, _bz2_BZ2Compressor___init__}, + {Py_tp_new, PyType_GenericNew}, + {Py_tp_doc, (char *)_bz2_BZ2Compressor___init____doc__}, + {Py_tp_traverse, BZ2Compressor_traverse}, + {0, 0} }; +static PyType_Spec bz2_compressor_type_spec = { + .name = "_bz2.BZ2Compressor", + .basicsize = sizeof(BZ2Compressor), + // Calling PyType_GetModuleState() on a subclass is not safe. + // bz2_compressor_type_spec does not have Py_TPFLAGS_BASETYPE flag + // which prevents to create a subclass. + // So calling PyType_GetModuleState() in this file is always safe. + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE), + .slots = bz2_compressor_type_slots, +}; /* BZ2Decompressor class. */ @@ -395,36 +438,29 @@ decompress_buf(BZ2Decompressor *d, Py_ssize_t max_length) /* data_size is strictly positive, but because we repeatedly have to compare against max_length and PyBytes_GET_SIZE we declare it as signed */ - Py_ssize_t data_size = 0; PyObject *result; + _BlocksOutputBuffer buffer = {.list = NULL}; bz_stream *bzs = &d->bzs; - if (max_length < 0 || max_length >= INITIAL_BUFFER_SIZE) - result = PyBytes_FromStringAndSize(NULL, INITIAL_BUFFER_SIZE); - else - result = PyBytes_FromStringAndSize(NULL, max_length); - if (result == NULL) - return NULL; + if (OutputBuffer_InitAndGrow(&buffer, max_length, &bzs->next_out, &bzs->avail_out) < 0) { + goto error; + } - bzs->next_out = PyBytes_AS_STRING(result); for (;;) { int bzret; - size_t avail; - /* On a 64-bit system, buffer length might not fit in avail_out, so we do decompression in chunks of no more than UINT_MAX bytes each. Note that the expression for `avail` is guaranteed to be positive, so the cast is safe. */ - avail = (size_t) (PyBytes_GET_SIZE(result) - data_size); - bzs->avail_out = (unsigned int)Py_MIN(avail, UINT_MAX); bzs->avail_in = (unsigned int)Py_MIN(d->bzs_avail_in_real, UINT_MAX); d->bzs_avail_in_real -= bzs->avail_in; Py_BEGIN_ALLOW_THREADS bzret = BZ2_bzDecompress(bzs); - data_size = bzs->next_out - PyBytes_AS_STRING(result); - d->bzs_avail_in_real += bzs->avail_in; Py_END_ALLOW_THREADS + + d->bzs_avail_in_real += bzs->avail_in; + if (catch_bz2_error(bzret)) goto error; if (bzret == BZ_STREAM_END) { @@ -433,22 +469,22 @@ decompress_buf(BZ2Decompressor *d, Py_ssize_t max_length) } else if (d->bzs_avail_in_real == 0) { break; } else if (bzs->avail_out == 0) { - if (data_size == max_length) + if (OutputBuffer_GetDataSize(&buffer, bzs->avail_out) == max_length) { break; - if (data_size == PyBytes_GET_SIZE(result) && - grow_buffer(&result, max_length) == -1) + } + if (OutputBuffer_Grow(&buffer, &bzs->next_out, &bzs->avail_out) < 0) { goto error; - bzs->next_out = PyBytes_AS_STRING(result) + data_size; + } } } - if (data_size != PyBytes_GET_SIZE(result)) - if (_PyBytes_Resize(&result, data_size) == -1) - goto error; - return result; + result = OutputBuffer_Finish(&buffer, bzs->avail_out); + if (result != NULL) { + return result; + } error: - Py_XDECREF(result); + OutputBuffer_OnError(&buffer); return NULL; } @@ -601,17 +637,10 @@ _bz2_BZ2Decompressor_decompress_impl(BZ2Decompressor *self, Py_buffer *data, return result; } -/*[clinic input] -_bz2.BZ2Decompressor.__init__ - -Create a decompressor object for decompressing data incrementally. - -For one-shot decompression, use the decompress() function instead. -[clinic start generated code]*/ - +/* Argument Clinic is not used since the Argument Clinic always want to + check the type which would be wrong here */ static int _bz2_BZ2Decompressor___init___impl(BZ2Decompressor *self) -/*[clinic end generated code: output=e4d2b9bb866ab8f1 input=95f6500dcda60088]*/ { int bzerror; @@ -646,16 +675,53 @@ error: return -1; } +static int +_bz2_BZ2Decompressor___init__(PyObject *self, PyObject *args, PyObject *kwargs) +{ + int return_value = -1; + + if (!_PyArg_NoPositional("BZ2Decompressor", args)) { + goto exit; + } + if (!_PyArg_NoKeywords("BZ2Decompressor", kwargs)) { + goto exit; + } + return_value = _bz2_BZ2Decompressor___init___impl((BZ2Decompressor *)self); + +exit: + return return_value; +} + +PyDoc_STRVAR(_bz2_BZ2Decompressor___init____doc__, +"BZ2Decompressor()\n" +"--\n" +"\n" +"Create a decompressor object for decompressing data incrementally.\n" +"\n" +"For one-shot decompression, use the decompress() function instead."); + static void BZ2Decompressor_dealloc(BZ2Decompressor *self) { - if(self->input_buffer != NULL) + if(self->input_buffer != NULL) { PyMem_Free(self->input_buffer); + } BZ2_bzDecompressEnd(&self->bzs); Py_CLEAR(self->unused_data); - if (self->lock != NULL) + if (self->lock != NULL) { PyThread_free_lock(self->lock); - Py_TYPE(self)->tp_free((PyObject *)self); + } + + PyTypeObject *tp = Py_TYPE(self); + tp->tp_free((PyObject *)self); + Py_DECREF(tp); +} + +static int +BZ2Decompressor_traverse(BZ2Decompressor *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + return 0; } static PyMethodDef BZ2Decompressor_methods[] = { @@ -682,64 +748,81 @@ static PyMemberDef BZ2Decompressor_members[] = { {NULL} }; -static PyTypeObject BZ2Decompressor_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_bz2.BZ2Decompressor", /* tp_name */ - sizeof(BZ2Decompressor), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)BZ2Decompressor_dealloc,/* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - _bz2_BZ2Decompressor___init____doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - BZ2Decompressor_methods, /* tp_methods */ - BZ2Decompressor_members, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - _bz2_BZ2Decompressor___init__, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ +static PyType_Slot bz2_decompressor_type_slots[] = { + {Py_tp_dealloc, BZ2Decompressor_dealloc}, + {Py_tp_methods, BZ2Decompressor_methods}, + {Py_tp_init, _bz2_BZ2Decompressor___init__}, + {Py_tp_doc, (char *)_bz2_BZ2Decompressor___init____doc__}, + {Py_tp_members, BZ2Decompressor_members}, + {Py_tp_new, PyType_GenericNew}, + {Py_tp_traverse, BZ2Decompressor_traverse}, + {0, 0} }; +static PyType_Spec bz2_decompressor_type_spec = { + .name = "_bz2.BZ2Decompressor", + .basicsize = sizeof(BZ2Decompressor), + // Calling PyType_GetModuleState() on a subclass is not safe. + // bz2_decompressor_type_spec does not have Py_TPFLAGS_BASETYPE flag + // which prevents to create a subclass. + // So calling PyType_GetModuleState() in this file is always safe. + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE), + .slots = bz2_decompressor_type_slots, +}; /* Module initialization. */ static int _bz2_exec(PyObject *module) { - if (PyModule_AddType(module, &BZ2Compressor_Type) < 0) { + _bz2_state *state = get_bz2_state(module); + state->bz2_compressor_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, + &bz2_compressor_type_spec, NULL); + if (state->bz2_compressor_type == NULL) { return -1; } - if (PyModule_AddType(module, &BZ2Decompressor_Type) < 0) { + if (PyModule_AddType(module, state->bz2_compressor_type) < 0) { return -1; } + state->bz2_decompressor_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, + &bz2_decompressor_type_spec, NULL); + if (state->bz2_decompressor_type == NULL) { + return -1; + } + + if (PyModule_AddType(module, state->bz2_decompressor_type) < 0) { + return -1; + } + + return 0; +} + +static int +_bz2_traverse(PyObject *module, visitproc visit, void *arg) +{ + _bz2_state *state = get_bz2_state(module); + Py_VISIT(state->bz2_compressor_type); + Py_VISIT(state->bz2_decompressor_type); + return 0; +} + +static int +_bz2_clear(PyObject *module) +{ + _bz2_state *state = get_bz2_state(module); + Py_CLEAR(state->bz2_compressor_type); + Py_CLEAR(state->bz2_decompressor_type); return 0; } +static void +_bz2_free(void *module) +{ + _bz2_clear((PyObject *)module); +} + static struct PyModuleDef_Slot _bz2_slots[] = { {Py_mod_exec, _bz2_exec}, {0, NULL} @@ -747,14 +830,12 @@ static struct PyModuleDef_Slot _bz2_slots[] = { static struct PyModuleDef _bz2module = { PyModuleDef_HEAD_INIT, - "_bz2", - NULL, - 0, - NULL, - _bz2_slots, - NULL, - NULL, - NULL + .m_name = "_bz2", + .m_size = sizeof(_bz2_state), + .m_slots = _bz2_slots, + .m_traverse = _bz2_traverse, + .m_clear = _bz2_clear, + .m_free = _bz2_free, }; PyMODINIT_FUNC diff --git a/contrib/tools/python3/src/Modules/_codecsmodule.c b/contrib/tools/python3/src/Modules/_codecsmodule.c index cbe5cc50f1..50afc097b3 100644 --- a/contrib/tools/python3/src/Modules/_codecsmodule.c +++ b/contrib/tools/python3/src/Modules/_codecsmodule.c @@ -69,6 +69,27 @@ _codecs_register(PyObject *module, PyObject *search_function) } /*[clinic input] +_codecs.unregister + search_function: object + / + +Unregister a codec search function and clear the registry's cache. + +If the search function is not registered, do nothing. +[clinic start generated code]*/ + +static PyObject * +_codecs_unregister(PyObject *module, PyObject *search_function) +/*[clinic end generated code: output=1f0edee9cf246399 input=dd7c004c652d345e]*/ +{ + if (PyCodec_Unregister(search_function) < 0) { + return NULL; + } + + Py_RETURN_NONE; +} + +/*[clinic input] _codecs.lookup encoding: str / @@ -139,25 +160,6 @@ _codecs_decode_impl(PyObject *module, PyObject *obj, const char *encoding, /* --- Helpers ------------------------------------------------------------ */ -/*[clinic input] -_codecs._forget_codec - - encoding: str - / - -Purge the named codec from the internal codec lookup cache -[clinic start generated code]*/ - -static PyObject * -_codecs__forget_codec_impl(PyObject *module, const char *encoding) -/*[clinic end generated code: output=0bde9f0a5b084aa2 input=18d5d92d0e386c38]*/ -{ - if (_PyCodec_Forget(encoding) < 0) { - return NULL; - }; - Py_RETURN_NONE; -} - static PyObject *codec_tuple(PyObject *decoded, Py_ssize_t len) @@ -998,6 +1000,7 @@ _codecs_lookup_error_impl(PyObject *module, const char *name) static PyMethodDef _codecs_functions[] = { _CODECS_REGISTER_METHODDEF + _CODECS_UNREGISTER_METHODDEF _CODECS_LOOKUP_METHODDEF _CODECS_ENCODE_METHODDEF _CODECS_DECODE_METHODDEF @@ -1041,7 +1044,6 @@ static PyMethodDef _codecs_functions[] = { _CODECS_CODE_PAGE_DECODE_METHODDEF _CODECS_REGISTER_ERROR_METHODDEF _CODECS_LOOKUP_ERROR_METHODDEF - _CODECS__FORGET_CODEC_METHODDEF {NULL, NULL} /* sentinel */ }; diff --git a/contrib/tools/python3/src/Modules/_collectionsmodule.c b/contrib/tools/python3/src/Modules/_collectionsmodule.c index 2e19b83dce..eff03c789e 100644 --- a/contrib/tools/python3/src/Modules/_collectionsmodule.c +++ b/contrib/tools/python3/src/Modules/_collectionsmodule.c @@ -1,4 +1,5 @@ #include "Python.h" +#include "pycore_long.h" // _PyLong_GetZero() #include "structmember.h" // PyMemberDef #ifdef STDC_HEADERS @@ -898,9 +899,20 @@ deque_rotate(dequeobject *deque, PyObject *const *args, Py_ssize_t nargs) { Py_ssize_t n=1; - if (!_PyArg_ParseStack(args, nargs, "|n:rotate", &n)) { + if (!_PyArg_CheckPositional("deque.rotate", nargs, 0, 1)) { return NULL; } + if (nargs) { + PyObject *index = _PyNumber_Index(args[0]); + if (index == NULL) { + return NULL; + } + n = PyLong_AsSsize_t(index); + Py_DECREF(index); + if (n == -1 && PyErr_Occurred()) { + return NULL; + } + } if (!_deque_rotate(deque, n)) Py_RETURN_NONE; @@ -1146,38 +1158,6 @@ deque_insert(dequeobject *deque, PyObject *const *args, Py_ssize_t nargs) PyDoc_STRVAR(insert_doc, "D.insert(index, object) -- insert object before index"); -static PyObject * -deque_remove(dequeobject *deque, PyObject *value) -{ - Py_ssize_t i, n=Py_SIZE(deque); - - for (i=0 ; i<n ; i++) { - PyObject *item = deque->leftblock->data[deque->leftindex]; - int cmp = PyObject_RichCompareBool(item, value, Py_EQ); - - if (Py_SIZE(deque) != n) { - PyErr_SetString(PyExc_IndexError, - "deque mutated during remove()."); - return NULL; - } - if (cmp > 0) { - PyObject *tgt = deque_popleft(deque, NULL); - assert (tgt != NULL); - if (_deque_rotate(deque, i)) - return NULL; - Py_DECREF(tgt); - Py_RETURN_NONE; - } - else if (cmp < 0) { - _deque_rotate(deque, i); - return NULL; - } - _deque_rotate(deque, -1); - } - PyErr_SetString(PyExc_ValueError, "deque.remove(x): x not in deque"); - return NULL; -} - PyDoc_STRVAR(remove_doc, "D.remove(value) -- remove first occurrence of value."); @@ -1245,6 +1225,48 @@ deque_del_item(dequeobject *deque, Py_ssize_t i) return rv; } +static PyObject * +deque_remove(dequeobject *deque, PyObject *value) +{ + PyObject *item; + block *b = deque->leftblock; + Py_ssize_t i, n = Py_SIZE(deque), index = deque->leftindex; + size_t start_state = deque->state; + int cmp, rv; + + for (i = 0 ; i < n; i++) { + item = b->data[index]; + Py_INCREF(item); + cmp = PyObject_RichCompareBool(item, value, Py_EQ); + Py_DECREF(item); + if (cmp < 0) { + return NULL; + } + if (start_state != deque->state) { + PyErr_SetString(PyExc_IndexError, + "deque mutated during iteration"); + return NULL; + } + if (cmp > 0) { + break; + } + index++; + if (index == BLOCKLEN) { + b = b->rightlink; + index = 0; + } + } + if (i == n) { + PyErr_Format(PyExc_ValueError, "%R is not in deque", value); + return NULL; + } + rv = deque_del_item(deque, i); + if (rv == -1) { + return NULL; + } + Py_RETURN_NONE; +} + static int deque_ass_item(dequeobject *deque, Py_ssize_t i, PyObject *v) { @@ -1640,7 +1662,8 @@ static PyTypeObject deque_type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_SEQUENCE, /* tp_flags */ deque_doc, /* tp_doc */ (traverseproc)deque_traverse, /* tp_traverse */ @@ -2296,6 +2319,7 @@ _collections__count_elements_impl(PyObject *module, PyObject *mapping, PyObject *dict_get; PyObject *mapping_setitem; PyObject *dict_setitem; + PyObject *one = _PyLong_GetOne(); // borrowed reference it = PyObject_GetIter(iterable); if (it == NULL) @@ -2342,10 +2366,10 @@ _collections__count_elements_impl(PyObject *module, PyObject *mapping, if (oldval == NULL) { if (PyErr_Occurred()) goto done; - if (_PyDict_SetItem_KnownHash(mapping, key, _PyLong_One, hash) < 0) + if (_PyDict_SetItem_KnownHash(mapping, key, one, hash) < 0) goto done; } else { - newval = PyNumber_Add(oldval, _PyLong_One); + newval = PyNumber_Add(oldval, one); if (newval == NULL) goto done; if (_PyDict_SetItem_KnownHash(mapping, key, newval, hash) < 0) @@ -2354,19 +2378,21 @@ _collections__count_elements_impl(PyObject *module, PyObject *mapping, } Py_DECREF(key); } - } else { + } + else { bound_get = _PyObject_GetAttrId(mapping, &PyId_get); if (bound_get == NULL) goto done; + PyObject *zero = _PyLong_GetZero(); // borrowed reference while (1) { key = PyIter_Next(it); if (key == NULL) break; - oldval = PyObject_CallFunctionObjArgs(bound_get, key, _PyLong_Zero, NULL); + oldval = PyObject_CallFunctionObjArgs(bound_get, key, zero, NULL); if (oldval == NULL) break; - newval = PyNumber_Add(oldval, _PyLong_One); + newval = PyNumber_Add(oldval, one); Py_DECREF(oldval); if (newval == NULL) break; diff --git a/contrib/tools/python3/src/Modules/_contextvarsmodule.c b/contrib/tools/python3/src/Modules/_contextvarsmodule.c index d6d7f375d1..d13b5962c1 100644 --- a/contrib/tools/python3/src/Modules/_contextvarsmodule.c +++ b/contrib/tools/python3/src/Modules/_contextvarsmodule.c @@ -30,30 +30,15 @@ static PyMethodDef _contextvars_methods[] = { static int _contextvars_exec(PyObject *m) { - Py_INCREF(&PyContext_Type); - if (PyModule_AddObject(m, "Context", - (PyObject *)&PyContext_Type) < 0) - { - Py_DECREF(&PyContext_Type); + if (PyModule_AddType(m, &PyContext_Type) < 0) { return -1; } - - Py_INCREF(&PyContextVar_Type); - if (PyModule_AddObject(m, "ContextVar", - (PyObject *)&PyContextVar_Type) < 0) - { - Py_DECREF(&PyContextVar_Type); + if (PyModule_AddType(m, &PyContextVar_Type) < 0) { return -1; } - - Py_INCREF(&PyContextToken_Type); - if (PyModule_AddObject(m, "Token", - (PyObject *)&PyContextToken_Type) < 0) - { - Py_DECREF(&PyContextToken_Type); + if (PyModule_AddType(m, &PyContextToken_Type) < 0) { return -1; } - return 0; } diff --git a/contrib/tools/python3/src/Modules/_csv.c b/contrib/tools/python3/src/Modules/_csv.c index 029f473ae8..72f0791a43 100644 --- a/contrib/tools/python3/src/Modules/_csv.c +++ b/contrib/tools/python3/src/Modules/_csv.c @@ -18,9 +18,14 @@ module instead. typedef struct { PyObject *error_obj; /* CSV exception */ PyObject *dialects; /* Dialect registry */ + PyTypeObject *dialect_type; + PyTypeObject *reader_type; + PyTypeObject *writer_type; long field_limit; /* max parsed field size */ } _csvstate; +static struct PyModuleDef _csvmodule; + static inline _csvstate* get_csv_state(PyObject *module) { @@ -30,31 +35,35 @@ get_csv_state(PyObject *module) } static int -_csv_clear(PyObject *m) +_csv_clear(PyObject *module) { - Py_CLEAR(get_csv_state(m)->error_obj); - Py_CLEAR(get_csv_state(m)->dialects); + _csvstate *module_state = PyModule_GetState(module); + Py_CLEAR(module_state->error_obj); + Py_CLEAR(module_state->dialects); + Py_CLEAR(module_state->dialect_type); + Py_CLEAR(module_state->reader_type); + Py_CLEAR(module_state->writer_type); return 0; } static int -_csv_traverse(PyObject *m, visitproc visit, void *arg) +_csv_traverse(PyObject *module, visitproc visit, void *arg) { - Py_VISIT(get_csv_state(m)->error_obj); - Py_VISIT(get_csv_state(m)->dialects); + _csvstate *module_state = PyModule_GetState(module); + Py_VISIT(module_state->error_obj); + Py_VISIT(module_state->dialects); + Py_VISIT(module_state->dialect_type); + Py_VISIT(module_state->reader_type); + Py_VISIT(module_state->writer_type); return 0; } static void -_csv_free(void *m) +_csv_free(void *module) { - _csv_clear((PyObject *)m); + _csv_clear((PyObject *)module); } -static struct PyModuleDef _csvmodule; - -#define _csvstate_global ((_csvstate *)PyModule_GetState(PyState_FindModule(&_csvmodule))) - typedef enum { START_RECORD, START_FIELD, ESCAPED_CHAR, IN_FIELD, IN_QUOTED_FIELD, ESCAPE_IN_QUOTED_FIELD, QUOTE_IN_QUOTED_FIELD, @@ -92,8 +101,6 @@ typedef struct { } DialectObj; -static PyTypeObject Dialect_Type; - typedef struct { PyObject_HEAD @@ -110,10 +117,6 @@ typedef struct { unsigned long line_num; /* Source-file line number */ } ReaderObj; -static PyTypeObject Reader_Type; - -#define ReaderObject_Check(v) Py_IS_TYPE(v, &Reader_Type) - typedef struct { PyObject_HEAD @@ -125,34 +128,28 @@ typedef struct { Py_ssize_t rec_size; /* size of allocated record */ Py_ssize_t rec_len; /* length of record */ int num_fields; /* number of fields in record */ -} WriterObj; -static PyTypeObject Writer_Type; + PyObject *error_obj; /* cached error object */ +} WriterObj; /* * DIALECT class */ static PyObject * -get_dialect_from_registry(PyObject * name_obj) +get_dialect_from_registry(PyObject *name_obj, _csvstate *module_state) { PyObject *dialect_obj; - dialect_obj = PyDict_GetItemWithError(_csvstate_global->dialects, name_obj); + dialect_obj = PyDict_GetItemWithError(module_state->dialects, name_obj); if (dialect_obj == NULL) { if (!PyErr_Occurred()) - PyErr_Format(_csvstate_global->error_obj, "unknown dialect"); + PyErr_Format(module_state->error_obj, "unknown dialect"); } else Py_INCREF(dialect_obj); - return dialect_obj; -} -static PyObject * -get_string(PyObject *str) -{ - Py_XINCREF(str); - return str; + return dialect_obj; } static PyObject * @@ -168,7 +165,8 @@ get_nullchar_as_None(Py_UCS4 c) static PyObject * Dialect_get_lineterminator(DialectObj *self, void *Py_UNUSED(ignored)) { - return get_string(self->lineterminator); + Py_XINCREF(self->lineterminator); + return self->lineterminator; } static PyObject * @@ -353,8 +351,11 @@ static PyGetSetDef Dialect_getsetlist[] = { static void Dialect_dealloc(DialectObj *self) { - Py_XDECREF(self->lineterminator); - Py_TYPE(self)->tp_free((PyObject *)self); + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); + tp->tp_clear((PyObject *)self); + PyObject_GC_Del(self); + Py_DECREF(tp); } static char *dialect_kws[] = { @@ -370,6 +371,22 @@ static char *dialect_kws[] = { NULL }; +static _csvstate * +_csv_state_from_type(PyTypeObject *type, const char *name) +{ + PyObject *module = _PyType_GetModuleByDef(type, &_csvmodule); + if (module == NULL) { + return NULL; + } + _csvstate *module_state = PyModule_GetState(module); + if (module_state == NULL) { + PyErr_Format(PyExc_SystemError, + "%s: No _csv module state found", name); + return NULL; + } + return module_state; +} + static PyObject * dialect_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { @@ -398,16 +415,21 @@ dialect_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) &strict)) return NULL; + _csvstate *module_state = _csv_state_from_type(type, "dialect_new"); + if (module_state == NULL) { + return NULL; + } + if (dialect != NULL) { if (PyUnicode_Check(dialect)) { - dialect = get_dialect_from_registry(dialect); + dialect = get_dialect_from_registry(dialect, module_state); if (dialect == NULL) return NULL; } else Py_INCREF(dialect); /* Can we reuse this instance? */ - if (PyObject_TypeCheck(dialect, &Dialect_Type) && + if (PyObject_TypeCheck(dialect, module_state->dialect_type) && delimiter == NULL && doublequote == NULL && escapechar == NULL && @@ -421,7 +443,7 @@ dialect_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) self = (DialectObj *)type->tp_alloc(type, 0); if (self == NULL) { - Py_XDECREF(dialect); + Py_CLEAR(dialect); return NULL; } self->lineterminator = NULL; @@ -489,76 +511,86 @@ dialect_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) ret = (PyObject *)self; Py_INCREF(self); err: - Py_XDECREF(self); - Py_XDECREF(dialect); - Py_XDECREF(delimiter); - Py_XDECREF(doublequote); - Py_XDECREF(escapechar); - Py_XDECREF(lineterminator); - Py_XDECREF(quotechar); - Py_XDECREF(quoting); - Py_XDECREF(skipinitialspace); - Py_XDECREF(strict); + Py_CLEAR(self); + Py_CLEAR(dialect); + Py_CLEAR(delimiter); + Py_CLEAR(doublequote); + Py_CLEAR(escapechar); + Py_CLEAR(lineterminator); + Py_CLEAR(quotechar); + Py_CLEAR(quoting); + Py_CLEAR(skipinitialspace); + Py_CLEAR(strict); return ret; } +/* Since dialect is now a heap type, it inherits pickling method for + * protocol 0 and 1 from object, therefore it needs to be overridden */ + +PyDoc_STRVAR(dialect_reduce_doc, "raises an exception to avoid pickling"); + +static PyObject * +Dialect_reduce(PyObject *self, PyObject *args) { + PyErr_Format(PyExc_TypeError, + "cannot pickle '%.100s' instances", _PyType_Name(Py_TYPE(self))); + return NULL; +} + +static struct PyMethodDef dialect_methods[] = { + {"__reduce__", Dialect_reduce, METH_VARARGS, dialect_reduce_doc}, + {"__reduce_ex__", Dialect_reduce, METH_VARARGS, dialect_reduce_doc}, + {NULL, NULL} +}; PyDoc_STRVAR(Dialect_Type_doc, "CSV dialect\n" "\n" "The Dialect type records CSV parsing and generation options.\n"); -static PyTypeObject Dialect_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_csv.Dialect", /* tp_name */ - sizeof(DialectObj), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)Dialect_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - (getattrfunc)0, /* tp_getattr */ - (setattrfunc)0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)0, /* tp_hash */ - (ternaryfunc)0, /* tp_call */ - (reprfunc)0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - Dialect_Type_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - Dialect_memberlist, /* tp_members */ - Dialect_getsetlist, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - dialect_new, /* tp_new */ - 0, /* tp_free */ +static int +Dialect_clear(DialectObj *self) +{ + Py_CLEAR(self->lineterminator); + return 0; +} + +static int +Dialect_traverse(DialectObj *self, visitproc visit, void *arg) +{ + Py_VISIT(self->lineterminator); + Py_VISIT(Py_TYPE(self)); + return 0; +} + +static PyType_Slot Dialect_Type_slots[] = { + {Py_tp_doc, (char*)Dialect_Type_doc}, + {Py_tp_members, Dialect_memberlist}, + {Py_tp_getset, Dialect_getsetlist}, + {Py_tp_new, dialect_new}, + {Py_tp_methods, dialect_methods}, + {Py_tp_dealloc, Dialect_dealloc}, + {Py_tp_clear, Dialect_clear}, + {Py_tp_traverse, Dialect_traverse}, + {0, NULL} +}; + +PyType_Spec Dialect_Type_spec = { + .name = "_csv.Dialect", + .basicsize = sizeof(DialectObj), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = Dialect_Type_slots, }; + /* * Return an instance of the dialect type, given a Python instance or kwarg * description of the dialect */ static PyObject * -_call_dialect(PyObject *dialect_inst, PyObject *kwargs) +_call_dialect(_csvstate *module_state, PyObject *dialect_inst, PyObject *kwargs) { - PyObject *type = (PyObject *)&Dialect_Type; + PyObject *type = (PyObject *)module_state->dialect_type; if (dialect_inst) { return PyObject_VectorcallDict(type, &dialect_inst, 1, kwargs); } @@ -616,11 +648,12 @@ parse_grow_buff(ReaderObj *self) } static int -parse_add_char(ReaderObj *self, Py_UCS4 c) +parse_add_char(ReaderObj *self, _csvstate *module_state, Py_UCS4 c) { - if (self->field_len >= _csvstate_global->field_limit) { - PyErr_Format(_csvstate_global->error_obj, "field larger than field limit (%ld)", - _csvstate_global->field_limit); + if (self->field_len >= module_state->field_limit) { + PyErr_Format(module_state->error_obj, + "field larger than field limit (%ld)", + module_state->field_limit); return -1; } if (self->field_len == self->field_size && !parse_grow_buff(self)) @@ -630,7 +663,7 @@ parse_add_char(ReaderObj *self, Py_UCS4 c) } static int -parse_process_char(ReaderObj *self, Py_UCS4 c) +parse_process_char(ReaderObj *self, _csvstate *module_state, Py_UCS4 c) { DialectObj *dialect = self->dialect; @@ -676,7 +709,7 @@ parse_process_char(ReaderObj *self, Py_UCS4 c) /* begin new unquoted field */ if (dialect->quoting == QUOTE_NONNUMERIC) self->numeric_field = 1; - if (parse_add_char(self, c) < 0) + if (parse_add_char(self, module_state, c) < 0) return -1; self->state = IN_FIELD; } @@ -684,14 +717,14 @@ parse_process_char(ReaderObj *self, Py_UCS4 c) case ESCAPED_CHAR: if (c == '\n' || c=='\r') { - if (parse_add_char(self, c) < 0) + if (parse_add_char(self, module_state, c) < 0) return -1; self->state = AFTER_ESCAPED_CRNL; break; } if (c == '\0') c = '\n'; - if (parse_add_char(self, c) < 0) + if (parse_add_char(self, module_state, c) < 0) return -1; self->state = IN_FIELD; break; @@ -721,7 +754,7 @@ parse_process_char(ReaderObj *self, Py_UCS4 c) } else { /* normal character - save in field */ - if (parse_add_char(self, c) < 0) + if (parse_add_char(self, module_state, c) < 0) return -1; } break; @@ -747,7 +780,7 @@ parse_process_char(ReaderObj *self, Py_UCS4 c) } else { /* normal character - save in field */ - if (parse_add_char(self, c) < 0) + if (parse_add_char(self, module_state, c) < 0) return -1; } break; @@ -755,7 +788,7 @@ parse_process_char(ReaderObj *self, Py_UCS4 c) case ESCAPE_IN_QUOTED_FIELD: if (c == '\0') c = '\n'; - if (parse_add_char(self, c) < 0) + if (parse_add_char(self, module_state, c) < 0) return -1; self->state = IN_QUOTED_FIELD; break; @@ -765,7 +798,7 @@ parse_process_char(ReaderObj *self, Py_UCS4 c) if (dialect->quoting != QUOTE_NONE && c == dialect->quotechar) { /* save "" as " */ - if (parse_add_char(self, c) < 0) + if (parse_add_char(self, module_state, c) < 0) return -1; self->state = IN_QUOTED_FIELD; } @@ -782,13 +815,13 @@ parse_process_char(ReaderObj *self, Py_UCS4 c) self->state = (c == '\0' ? START_RECORD : EAT_CRNL); } else if (!dialect->strict) { - if (parse_add_char(self, c) < 0) + if (parse_add_char(self, module_state, c) < 0) return -1; self->state = IN_FIELD; } else { /* illegal */ - PyErr_Format(_csvstate_global->error_obj, "'%c' expected after '%c'", + PyErr_Format(module_state->error_obj, "'%c' expected after '%c'", dialect->delimiter, dialect->quotechar); return -1; @@ -801,7 +834,8 @@ parse_process_char(ReaderObj *self, Py_UCS4 c) else if (c == '\0') self->state = START_RECORD; else { - PyErr_Format(_csvstate_global->error_obj, "new-line character seen in unquoted field - do you need to open the file in universal-newline mode?"); + PyErr_Format(module_state->error_obj, + "new-line character seen in unquoted field - do you need to open the file in universal-newline mode?"); return -1; } break; @@ -832,6 +866,12 @@ Reader_iternext(ReaderObj *self) const void *data; PyObject *lineobj; + _csvstate *module_state = _csv_state_from_type(Py_TYPE(self), + "Reader.__next__"); + if (module_state == NULL) { + return NULL; + } + if (parse_reset(self) < 0) return NULL; do { @@ -841,7 +881,7 @@ Reader_iternext(ReaderObj *self) if (!PyErr_Occurred() && (self->field_len != 0 || self->state == IN_QUOTED_FIELD)) { if (self->dialect->strict) - PyErr_SetString(_csvstate_global->error_obj, + PyErr_SetString(module_state->error_obj, "unexpected end of data"); else if (parse_save_field(self) >= 0) break; @@ -849,10 +889,10 @@ Reader_iternext(ReaderObj *self) return NULL; } if (!PyUnicode_Check(lineobj)) { - PyErr_Format(_csvstate_global->error_obj, + PyErr_Format(module_state->error_obj, "iterator should return strings, " "not %.200s " - "(did you open the file in text mode?)", + "(the file should be opened in text mode)", Py_TYPE(lineobj)->tp_name ); Py_DECREF(lineobj); @@ -871,18 +911,18 @@ Reader_iternext(ReaderObj *self) c = PyUnicode_READ(kind, data, pos); if (c == '\0') { Py_DECREF(lineobj); - PyErr_Format(_csvstate_global->error_obj, + PyErr_Format(module_state->error_obj, "line contains NUL"); goto err; } - if (parse_process_char(self, c) < 0) { + if (parse_process_char(self, module_state, c) < 0) { Py_DECREF(lineobj); goto err; } pos++; } Py_DECREF(lineobj); - if (parse_process_char(self, 0) < 0) + if (parse_process_char(self, module_state, 0) < 0) goto err; } while (self->state != START_RECORD); @@ -895,13 +935,15 @@ err: static void Reader_dealloc(ReaderObj *self) { + PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(self); - Py_XDECREF(self->dialect); - Py_XDECREF(self->input_iter); - Py_XDECREF(self->fields); - if (self->field != NULL) + tp->tp_clear((PyObject *)self); + if (self->field != NULL) { PyMem_Free(self->field); + self->field = NULL; + } PyObject_GC_Del(self); + Py_DECREF(tp); } static int @@ -910,6 +952,7 @@ Reader_traverse(ReaderObj *self, visitproc visit, void *arg) Py_VISIT(self->dialect); Py_VISIT(self->input_iter); Py_VISIT(self->fields); + Py_VISIT(Py_TYPE(self)); return 0; } @@ -941,47 +984,35 @@ static struct PyMemberDef Reader_memberlist[] = { }; -static PyTypeObject Reader_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_csv.reader", /*tp_name*/ - sizeof(ReaderObj), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)Reader_dealloc, /*tp_dealloc*/ - 0, /*tp_vectorcall_offset*/ - (getattrfunc)0, /*tp_getattr*/ - (setattrfunc)0, /*tp_setattr*/ - 0, /*tp_as_async*/ - (reprfunc)0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - (hashfunc)0, /*tp_hash*/ - (ternaryfunc)0, /*tp_call*/ - (reprfunc)0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_GC, /*tp_flags*/ - Reader_Type_doc, /*tp_doc*/ - (traverseproc)Reader_traverse, /*tp_traverse*/ - (inquiry)Reader_clear, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - PyObject_SelfIter, /*tp_iter*/ - (getiterfunc)Reader_iternext, /*tp_iternext*/ - Reader_methods, /*tp_methods*/ - Reader_memberlist, /*tp_members*/ - 0, /*tp_getset*/ +static PyType_Slot Reader_Type_slots[] = { + {Py_tp_doc, (char*)Reader_Type_doc}, + {Py_tp_traverse, Reader_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, Reader_iternext}, + {Py_tp_methods, Reader_methods}, + {Py_tp_members, Reader_memberlist}, + {Py_tp_clear, Reader_clear}, + {Py_tp_dealloc, Reader_dealloc}, + {0, NULL} +}; +PyType_Spec Reader_Type_spec = { + .name = "_csv.reader", + .basicsize = sizeof(ReaderObj), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = Reader_Type_slots }; + static PyObject * csv_reader(PyObject *module, PyObject *args, PyObject *keyword_args) { PyObject * iterator, * dialect = NULL; - ReaderObj * self = PyObject_GC_New(ReaderObj, &Reader_Type); + _csvstate *module_state = get_csv_state(module); + ReaderObj * self = PyObject_GC_New( + ReaderObj, + module_state->reader_type); if (!self) return NULL; @@ -1007,7 +1038,8 @@ csv_reader(PyObject *module, PyObject *args, PyObject *keyword_args) Py_DECREF(self); return NULL; } - self->dialect = (DialectObj *)_call_dialect(dialect, keyword_args); + self->dialect = (DialectObj *)_call_dialect(module_state, dialect, + keyword_args); if (self->dialect == NULL) { Py_DECREF(self); return NULL; @@ -1088,12 +1120,15 @@ join_append_data(WriterObj *self, unsigned int field_kind, const void *field_dat else want_escape = 1; } + else if (c == dialect->escapechar) { + want_escape = 1; + } if (!want_escape) *quoted = 1; } if (want_escape) { if (!dialect->escapechar) { - PyErr_Format(_csvstate_global->error_obj, + PyErr_Format(self->error_obj, "need to escape, but no escapechar set"); return -1; } @@ -1211,7 +1246,7 @@ csv_writerow(WriterObj *self, PyObject *seq) iter = PyObject_GetIter(seq); if (iter == NULL) { if (PyErr_ExceptionMatches(PyExc_TypeError)) { - PyErr_Format(_csvstate_global->error_obj, + PyErr_Format(self->error_obj, "iterable expected, not %.200s", Py_TYPE(seq)->tp_name); } @@ -1268,7 +1303,7 @@ csv_writerow(WriterObj *self, PyObject *seq) if (self->num_fields > 0 && self->rec_len == 0) { if (dialect->quoting == QUOTE_NONE) { - PyErr_Format(_csvstate_global->error_obj, + PyErr_Format(self->error_obj, "single empty field record must be quoted"); return NULL; } @@ -1337,22 +1372,13 @@ static struct PyMemberDef Writer_memberlist[] = { { NULL } }; -static void -Writer_dealloc(WriterObj *self) -{ - PyObject_GC_UnTrack(self); - Py_XDECREF(self->dialect); - Py_XDECREF(self->write); - if (self->rec != NULL) - PyMem_Free(self->rec); - PyObject_GC_Del(self); -} - static int Writer_traverse(WriterObj *self, visitproc visit, void *arg) { Py_VISIT(self->dialect); Py_VISIT(self->write); + Py_VISIT(self->error_obj); + Py_VISIT(Py_TYPE(self)); return 0; } @@ -1361,9 +1387,23 @@ Writer_clear(WriterObj *self) { Py_CLEAR(self->dialect); Py_CLEAR(self->write); + Py_CLEAR(self->error_obj); return 0; } +static void +Writer_dealloc(WriterObj *self) +{ + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); + tp->tp_clear((PyObject *)self); + if (self->rec != NULL) { + PyMem_Free(self->rec); + } + PyObject_GC_Del(self); + Py_DECREF(tp); +} + PyDoc_STRVAR(Writer_Type_doc, "CSV writer\n" "\n" @@ -1371,46 +1411,31 @@ PyDoc_STRVAR(Writer_Type_doc, "in CSV format from sequence input.\n" ); -static PyTypeObject Writer_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_csv.writer", /*tp_name*/ - sizeof(WriterObj), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)Writer_dealloc, /*tp_dealloc*/ - 0, /*tp_vectorcall_offset*/ - (getattrfunc)0, /*tp_getattr*/ - (setattrfunc)0, /*tp_setattr*/ - 0, /*tp_as_async*/ - (reprfunc)0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - (hashfunc)0, /*tp_hash*/ - (ternaryfunc)0, /*tp_call*/ - (reprfunc)0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_GC, /*tp_flags*/ - Writer_Type_doc, - (traverseproc)Writer_traverse, /*tp_traverse*/ - (inquiry)Writer_clear, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - (getiterfunc)0, /*tp_iter*/ - (getiterfunc)0, /*tp_iternext*/ - Writer_methods, /*tp_methods*/ - Writer_memberlist, /*tp_members*/ - 0, /*tp_getset*/ +static PyType_Slot Writer_Type_slots[] = { + {Py_tp_doc, (char*)Writer_Type_doc}, + {Py_tp_traverse, Writer_traverse}, + {Py_tp_clear, Writer_clear}, + {Py_tp_dealloc, Writer_dealloc}, + {Py_tp_methods, Writer_methods}, + {Py_tp_members, Writer_memberlist}, + {0, NULL} }; +PyType_Spec Writer_Type_spec = { + .name = "_csv.writer", + .basicsize = sizeof(WriterObj), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = Writer_Type_slots, +}; + + static PyObject * csv_writer(PyObject *module, PyObject *args, PyObject *keyword_args) { PyObject * output_file, * dialect = NULL; - WriterObj * self = PyObject_GC_New(WriterObj, &Writer_Type); + _csvstate *module_state = get_csv_state(module); + WriterObj * self = PyObject_GC_New(WriterObj, module_state->writer_type); _Py_IDENTIFIER(write); if (!self) @@ -1424,6 +1449,8 @@ csv_writer(PyObject *module, PyObject *args, PyObject *keyword_args) self->rec_len = 0; self->num_fields = 0; + self->error_obj = Py_NewRef(module_state->error_obj); + if (!PyArg_UnpackTuple(args, "", 1, 2, &output_file, &dialect)) { Py_DECREF(self); return NULL; @@ -1438,7 +1465,8 @@ csv_writer(PyObject *module, PyObject *args, PyObject *keyword_args) Py_DECREF(self); return NULL; } - self->dialect = (DialectObj *)_call_dialect(dialect, keyword_args); + self->dialect = (DialectObj *)_call_dialect(module_state, dialect, + keyword_args); if (self->dialect == NULL) { Py_DECREF(self); return NULL; @@ -1453,13 +1481,14 @@ csv_writer(PyObject *module, PyObject *args, PyObject *keyword_args) static PyObject * csv_list_dialects(PyObject *module, PyObject *args) { - return PyDict_Keys(_csvstate_global->dialects); + return PyDict_Keys(get_csv_state(module)->dialects); } static PyObject * csv_register_dialect(PyObject *module, PyObject *args, PyObject *kwargs) { PyObject *name_obj, *dialect_obj = NULL; + _csvstate *module_state = get_csv_state(module); PyObject *dialect; if (!PyArg_UnpackTuple(args, "", 1, 2, &name_obj, &dialect_obj)) @@ -1471,10 +1500,10 @@ csv_register_dialect(PyObject *module, PyObject *args, PyObject *kwargs) } if (PyUnicode_READY(name_obj) == -1) return NULL; - dialect = _call_dialect(dialect_obj, kwargs); + dialect = _call_dialect(module_state, dialect_obj, kwargs); if (dialect == NULL) return NULL; - if (PyDict_SetItem(_csvstate_global->dialects, name_obj, dialect) < 0) { + if (PyDict_SetItem(module_state->dialects, name_obj, dialect) < 0) { Py_DECREF(dialect); return NULL; } @@ -1485,9 +1514,10 @@ csv_register_dialect(PyObject *module, PyObject *args, PyObject *kwargs) static PyObject * csv_unregister_dialect(PyObject *module, PyObject *name_obj) { - if (PyDict_DelItem(_csvstate_global->dialects, name_obj) < 0) { + _csvstate *module_state = get_csv_state(module); + if (PyDict_DelItem(module_state->dialects, name_obj) < 0) { if (PyErr_ExceptionMatches(PyExc_KeyError)) { - PyErr_Format(_csvstate_global->error_obj, "unknown dialect"); + PyErr_Format(module_state->error_obj, "unknown dialect"); } return NULL; } @@ -1497,14 +1527,15 @@ csv_unregister_dialect(PyObject *module, PyObject *name_obj) static PyObject * csv_get_dialect(PyObject *module, PyObject *name_obj) { - return get_dialect_from_registry(name_obj); + return get_dialect_from_registry(name_obj, get_csv_state(module)); } static PyObject * csv_field_size_limit(PyObject *module, PyObject *args) { PyObject *new_limit = NULL; - long old_limit = _csvstate_global->field_limit; + _csvstate *module_state = get_csv_state(module); + long old_limit = module_state->field_limit; if (!PyArg_UnpackTuple(args, "field_size_limit", 0, 1, &new_limit)) return NULL; @@ -1514,15 +1545,25 @@ csv_field_size_limit(PyObject *module, PyObject *args) "limit must be an integer"); return NULL; } - _csvstate_global->field_limit = PyLong_AsLong(new_limit); - if (_csvstate_global->field_limit == -1 && PyErr_Occurred()) { - _csvstate_global->field_limit = old_limit; + module_state->field_limit = PyLong_AsLong(new_limit); + if (module_state->field_limit == -1 && PyErr_Occurred()) { + module_state->field_limit = old_limit; return NULL; } } return PyLong_FromLong(old_limit); } +static PyType_Slot error_slots[] = { + {0, NULL}, +}; + +PyType_Spec error_spec = { + .name = "_csv.Error", + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .slots = error_slots, +}; + /* * MODULE */ @@ -1655,68 +1696,89 @@ static struct PyMethodDef csv_methods[] = { { NULL, NULL } }; -static struct PyModuleDef _csvmodule = { - PyModuleDef_HEAD_INIT, - "_csv", - csv_module_doc, - sizeof(_csvstate), - csv_methods, - NULL, - _csv_traverse, - _csv_clear, - _csv_free -}; - -PyMODINIT_FUNC -PyInit__csv(void) -{ - PyObject *module; +static int +csv_exec(PyObject *module) { const StyleDesc *style; + PyObject *temp; + _csvstate *module_state = get_csv_state(module); - if (PyType_Ready(&Reader_Type) < 0) - return NULL; + temp = PyType_FromModuleAndSpec(module, &Dialect_Type_spec, NULL); + module_state->dialect_type = (PyTypeObject *)temp; + if (PyModule_AddObjectRef(module, "Dialect", temp) < 0) { + return -1; + } - if (PyType_Ready(&Writer_Type) < 0) - return NULL; + temp = PyType_FromModuleAndSpec(module, &Reader_Type_spec, NULL); + module_state->reader_type = (PyTypeObject *)temp; + if (PyModule_AddObjectRef(module, "Reader", temp) < 0) { + return -1; + } - /* Create the module and add the functions */ - module = PyModule_Create(&_csvmodule); - if (module == NULL) - return NULL; + temp = PyType_FromModuleAndSpec(module, &Writer_Type_spec, NULL); + module_state->writer_type = (PyTypeObject *)temp; + if (PyModule_AddObjectRef(module, "Writer", temp) < 0) { + return -1; + } /* Add version to the module. */ if (PyModule_AddStringConstant(module, "__version__", - MODULE_VERSION) == -1) - return NULL; + MODULE_VERSION) == -1) { + return -1; + } /* Set the field limit */ - get_csv_state(module)->field_limit = 128 * 1024; - /* Do I still need to add this var to the Module Dict? */ + module_state->field_limit = 128 * 1024; /* Add _dialects dictionary */ - get_csv_state(module)->dialects = PyDict_New(); - if (get_csv_state(module)->dialects == NULL) - return NULL; - Py_INCREF(get_csv_state(module)->dialects); - if (PyModule_AddObject(module, "_dialects", get_csv_state(module)->dialects)) - return NULL; + module_state->dialects = PyDict_New(); + if (PyModule_AddObjectRef(module, "_dialects", module_state->dialects) < 0) { + return -1; + } /* Add quote styles into dictionary */ for (style = quote_styles; style->name; style++) { if (PyModule_AddIntConstant(module, style->name, style->style) == -1) - return NULL; + return -1; } - if (PyModule_AddType(module, &Dialect_Type)) { - return NULL; + /* Add the CSV exception object to the module. */ + PyObject *bases = PyTuple_Pack(1, PyExc_Exception); + if (bases == NULL) { + return -1; + } + module_state->error_obj = PyType_FromModuleAndSpec(module, &error_spec, + bases); + Py_DECREF(bases); + if (module_state->error_obj == NULL) { + return -1; + } + if (PyModule_AddType(module, (PyTypeObject *)module_state->error_obj) != 0) { + return -1; } - /* Add the CSV exception object to the module. */ - get_csv_state(module)->error_obj = PyErr_NewException("_csv.Error", NULL, NULL); - if (get_csv_state(module)->error_obj == NULL) - return NULL; - Py_INCREF(get_csv_state(module)->error_obj); - PyModule_AddObject(module, "Error", get_csv_state(module)->error_obj); - return module; + return 0; +} + +static PyModuleDef_Slot csv_slots[] = { + {Py_mod_exec, csv_exec}, + {0, NULL} +}; + +static struct PyModuleDef _csvmodule = { + PyModuleDef_HEAD_INIT, + "_csv", + csv_module_doc, + sizeof(_csvstate), + csv_methods, + csv_slots, + _csv_traverse, + _csv_clear, + _csv_free +}; + +PyMODINIT_FUNC +PyInit__csv(void) +{ + return PyModuleDef_Init(&_csvmodule); } diff --git a/contrib/tools/python3/src/Modules/_ctypes/_ctypes.c b/contrib/tools/python3/src/Modules/_ctypes/_ctypes.c index 0f7b8003f2..198bdd444b 100644 --- a/contrib/tools/python3/src/Modules/_ctypes/_ctypes.c +++ b/contrib/tools/python3/src/Modules/_ctypes/_ctypes.c @@ -117,6 +117,8 @@ bytes(cdata) #endif #include "ctypes.h" +#include "pycore_long.h" // _PyLong_GetZero() + PyObject *PyExc_ArgError = NULL; /* This dict maps ctypes types to POINTER types */ @@ -124,9 +126,13 @@ PyObject *_ctypes_ptrtype_cache = NULL; static PyTypeObject Simple_Type; -/* a callable object used for unpickling */ +/* a callable object used for unpickling: + strong reference to _ctypes._unpickle() function */ static PyObject *_unpickle; +#ifdef MS_WIN32 +PyObject *ComError; // Borrowed reference to: &PyComError_Type +#endif /****************************************************************/ @@ -493,9 +499,10 @@ StructUnionType_new(PyTypeObject *type, PyObject *args, PyObject *kwds, int isSt return NULL; /* keep this for bw compatibility */ - if (_PyDict_GetItemIdWithError(result->tp_dict, &PyId__abstract_)) + int r = _PyDict_ContainsId(result->tp_dict, &PyId__abstract_); + if (r > 0) return (PyObject *)result; - if (PyErr_Occurred()) { + if (r < 0) { Py_DECREF(result); return NULL; } @@ -1352,7 +1359,6 @@ static PyGetSetDef CharArray_getsets[] = { { NULL, NULL } }; -#ifdef CTYPES_UNICODE static PyObject * WCharArray_get_value(CDataObject *self, void *Py_UNUSED(ignored)) { @@ -1367,8 +1373,6 @@ WCharArray_get_value(CDataObject *self, void *Py_UNUSED(ignored)) static int WCharArray_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored)) { - Py_ssize_t result = 0; - if (value == NULL) { PyErr_SetString(PyExc_TypeError, "can't delete attribute"); @@ -1379,29 +1383,24 @@ WCharArray_set_value(CDataObject *self, PyObject *value, void *Py_UNUSED(ignored "unicode string expected instead of %s instance", Py_TYPE(value)->tp_name); return -1; - } else - Py_INCREF(value); + } + Py_ssize_t size = self->b_size / sizeof(wchar_t); Py_ssize_t len = PyUnicode_AsWideChar(value, NULL, 0); if (len < 0) { return -1; } // PyUnicode_AsWideChar() returns number of wchars including trailing null byte, // when it is called with NULL. - if (((size_t)len-1) > self->b_size/sizeof(wchar_t)) { + assert(len > 0); + if (len - 1 > size) { PyErr_SetString(PyExc_ValueError, "string too long"); - result = -1; - goto done; - } - result = PyUnicode_AsWideChar(value, - (wchar_t *)self->b_ptr, - self->b_size/sizeof(wchar_t)); - if (result >= 0 && (size_t)result < self->b_size/sizeof(wchar_t)) - ((wchar_t *)self->b_ptr)[result] = (wchar_t)0; - done: - Py_DECREF(value); - - return result >= 0 ? 0 : -1; + return -1; + } + if (PyUnicode_AsWideChar(value, (wchar_t *)self->b_ptr, size) < 0) { + return -1; + } + return 0; } static PyGetSetDef WCharArray_getsets[] = { @@ -1409,7 +1408,6 @@ static PyGetSetDef WCharArray_getsets[] = { "string value"}, { NULL, NULL } }; -#endif /* The next three functions copied from Python's typeobject.c. @@ -1616,11 +1614,10 @@ PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (itemdict->getfunc == _ctypes_get_fielddesc("c")->getfunc) { if (-1 == add_getset(result, CharArray_getsets)) goto error; -#ifdef CTYPES_UNICODE - } else if (itemdict->getfunc == _ctypes_get_fielddesc("u")->getfunc) { + } + else if (itemdict->getfunc == _ctypes_get_fielddesc("u")->getfunc) { if (-1 == add_getset(result, WCharArray_getsets)) goto error; -#endif } return (PyObject *)result; @@ -3485,10 +3482,12 @@ _validate_paramflags(PyTypeObject *type, PyObject *paramflags) for (i = 0; i < len; ++i) { PyObject *item = PyTuple_GET_ITEM(paramflags, i); int flag; - char *name; + PyObject *name = Py_None; PyObject *defval; PyObject *typ; - if (!PyArg_ParseTuple(item, "i|ZO", &flag, &name, &defval)) { + if (!PyArg_ParseTuple(item, "i|OO", &flag, &name, &defval) || + !(name == Py_None || PyUnicode_Check(name))) + { PyErr_SetString(PyExc_TypeError, "paramflags must be a sequence of (int [,string [,value]]) tuples"); return 0; @@ -3934,8 +3933,9 @@ _build_callargs(PyCFuncPtrObject *self, PyObject *argtypes, case PARAMFLAG_FIN | PARAMFLAG_FLCID: /* ['in', 'lcid'] parameter. Always taken from defval, if given, else the integer 0. */ - if (defval == NULL) - defval = _PyLong_Zero; + if (defval == NULL) { + defval = _PyLong_GetZero(); + } Py_INCREF(defval); PyTuple_SET_ITEM(callargs, i, defval); break; @@ -4309,7 +4309,7 @@ static PyNumberMethods PyCFuncPtr_as_number = { PyTypeObject PyCFuncPtr_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "_ctypes.PyCFuncPtr", + "_ctypes.CFuncPtr", sizeof(PyCFuncPtrObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)PyCFuncPtr_dealloc, /* tp_dealloc */ @@ -4403,15 +4403,13 @@ _init_pos_args(PyObject *self, PyTypeObject *type, } val = PyTuple_GET_ITEM(args, i + index); if (kwds) { - if (PyDict_GetItemWithError(kwds, name)) { - PyErr_Format(PyExc_TypeError, - "duplicate values for field %R", - name); - Py_DECREF(pair); - Py_DECREF(name); - return -1; - } - else if (PyErr_Occurred()) { + res = PyDict_Contains(kwds, name); + if (res != 0) { + if (res > 0) { + PyErr_Format(PyExc_TypeError, + "duplicate values for field %R", + name); + } Py_DECREF(pair); Py_DECREF(name); return -1; @@ -4654,7 +4652,6 @@ Array_subscript(PyObject *myself, PyObject *item) PyMem_Free(dest); return np; } -#ifdef CTYPES_UNICODE if (itemdict->getfunc == _ctypes_get_fielddesc("u")->getfunc) { wchar_t *ptr = (wchar_t *)self->b_ptr; wchar_t *dest; @@ -4681,7 +4678,6 @@ Array_subscript(PyObject *myself, PyObject *item) PyMem_Free(dest); return np; } -#endif np = PyList_New(slicelen); if (np == NULL) @@ -5350,7 +5346,6 @@ Pointer_subscript(PyObject *myself, PyObject *item) PyMem_Free(dest); return np; } -#ifdef CTYPES_UNICODE if (itemdict->getfunc == _ctypes_get_fielddesc("u")->getfunc) { wchar_t *ptr = *(wchar_t **)self->b_ptr; wchar_t *dest; @@ -5371,7 +5366,6 @@ Pointer_subscript(PyObject *myself, PyObject *item) PyMem_Free(dest); return np; } -#endif np = PyList_New(len); if (np == NULL) @@ -5559,20 +5553,7 @@ static PyTypeObject PyComError_Type = { 0, /* tp_alloc */ 0, /* tp_new */ }; - - -static int -create_comerror(void) -{ - PyComError_Type.tp_base = (PyTypeObject*)PyExc_Exception; - if (PyType_Ready(&PyComError_Type) < 0) - return -1; - Py_INCREF(&PyComError_Type); - ComError = (PyObject*)&PyComError_Type; - return 0; -} - -#endif +#endif // MS_WIN32 static PyObject * string_at(const char *ptr, int size) @@ -5666,7 +5647,7 @@ cast(void *ptr, PyObject *src, PyObject *ctype) return NULL; } -#ifdef CTYPES_UNICODE + static PyObject * wstring_at(const wchar_t *ptr, int size) { @@ -5678,133 +5659,74 @@ wstring_at(const wchar_t *ptr, int size) ssize = wcslen(ptr); return PyUnicode_FromWideChar(ptr, ssize); } -#endif static struct PyModuleDef _ctypesmodule = { PyModuleDef_HEAD_INIT, - "_ctypes", - module_docs, - -1, - _ctypes_module_methods, - NULL, - NULL, - NULL, - NULL + .m_name = "_ctypes", + .m_doc = module_docs, + .m_size = -1, + .m_methods = _ctypes_module_methods, }; -PyMODINIT_FUNC -PyInit__ctypes(void) -{ - PyObject *m; - -/* Note: - ob_type is the metatype (the 'type'), defaults to PyType_Type, - tp_base is the base type, defaults to 'object' aka PyBaseObject_Type. -*/ - m = PyModule_Create(&_ctypesmodule); - if (!m) - return NULL; - - _ctypes_ptrtype_cache = PyDict_New(); - if (_ctypes_ptrtype_cache == NULL) - return NULL; - - PyModule_AddObject(m, "_pointer_type_cache", (PyObject *)_ctypes_ptrtype_cache); - - _unpickle = PyObject_GetAttrString(m, "_unpickle"); - if (_unpickle == NULL) - return NULL; - - if (PyType_Ready(&PyCArg_Type) < 0) - return NULL; - - if (PyType_Ready(&PyCThunk_Type) < 0) - return NULL; +static int +_ctypes_add_types(PyObject *mod) +{ +#define TYPE_READY(TYPE) \ + if (PyType_Ready(TYPE) < 0) { \ + return -1; \ + } + +#define TYPE_READY_BASE(TYPE_EXPR, TP_BASE) \ + do { \ + PyTypeObject *type = (TYPE_EXPR); \ + type->tp_base = (TP_BASE); \ + TYPE_READY(type); \ + } while (0) + +#define MOD_ADD_TYPE(TYPE_EXPR, TP_TYPE, TP_BASE) \ + do { \ + PyTypeObject *type = (TYPE_EXPR); \ + Py_SET_TYPE(type, TP_TYPE); \ + type->tp_base = TP_BASE; \ + if (PyModule_AddType(mod, type) < 0) { \ + return -1; \ + } \ + } while (0) + + /* Note: + ob_type is the metatype (the 'type'), defaults to PyType_Type, + tp_base is the base type, defaults to 'object' aka PyBaseObject_Type. + */ + TYPE_READY(&PyCArg_Type); + TYPE_READY(&PyCThunk_Type); + TYPE_READY(&PyCData_Type); /* StgDict is derived from PyDict_Type */ - PyCStgDict_Type.tp_base = &PyDict_Type; - if (PyType_Ready(&PyCStgDict_Type) < 0) - return NULL; + TYPE_READY_BASE(&PyCStgDict_Type, &PyDict_Type); /************************************************* * * Metaclasses */ - - PyCStructType_Type.tp_base = &PyType_Type; - if (PyType_Ready(&PyCStructType_Type) < 0) - return NULL; - - UnionType_Type.tp_base = &PyType_Type; - if (PyType_Ready(&UnionType_Type) < 0) - return NULL; - - PyCPointerType_Type.tp_base = &PyType_Type; - if (PyType_Ready(&PyCPointerType_Type) < 0) - return NULL; - - PyCArrayType_Type.tp_base = &PyType_Type; - if (PyType_Ready(&PyCArrayType_Type) < 0) - return NULL; - - PyCSimpleType_Type.tp_base = &PyType_Type; - if (PyType_Ready(&PyCSimpleType_Type) < 0) - return NULL; - - PyCFuncPtrType_Type.tp_base = &PyType_Type; - if (PyType_Ready(&PyCFuncPtrType_Type) < 0) - return NULL; + TYPE_READY_BASE(&PyCStructType_Type, &PyType_Type); + TYPE_READY_BASE(&UnionType_Type, &PyType_Type); + TYPE_READY_BASE(&PyCPointerType_Type, &PyType_Type); + TYPE_READY_BASE(&PyCArrayType_Type, &PyType_Type); + TYPE_READY_BASE(&PyCSimpleType_Type, &PyType_Type); + TYPE_READY_BASE(&PyCFuncPtrType_Type, &PyType_Type); /************************************************* * * Classes using a custom metaclass */ - if (PyType_Ready(&PyCData_Type) < 0) - return NULL; - - Py_SET_TYPE(&Struct_Type, &PyCStructType_Type); - Struct_Type.tp_base = &PyCData_Type; - if (PyType_Ready(&Struct_Type) < 0) - return NULL; - Py_INCREF(&Struct_Type); - PyModule_AddObject(m, "Structure", (PyObject *)&Struct_Type); - - Py_SET_TYPE(&Union_Type, &UnionType_Type); - Union_Type.tp_base = &PyCData_Type; - if (PyType_Ready(&Union_Type) < 0) - return NULL; - Py_INCREF(&Union_Type); - PyModule_AddObject(m, "Union", (PyObject *)&Union_Type); - - Py_SET_TYPE(&PyCPointer_Type, &PyCPointerType_Type); - PyCPointer_Type.tp_base = &PyCData_Type; - if (PyType_Ready(&PyCPointer_Type) < 0) - return NULL; - Py_INCREF(&PyCPointer_Type); - PyModule_AddObject(m, "_Pointer", (PyObject *)&PyCPointer_Type); - - Py_SET_TYPE(&PyCArray_Type, &PyCArrayType_Type); - PyCArray_Type.tp_base = &PyCData_Type; - if (PyType_Ready(&PyCArray_Type) < 0) - return NULL; - Py_INCREF(&PyCArray_Type); - PyModule_AddObject(m, "Array", (PyObject *)&PyCArray_Type); - - Py_SET_TYPE(&Simple_Type, &PyCSimpleType_Type); - Simple_Type.tp_base = &PyCData_Type; - if (PyType_Ready(&Simple_Type) < 0) - return NULL; - Py_INCREF(&Simple_Type); - PyModule_AddObject(m, "_SimpleCData", (PyObject *)&Simple_Type); - - Py_SET_TYPE(&PyCFuncPtr_Type, &PyCFuncPtrType_Type); - PyCFuncPtr_Type.tp_base = &PyCData_Type; - if (PyType_Ready(&PyCFuncPtr_Type) < 0) - return NULL; - Py_INCREF(&PyCFuncPtr_Type); - PyModule_AddObject(m, "CFuncPtr", (PyObject *)&PyCFuncPtr_Type); + MOD_ADD_TYPE(&Struct_Type, &PyCStructType_Type, &PyCData_Type); + MOD_ADD_TYPE(&Union_Type, &UnionType_Type, &PyCData_Type); + MOD_ADD_TYPE(&PyCPointer_Type, &PyCPointerType_Type, &PyCData_Type); + MOD_ADD_TYPE(&PyCArray_Type, &PyCArrayType_Type, &PyCData_Type); + MOD_ADD_TYPE(&Simple_Type, &PyCSimpleType_Type, &PyCData_Type); + MOD_ADD_TYPE(&PyCFuncPtr_Type, &PyCFuncPtrType_Type, &PyCData_Type); /************************************************* * @@ -5812,8 +5734,7 @@ PyInit__ctypes(void) */ /* PyCField_Type is derived from PyBaseObject_Type */ - if (PyType_Ready(&PyCField_Type) < 0) - return NULL; + TYPE_READY(&PyCField_Type); /************************************************* * @@ -5821,56 +5742,118 @@ PyInit__ctypes(void) */ DictRemover_Type.tp_new = PyType_GenericNew; - if (PyType_Ready(&DictRemover_Type) < 0) - return NULL; - - if (PyType_Ready(&StructParam_Type) < 0) { - return NULL; - } + TYPE_READY(&DictRemover_Type); + TYPE_READY(&StructParam_Type); #ifdef MS_WIN32 - if (create_comerror() < 0) - return NULL; - PyModule_AddObject(m, "COMError", ComError); - - PyModule_AddObject(m, "FUNCFLAG_HRESULT", PyLong_FromLong(FUNCFLAG_HRESULT)); - PyModule_AddObject(m, "FUNCFLAG_STDCALL", PyLong_FromLong(FUNCFLAG_STDCALL)); + TYPE_READY_BASE(&PyComError_Type, (PyTypeObject*)PyExc_Exception); #endif - PyModule_AddObject(m, "FUNCFLAG_CDECL", PyLong_FromLong(FUNCFLAG_CDECL)); - PyModule_AddObject(m, "FUNCFLAG_USE_ERRNO", PyLong_FromLong(FUNCFLAG_USE_ERRNO)); - PyModule_AddObject(m, "FUNCFLAG_USE_LASTERROR", PyLong_FromLong(FUNCFLAG_USE_LASTERROR)); - PyModule_AddObject(m, "FUNCFLAG_PYTHONAPI", PyLong_FromLong(FUNCFLAG_PYTHONAPI)); - PyModule_AddStringConstant(m, "__version__", "1.1.0"); - - PyModule_AddObject(m, "_memmove_addr", PyLong_FromVoidPtr(memmove)); - PyModule_AddObject(m, "_memset_addr", PyLong_FromVoidPtr(memset)); - PyModule_AddObject(m, "_string_at_addr", PyLong_FromVoidPtr(string_at)); - PyModule_AddObject(m, "_cast_addr", PyLong_FromVoidPtr(cast)); -#ifdef CTYPES_UNICODE - PyModule_AddObject(m, "_wstring_at_addr", PyLong_FromVoidPtr(wstring_at)); + +#undef TYPE_READY +#undef TYPE_READY_BASE +#undef MOD_ADD_TYPE + return 0; +} + + +static int +_ctypes_add_objects(PyObject *mod) +{ +#define MOD_ADD(name, expr) \ + do { \ + PyObject *obj = (expr); \ + if (obj == NULL) { \ + return -1; \ + } \ + if (PyModule_AddObjectRef(mod, name, obj) < 0) { \ + Py_DECREF(obj); \ + return -1; \ + } \ + Py_DECREF(obj); \ + } while (0) + + MOD_ADD("_pointer_type_cache", Py_NewRef(_ctypes_ptrtype_cache)); + +#ifdef MS_WIN32 + MOD_ADD("COMError", Py_NewRef(ComError)); + MOD_ADD("FUNCFLAG_HRESULT", PyLong_FromLong(FUNCFLAG_HRESULT)); + MOD_ADD("FUNCFLAG_STDCALL", PyLong_FromLong(FUNCFLAG_STDCALL)); #endif + MOD_ADD("FUNCFLAG_CDECL", PyLong_FromLong(FUNCFLAG_CDECL)); + MOD_ADD("FUNCFLAG_USE_ERRNO", PyLong_FromLong(FUNCFLAG_USE_ERRNO)); + MOD_ADD("FUNCFLAG_USE_LASTERROR", PyLong_FromLong(FUNCFLAG_USE_LASTERROR)); + MOD_ADD("FUNCFLAG_PYTHONAPI", PyLong_FromLong(FUNCFLAG_PYTHONAPI)); + MOD_ADD("__version__", PyUnicode_FromString("1.1.0")); + + MOD_ADD("_memmove_addr", PyLong_FromVoidPtr(memmove)); + MOD_ADD("_memset_addr", PyLong_FromVoidPtr(memset)); + MOD_ADD("_string_at_addr", PyLong_FromVoidPtr(string_at)); + MOD_ADD("_cast_addr", PyLong_FromVoidPtr(cast)); + MOD_ADD("_wstring_at_addr", PyLong_FromVoidPtr(wstring_at)); /* If RTLD_LOCAL is not defined (Windows!), set it to zero. */ #if !HAVE_DECL_RTLD_LOCAL -#define RTLD_LOCAL 0 +# define RTLD_LOCAL 0 #endif /* If RTLD_GLOBAL is not defined (cygwin), set it to the same value as - RTLD_LOCAL. -*/ + RTLD_LOCAL. */ #if !HAVE_DECL_RTLD_GLOBAL -#define RTLD_GLOBAL RTLD_LOCAL +# define RTLD_GLOBAL RTLD_LOCAL #endif + MOD_ADD("RTLD_LOCAL", PyLong_FromLong(RTLD_LOCAL)); + MOD_ADD("RTLD_GLOBAL", PyLong_FromLong(RTLD_GLOBAL)); + MOD_ADD("ArgumentError", Py_NewRef(PyExc_ArgError)); + return 0; +#undef MOD_ADD +} - PyModule_AddObject(m, "RTLD_LOCAL", PyLong_FromLong(RTLD_LOCAL)); - PyModule_AddObject(m, "RTLD_GLOBAL", PyLong_FromLong(RTLD_GLOBAL)); + +static int +_ctypes_mod_exec(PyObject *mod) +{ + _unpickle = PyObject_GetAttrString(mod, "_unpickle"); + if (_unpickle == NULL) { + return -1; + } + + _ctypes_ptrtype_cache = PyDict_New(); + if (_ctypes_ptrtype_cache == NULL) { + return -1; + } PyExc_ArgError = PyErr_NewException("ctypes.ArgumentError", NULL, NULL); - if (PyExc_ArgError) { - Py_INCREF(PyExc_ArgError); - PyModule_AddObject(m, "ArgumentError", PyExc_ArgError); + if (!PyExc_ArgError) { + return -1; + } + + if (_ctypes_add_types(mod) < 0) { + return -1; + } +#ifdef MS_WIN32 + ComError = (PyObject*)&PyComError_Type; +#endif + + if (_ctypes_add_objects(mod) < 0) { + return -1; + } + return 0; +} + + +PyMODINIT_FUNC +PyInit__ctypes(void) +{ + PyObject *mod = PyModule_Create(&_ctypesmodule); + if (!mod) { + return NULL; + } + + if (_ctypes_mod_exec(mod) < 0) { + Py_DECREF(mod); + return NULL; } - return m; + return mod; } /* diff --git a/contrib/tools/python3/src/Modules/_ctypes/callbacks.c b/contrib/tools/python3/src/Modules/_ctypes/callbacks.c index 0dc8242817..1afbd617c7 100644 --- a/contrib/tools/python3/src/Modules/_ctypes/callbacks.c +++ b/contrib/tools/python3/src/Modules/_ctypes/callbacks.c @@ -112,8 +112,9 @@ TryAddRef(StgDictObject *dict, CDataObject *obj) IUnknown *punk; _Py_IDENTIFIER(_needs_com_addref_); - if (!_PyDict_GetItemIdWithError((PyObject *)dict, &PyId__needs_com_addref_)) { - if (PyErr_Occurred()) { + int r = _PyDict_ContainsId((PyObject *)dict, &PyId__needs_com_addref_); + if (r <= 0) { + if (r < 0) { PrintError("getting _needs_com_addref_"); } return; diff --git a/contrib/tools/python3/src/Modules/_ctypes/callproc.c b/contrib/tools/python3/src/Modules/_ctypes/callproc.c index 287bec47aa..ce148e0ecd 100644 --- a/contrib/tools/python3/src/Modules/_ctypes/callproc.c +++ b/contrib/tools/python3/src/Modules/_ctypes/callproc.c @@ -255,8 +255,6 @@ set_last_error(PyObject *self, PyObject *args) return set_error_internal(self, args, 1); } -PyObject *ComError; - static WCHAR *FormatError(DWORD code) { WCHAR *lpMsgBuf; @@ -478,7 +476,7 @@ static void PyCArg_dealloc(PyCArgObject *self) { Py_XDECREF(self->obj); - PyObject_Del(self); + PyObject_Free(self); } static int @@ -703,7 +701,6 @@ static int ConvParam(PyObject *obj, Py_ssize_t index, struct argument *pa) return 0; } -#ifdef CTYPES_UNICODE if (PyUnicode_Check(obj)) { pa->ffi_type = &ffi_type_pointer; pa->value.p = PyUnicode_AsWideCharString(obj, NULL); @@ -716,7 +713,6 @@ static int ConvParam(PyObject *obj, Py_ssize_t index, struct argument *pa) } return 0; } -#endif { _Py_IDENTIFIER(_as_parameter_); @@ -1350,7 +1346,6 @@ module. load_flags are as defined for LoadLibraryEx in the\n\ Windows API.\n"; static PyObject *load_library(PyObject *self, PyObject *args) { - const WCHAR *name; PyObject *nameobj; int load_flags = 0; HMODULE hMod; @@ -1359,17 +1354,14 @@ static PyObject *load_library(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "U|i:LoadLibrary", &nameobj, &load_flags)) return NULL; -_Py_COMP_DIAG_PUSH -_Py_COMP_DIAG_IGNORE_DEPR_DECLS - name = _PyUnicode_AsUnicode(nameobj); -_Py_COMP_DIAG_POP - if (!name) - return NULL; - if (PySys_Audit("ctypes.dlopen", "O", nameobj) < 0) { return NULL; } + WCHAR *name = PyUnicode_AsWideCharString(nameobj, NULL); + if (!name) + return NULL; + Py_BEGIN_ALLOW_THREADS /* bpo-36085: Limit DLL search directories to avoid pre-loading * attacks and enable use of the AddDllDirectory function. @@ -1378,6 +1370,7 @@ _Py_COMP_DIAG_POP err = hMod ? 0 : GetLastError(); Py_END_ALLOW_THREADS + PyMem_Free(name); if (err == ERROR_MOD_NOT_FOUND) { PyErr_Format(PyExc_FileNotFoundError, ("Could not find module '%.500S' (or one of its " diff --git a/contrib/tools/python3/src/Modules/_ctypes/cfield.c b/contrib/tools/python3/src/Modules/_ctypes/cfield.c index 2647777666..eed06289f0 100644 --- a/contrib/tools/python3/src/Modules/_ctypes/cfield.c +++ b/contrib/tools/python3/src/Modules/_ctypes/cfield.c @@ -1,5 +1,5 @@ #include "Python.h" -#include "pycore_byteswap.h" // _Py_bswap32() +#include "pycore_bitutils.h" // _Py_bswap32() #include <ffi.h> #ifdef MS_WIN32 @@ -126,13 +126,11 @@ PyCField_FromDesc(PyObject *desc, Py_ssize_t index, getfunc = fd->getfunc; setfunc = fd->setfunc; } -#ifdef CTYPES_UNICODE if (idict->getfunc == _ctypes_get_fielddesc("u")->getfunc) { struct fielddesc *fd = _ctypes_get_fielddesc("U"); getfunc = fd->getfunc; setfunc = fd->setfunc; } -#endif } } @@ -355,14 +353,7 @@ PyTypeObject PyCField_Type = { static int get_long(PyObject *v, long *p) { - long x; - - if (PyFloat_Check(v)) { - PyErr_SetString(PyExc_TypeError, - "int expected instead of float"); - return -1; - } - x = PyLong_AsUnsignedLongMask(v); + long x = PyLong_AsUnsignedLongMask(v); if (x == -1 && PyErr_Occurred()) return -1; *p = x; @@ -374,14 +365,7 @@ get_long(PyObject *v, long *p) static int get_ulong(PyObject *v, unsigned long *p) { - unsigned long x; - - if (PyFloat_Check(v)) { - PyErr_SetString(PyExc_TypeError, - "int expected instead of float"); - return -1; - } - x = PyLong_AsUnsignedLongMask(v); + unsigned long x = PyLong_AsUnsignedLongMask(v); if (x == (unsigned long)-1 && PyErr_Occurred()) return -1; *p = x; @@ -393,13 +377,7 @@ get_ulong(PyObject *v, unsigned long *p) static int get_longlong(PyObject *v, long long *p) { - long long x; - if (PyFloat_Check(v)) { - PyErr_SetString(PyExc_TypeError, - "int expected instead of float"); - return -1; - } - x = PyLong_AsUnsignedLongLongMask(v); + long long x = PyLong_AsUnsignedLongLongMask(v); if (x == -1 && PyErr_Occurred()) return -1; *p = x; @@ -411,13 +389,7 @@ get_longlong(PyObject *v, long long *p) static int get_ulonglong(PyObject *v, unsigned long long *p) { - unsigned long long x; - if (PyFloat_Check(v)) { - PyErr_SetString(PyExc_TypeError, - "int expected instead of float"); - return -1; - } - x = PyLong_AsUnsignedLongLongMask(v); + unsigned long long x = PyLong_AsUnsignedLongLongMask(v); if (x == (unsigned long long)-1 && PyErr_Occurred()) return -1; *p = x; @@ -1164,7 +1136,6 @@ c_get(void *ptr, Py_ssize_t size) return PyBytes_FromStringAndSize((char *)ptr, 1); } -#ifdef CTYPES_UNICODE /* u - a single wchar_t character */ static PyObject * u_set(void *ptr, PyObject *value, Py_ssize_t size) @@ -1250,11 +1221,8 @@ U_set(void *ptr, PyObject *value, Py_ssize_t length) "string too long (%zd, maximum length %zd)", size, length); return NULL; - } else if (size < length-1) - /* copy terminating NUL character if there is space */ - size += 1; - - if (PyUnicode_AsWideChar(value, (wchar_t *)ptr, size) == -1) { + } + if (PyUnicode_AsWideChar(value, (wchar_t *)ptr, length) == -1) { return NULL; } @@ -1262,7 +1230,6 @@ U_set(void *ptr, PyObject *value, Py_ssize_t length) return value; } -#endif static PyObject * s_get(void *ptr, Py_ssize_t size) @@ -1293,7 +1260,9 @@ s_set(void *ptr, PyObject *value, Py_ssize_t length) } data = PyBytes_AS_STRING(value); - size = strlen(data); /* XXX Why not Py_SIZE(value)? */ + // bpo-39593: Use strlen() to truncate the string at the first null character. + size = strlen(data); + if (size < length) { /* This will copy the terminating NUL character * if there is space for it. @@ -1349,7 +1318,6 @@ z_get(void *ptr, Py_ssize_t size) } } -#ifdef CTYPES_UNICODE static PyObject * Z_set(void *ptr, PyObject *value, Py_ssize_t size) { @@ -1402,7 +1370,7 @@ Z_get(void *ptr, Py_ssize_t size) Py_RETURN_NONE; } } -#endif + #ifdef MS_WIN32 static PyObject * @@ -1536,11 +1504,9 @@ static struct fielddesc formattable[] = { #endif { 'P', P_set, P_get, &ffi_type_pointer}, { 'z', z_set, z_get, &ffi_type_pointer}, -#ifdef CTYPES_UNICODE { 'u', u_set, u_get, NULL}, /* ffi_type set later */ { 'U', U_set, U_get, &ffi_type_pointer}, { 'Z', Z_set, Z_get, &ffi_type_pointer}, -#endif #ifdef MS_WIN32 { 'X', BSTR_set, BSTR_get, &ffi_type_pointer}, #endif @@ -1573,14 +1539,12 @@ _ctypes_get_fielddesc(const char *fmt) if (!initialized) { initialized = 1; -#ifdef CTYPES_UNICODE if (sizeof(wchar_t) == sizeof(short)) _ctypes_get_fielddesc("u")->pffi_type = &ffi_type_sshort; else if (sizeof(wchar_t) == sizeof(int)) _ctypes_get_fielddesc("u")->pffi_type = &ffi_type_sint; else if (sizeof(wchar_t) == sizeof(long)) _ctypes_get_fielddesc("u")->pffi_type = &ffi_type_slong; -#endif } for (; table->code; ++table) { diff --git a/contrib/tools/python3/src/Modules/_ctypes/ctypes.h b/contrib/tools/python3/src/Modules/_ctypes/ctypes.h index 0f422113a8..9600ddc741 100644 --- a/contrib/tools/python3/src/Modules/_ctypes/ctypes.h +++ b/contrib/tools/python3/src/Modules/_ctypes/ctypes.h @@ -343,10 +343,6 @@ extern PyObject *PyExc_ArgError; extern char *_ctypes_conversion_encoding; extern char *_ctypes_conversion_errors; -#if defined(HAVE_WCHAR_H) -# define CTYPES_UNICODE -#endif - extern void _ctypes_free_closure(void *); extern void *_ctypes_alloc_closure(void); diff --git a/contrib/tools/python3/src/Modules/_ctypes/stgdict.c b/contrib/tools/python3/src/Modules/_ctypes/stgdict.c index bbef2921e6..3951ce9565 100644 --- a/contrib/tools/python3/src/Modules/_ctypes/stgdict.c +++ b/contrib/tools/python3/src/Modules/_ctypes/stgdict.c @@ -539,9 +539,7 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct case FFI_TYPE_SINT16: case FFI_TYPE_SINT32: if (dict->getfunc != _ctypes_get_fielddesc("c")->getfunc -#ifdef CTYPES_UNICODE && dict->getfunc != _ctypes_get_fielddesc("u")->getfunc -#endif ) break; /* else fall through */ diff --git a/contrib/tools/python3/src/Modules/_datetimemodule.c b/contrib/tools/python3/src/Modules/_datetimemodule.c index 9602375405..e54a01b44c 100644 --- a/contrib/tools/python3/src/Modules/_datetimemodule.c +++ b/contrib/tools/python3/src/Modules/_datetimemodule.c @@ -8,6 +8,8 @@ #define _PY_DATETIME_IMPL #include "Python.h" +#include "pycore_long.h" // _PyLong_GetOne() +#include "pycore_object.h" // _PyObject_Init() #include "datetime.h" #include "structmember.h" // PyMemberDef @@ -114,14 +116,9 @@ class datetime.IsoCalendarDate "PyDateTime_IsoCalendarDate *" "&PyDateTime_IsoCa #define SET_TD_SECONDS(o, v) ((o)->seconds = (v)) #define SET_TD_MICROSECONDS(o, v) ((o)->microseconds = (v)) -/* p is a pointer to a time or a datetime object; HASTZINFO(p) returns - * p->hastzinfo. - */ -#define HASTZINFO(p) (((_PyDateTime_BaseTZInfo *)(p))->hastzinfo) -#define GET_TIME_TZINFO(p) (HASTZINFO(p) ? \ - ((PyDateTime_Time *)(p))->tzinfo : Py_None) -#define GET_DT_TZINFO(p) (HASTZINFO(p) ? \ - ((PyDateTime_DateTime *)(p))->tzinfo : Py_None) +#define HASTZINFO _PyDateTime_HAS_TZINFO +#define GET_TIME_TZINFO PyDateTime_TIME_GET_TZINFO +#define GET_DT_TZINFO PyDateTime_DATE_GET_TZINFO /* M is a char or int claiming to be a valid month. The macro is equivalent * to the two-sided Python test * 1 <= M <= 12 @@ -638,30 +635,24 @@ normalize_datetime(int *year, int *month, int *day, static PyObject * time_alloc(PyTypeObject *type, Py_ssize_t aware) { - PyObject *self; - - self = (PyObject *) - PyObject_MALLOC(aware ? - sizeof(PyDateTime_Time) : - sizeof(_PyDateTime_BaseTime)); - if (self == NULL) - return (PyObject *)PyErr_NoMemory(); - (void)PyObject_INIT(self, type); + size_t size = aware ? sizeof(PyDateTime_Time) : sizeof(_PyDateTime_BaseTime); + PyObject *self = (PyObject *)PyObject_Malloc(size); + if (self == NULL) { + return PyErr_NoMemory(); + } + _PyObject_Init(self, type); return self; } static PyObject * datetime_alloc(PyTypeObject *type, Py_ssize_t aware) { - PyObject *self; - - self = (PyObject *) - PyObject_MALLOC(aware ? - sizeof(PyDateTime_DateTime) : - sizeof(_PyDateTime_BaseDateTime)); - if (self == NULL) - return (PyObject *)PyErr_NoMemory(); - (void)PyObject_INIT(self, type); + size_t size = aware ? sizeof(PyDateTime_DateTime) : sizeof(_PyDateTime_BaseDateTime); + PyObject *self = (PyObject *)PyObject_Malloc(size); + if (self == NULL) { + return PyErr_NoMemory(); + } + _PyObject_Init(self, type); return self; } @@ -2458,7 +2449,7 @@ delta_new(PyTypeObject *type, PyObject *args, PyObject *kw) goto Done if (us) { - y = accum("microseconds", x, us, _PyLong_One, &leftover_us); + y = accum("microseconds", x, us, _PyLong_GetOne(), &leftover_us); CLEANUP; } if (ms) { @@ -2497,7 +2488,7 @@ delta_new(PyTypeObject *type, PyObject *args, PyObject *kw) * is odd. Note that x is odd when it's last bit is 1. The * code below uses bitwise and operation to check the last * bit. */ - temp = PyNumber_And(x, _PyLong_One); /* temp <- x & 1 */ + temp = PyNumber_And(x, _PyLong_GetOne()); /* temp <- x & 1 */ if (temp == NULL) { Py_DECREF(x); goto Done; @@ -6482,53 +6473,48 @@ static PyMethodDef module_methods[] = { {NULL, NULL} }; -/* C API. Clients get at this via PyDateTime_IMPORT, defined in - * datetime.h. +/* Get a new C API by calling this function. + * Clients get at C API via PyDateTime_IMPORT, defined in datetime.h. */ -static PyDateTime_CAPI CAPI = { - &PyDateTime_DateType, - &PyDateTime_DateTimeType, - &PyDateTime_TimeType, - &PyDateTime_DeltaType, - &PyDateTime_TZInfoType, - NULL, // PyDatetime_TimeZone_UTC not initialized yet - new_date_ex, - new_datetime_ex, - new_time_ex, - new_delta_ex, - new_timezone, - datetime_fromtimestamp, - datetime_date_fromtimestamp_capi, - new_datetime_ex2, - new_time_ex2 -}; - - - -static struct PyModuleDef datetimemodule = { - PyModuleDef_HEAD_INIT, - "_datetime", - "Fast implementation of the datetime type.", - -1, - module_methods, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit__datetime(void) +static inline PyDateTime_CAPI * +get_datetime_capi(void) { - PyObject *m; /* a module object */ - PyObject *d; /* its dict */ - PyObject *x; - PyObject *delta; - - m = PyModule_Create(&datetimemodule); - if (m == NULL) + PyDateTime_CAPI *capi = PyMem_Malloc(sizeof(PyDateTime_CAPI)); + if (capi == NULL) { + PyErr_NoMemory(); return NULL; + } + capi->DateType = &PyDateTime_DateType; + capi->DateTimeType = &PyDateTime_DateTimeType; + capi->TimeType = &PyDateTime_TimeType; + capi->DeltaType = &PyDateTime_DeltaType; + capi->TZInfoType = &PyDateTime_TZInfoType; + capi->Date_FromDate = new_date_ex; + capi->DateTime_FromDateAndTime = new_datetime_ex; + capi->Time_FromTime = new_time_ex; + capi->Delta_FromDelta = new_delta_ex; + capi->TimeZone_FromTimeZone = new_timezone; + capi->DateTime_FromTimestamp = datetime_fromtimestamp; + capi->Date_FromTimestamp = datetime_date_fromtimestamp_capi; + capi->DateTime_FromDateAndTimeAndFold = new_datetime_ex2; + capi->Time_FromTimeAndFold = new_time_ex2; + // Make sure this function is called after PyDateTime_TimeZone_UTC has + // been initialized. + assert(PyDateTime_TimeZone_UTC != NULL); + capi->TimeZone_UTC = PyDateTime_TimeZone_UTC; // borrowed ref + return capi; +} +static void +datetime_destructor(PyObject *op) +{ + void *ptr = PyCapsule_GetPointer(op, PyDateTime_CAPSULE_NAME); + PyMem_Free(ptr); +} + +static int +_datetime_exec(PyObject *module) +{ // `&...` is not a constant expression according to a strict reading // of C standards. Fill tp_base at run-time rather than statically. // See https://bugs.python.org/issue40777 @@ -6546,136 +6532,124 @@ PyInit__datetime(void) }; for (size_t i = 0; i < Py_ARRAY_LENGTH(types); i++) { - if (PyModule_AddType(m, types[i]) < 0) { - return NULL; + if (PyModule_AddType(module, types[i]) < 0) { + return -1; } } if (PyType_Ready(&PyDateTime_IsoCalendarDateType) < 0) { - return NULL; + return -1; } - Py_INCREF(&PyDateTime_IsoCalendarDateType); - /* timedelta values */ - d = PyDateTime_DeltaType.tp_dict; +#define DATETIME_ADD_MACRO(dict, c, value_expr) \ + do { \ + PyObject *value = (value_expr); \ + if (value == NULL) { \ + return -1; \ + } \ + if (PyDict_SetItemString(dict, c, value) < 0) { \ + Py_DECREF(value); \ + return -1; \ + } \ + Py_DECREF(value); \ + } while(0) - x = new_delta(0, 0, 1, 0); - if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_delta(-MAX_DELTA_DAYS, 0, 0, 0); - if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0); - if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) - return NULL; - Py_DECREF(x); + /* timedelta values */ + PyObject *d = PyDateTime_DeltaType.tp_dict; + DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0)); + DATETIME_ADD_MACRO(d, "min", new_delta(-MAX_DELTA_DAYS, 0, 0, 0)); + DATETIME_ADD_MACRO(d, "max", + new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0)); /* date values */ d = PyDateTime_DateType.tp_dict; - - x = new_date(1, 1, 1); - if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_date(MAXYEAR, 12, 31); - if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_delta(1, 0, 0, 0); - if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0) - return NULL; - Py_DECREF(x); + DATETIME_ADD_MACRO(d, "min", new_date(1, 1, 1)); + DATETIME_ADD_MACRO(d, "max", new_date(MAXYEAR, 12, 31)); + DATETIME_ADD_MACRO(d, "resolution", new_delta(1, 0, 0, 0)); /* time values */ d = PyDateTime_TimeType.tp_dict; - - x = new_time(0, 0, 0, 0, Py_None, 0); - if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_time(23, 59, 59, 999999, Py_None, 0); - if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_delta(0, 0, 1, 0); - if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0) - return NULL; - Py_DECREF(x); + DATETIME_ADD_MACRO(d, "min", new_time(0, 0, 0, 0, Py_None, 0)); + DATETIME_ADD_MACRO(d, "max", new_time(23, 59, 59, 999999, Py_None, 0)); + DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0)); /* datetime values */ d = PyDateTime_DateTimeType.tp_dict; - - x = new_datetime(1, 1, 1, 0, 0, 0, 0, Py_None, 0); - if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999, Py_None, 0); - if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_delta(0, 0, 1, 0); - if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0) - return NULL; - Py_DECREF(x); + DATETIME_ADD_MACRO(d, "min", + new_datetime(1, 1, 1, 0, 0, 0, 0, Py_None, 0)); + DATETIME_ADD_MACRO(d, "max", new_datetime(MAXYEAR, 12, 31, 23, 59, 59, + 999999, Py_None, 0)); + DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0)); /* timezone values */ d = PyDateTime_TimeZoneType.tp_dict; + PyObject *delta = new_delta(0, 0, 0, 0); + if (delta == NULL) { + return -1; + } - delta = new_delta(0, 0, 0, 0); - if (delta == NULL) - return NULL; - x = create_timezone(delta, NULL); + PyObject *x = create_timezone(delta, NULL); Py_DECREF(delta); - if (x == NULL || PyDict_SetItemString(d, "utc", x) < 0) - return NULL; + if (x == NULL) { + return -1; + } + if (PyDict_SetItemString(d, "utc", x) < 0) { + Py_DECREF(x); + return -1; + } + PyDateTime_TimeZone_UTC = x; - CAPI.TimeZone_UTC = PyDateTime_TimeZone_UTC; /* bpo-37642: These attributes are rounded to the nearest minute for backwards * compatibility, even though the constructor will accept a wider range of * values. This may change in the future.*/ delta = new_delta(-1, 60, 0, 1); /* -23:59 */ - if (delta == NULL) - return NULL; + if (delta == NULL) { + return -1; + } + x = create_timezone(delta, NULL); Py_DECREF(delta); - if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) - return NULL; - Py_DECREF(x); + DATETIME_ADD_MACRO(d, "min", x); delta = new_delta(0, (23 * 60 + 59) * 60, 0, 0); /* +23:59 */ - if (delta == NULL) - return NULL; + if (delta == NULL) { + return -1; + } + x = create_timezone(delta, NULL); Py_DECREF(delta); - if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) - return NULL; - Py_DECREF(x); + DATETIME_ADD_MACRO(d, "max", x); /* Epoch */ PyDateTime_Epoch = new_datetime(1970, 1, 1, 0, 0, 0, 0, PyDateTime_TimeZone_UTC, 0); - if (PyDateTime_Epoch == NULL) - return NULL; + if (PyDateTime_Epoch == NULL) { + return -1; + } /* module initialization */ - PyModule_AddIntMacro(m, MINYEAR); - PyModule_AddIntMacro(m, MAXYEAR); + if (PyModule_AddIntMacro(module, MINYEAR) < 0) { + return -1; + } + if (PyModule_AddIntMacro(module, MAXYEAR) < 0) { + return -1; + } - x = PyCapsule_New(&CAPI, PyDateTime_CAPSULE_NAME, NULL); - if (x == NULL) - return NULL; - PyModule_AddObject(m, "datetime_CAPI", x); + PyDateTime_CAPI *capi = get_datetime_capi(); + if (capi == NULL) { + return -1; + } + x = PyCapsule_New(capi, PyDateTime_CAPSULE_NAME, datetime_destructor); + if (x == NULL) { + PyMem_Free(capi); + return -1; + } + + if (PyModule_AddObject(module, "datetime_CAPI", x) < 0) { + Py_DECREF(x); + return -1; + } /* A 4-year cycle has an extra leap day over what we'd get from * pasting together 4 single years. @@ -6700,8 +6674,9 @@ PyInit__datetime(void) us_per_minute = PyLong_FromLong(60000000); seconds_per_day = PyLong_FromLong(24 * 3600); if (us_per_ms == NULL || us_per_second == NULL || - us_per_minute == NULL || seconds_per_day == NULL) - return NULL; + us_per_minute == NULL || seconds_per_day == NULL) { + return -1; + } /* The rest are too big for 32-bit ints, but even * us_per_week fits in 40 bits, so doubles should be exact. @@ -6709,9 +6684,33 @@ PyInit__datetime(void) us_per_hour = PyLong_FromDouble(3600000000.0); us_per_day = PyLong_FromDouble(86400000000.0); us_per_week = PyLong_FromDouble(604800000000.0); - if (us_per_hour == NULL || us_per_day == NULL || us_per_week == NULL) + if (us_per_hour == NULL || us_per_day == NULL || us_per_week == NULL) { + return -1; + } + return 0; +} + +static struct PyModuleDef datetimemodule = { + PyModuleDef_HEAD_INIT, + .m_name = "_datetime", + .m_doc = "Fast implementation of the datetime type.", + .m_size = -1, + .m_methods = module_methods, +}; + +PyMODINIT_FUNC +PyInit__datetime(void) +{ + PyObject *mod = PyModule_Create(&datetimemodule); + if (mod == NULL) return NULL; - return m; + + if (_datetime_exec(mod) < 0) { + Py_DECREF(mod); + return NULL; + } + + return mod; } /* --------------------------------------------------------------------------- diff --git a/contrib/tools/python3/src/Modules/_decimal/_decimal.c b/contrib/tools/python3/src/Modules/_decimal/_decimal.c index d80d791550..e2979a577c 100644 --- a/contrib/tools/python3/src/Modules/_decimal/_decimal.c +++ b/contrib/tools/python3/src/Modules/_decimal/_decimal.c @@ -1762,7 +1762,7 @@ ctxmanager_dealloc(PyDecContextManagerObject *self) { Py_XDECREF(self->local); Py_XDECREF(self->global); - PyObject_Del(self); + PyObject_Free(self); } static PyObject * @@ -3183,6 +3183,31 @@ dotsep_as_utf8(const char *s) return utf8; } +static int +dict_get_item_string(PyObject *dict, const char *key, PyObject **valueobj, const char **valuestr) +{ + *valueobj = NULL; + PyObject *keyobj = PyUnicode_FromString(key); + if (keyobj == NULL) { + return -1; + } + PyObject *value = PyDict_GetItemWithError(dict, keyobj); + Py_DECREF(keyobj); + if (value == NULL) { + if (PyErr_Occurred()) { + return -1; + } + return 0; + } + value = PyUnicode_AsUTF8String(value); + if (value == NULL) { + return -1; + } + *valueobj = value; + *valuestr = PyBytes_AS_STRING(value); + return 0; +} + /* Formatted representation of a PyDecObject. */ static PyObject * dec_format(PyObject *dec, PyObject *args) @@ -3253,23 +3278,11 @@ dec_format(PyObject *dec, PyObject *args) "optional argument must be a dict"); goto finish; } - if ((dot = PyDict_GetItemString(override, "decimal_point"))) { - if ((dot = PyUnicode_AsUTF8String(dot)) == NULL) { - goto finish; - } - spec.dot = PyBytes_AS_STRING(dot); - } - if ((sep = PyDict_GetItemString(override, "thousands_sep"))) { - if ((sep = PyUnicode_AsUTF8String(sep)) == NULL) { - goto finish; - } - spec.sep = PyBytes_AS_STRING(sep); - } - if ((grouping = PyDict_GetItemString(override, "grouping"))) { - if ((grouping = PyUnicode_AsUTF8String(grouping)) == NULL) { - goto finish; - } - spec.grouping = PyBytes_AS_STRING(grouping); + if (dict_get_item_string(override, "decimal_point", &dot, &spec.dot) || + dict_get_item_string(override, "thousands_sep", &sep, &spec.sep) || + dict_get_item_string(override, "grouping", &grouping, &spec.grouping)) + { + goto finish; } if (mpd_validate_lconv(&spec) < 0) { PyErr_SetString(PyExc_ValueError, @@ -3279,7 +3292,7 @@ dec_format(PyObject *dec, PyObject *args) } else { size_t n = strlen(spec.dot); - if (n > 1 || (n == 1 && !isascii((uchar)spec.dot[0]))) { + if (n > 1 || (n == 1 && !isascii((unsigned char)spec.dot[0]))) { /* fix locale dependent non-ascii characters */ dot = dotsep_as_utf8(spec.dot); if (dot == NULL) { @@ -3288,7 +3301,7 @@ dec_format(PyObject *dec, PyObject *args) spec.dot = PyBytes_AS_STRING(dot); } n = strlen(spec.sep); - if (n > 1 || (n == 1 && !isascii((uchar)spec.sep[0]))) { + if (n > 1 || (n == 1 && !isascii((unsigned char)spec.sep[0]))) { /* fix locale dependent non-ascii characters */ sep = dotsep_as_utf8(spec.sep); if (sep == NULL) { @@ -4522,7 +4535,6 @@ _dec_hash(PyDecObject *v) #error "No valid combination of CONFIG_64, CONFIG_32 and _PyHASH_BITS" #endif const Py_hash_t py_hash_inf = 314159; - const Py_hash_t py_hash_nan = 0; mpd_uint_t ten_data[1] = {10}; mpd_t ten = {MPD_POS|MPD_STATIC|MPD_CONST_DATA, 0, 2, 1, 1, ten_data}; @@ -4541,7 +4553,7 @@ _dec_hash(PyDecObject *v) return -1; } else if (mpd_isnan(MPD(v))) { - return py_hash_nan; + return _Py_HashPointer(v); } else { return py_hash_inf * mpd_arith_sign(MPD(v)); @@ -5925,5 +5937,3 @@ error: return NULL; /* GCOV_NOT_REACHED */ } - - diff --git a/contrib/tools/python3/src/Modules/_decimal/libmpdec/bench.c b/contrib/tools/python3/src/Modules/_decimal/libmpdec/bench.c new file mode 100644 index 0000000000..09138f4ce9 --- /dev/null +++ b/contrib/tools/python3/src/Modules/_decimal/libmpdec/bench.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2008-2020 Stefan Krah. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include "mpdecimal.h" + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> + + +static void +err_exit(const char *msg) +{ + fprintf(stderr, "%s\n", msg); + exit(1); +} + +static mpd_t * +new_mpd(void) +{ + mpd_t *x = mpd_qnew(); + if (x == NULL) { + err_exit("out of memory"); + } + + return x; +} + +/* Nonsense version of escape-time algorithm for calculating a mandelbrot + * set. Just for benchmarking. */ +static void +color_point(mpd_t *x0, mpd_t *y0, long maxiter, mpd_context_t *ctx) +{ + mpd_t *x, *y, *sq_x, *sq_y; + mpd_t *two; + + x = new_mpd(); + y = new_mpd(); + mpd_set_u32(x, 0, ctx); + mpd_set_u32(y, 0, ctx); + + sq_x = new_mpd(); + sq_y = new_mpd(); + mpd_set_u32(sq_x, 0, ctx); + mpd_set_u32(sq_y, 0, ctx); + + two = new_mpd(); + mpd_set_u32(two, 2, ctx); + + for (long i = 0; i < maxiter; i++) { + mpd_mul(y, x, y, ctx); + mpd_mul(y, y, two, ctx); + mpd_add(y, y, y0, ctx); + + mpd_sub(x, sq_x, sq_y, ctx); + mpd_add(x, x, x0, ctx); + + mpd_mul(sq_x, x, x, ctx); + mpd_mul(sq_y, y, y, ctx); + } + + mpd_copy(x0, x, ctx); + + mpd_del(two); + mpd_del(sq_y); + mpd_del(sq_x); + mpd_del(y); + mpd_del(x); +} + + +int +main(int argc, char **argv) +{ + mpd_context_t ctx; + mpd_t *x0, *y0; + uint32_t prec = 19; + long iter = 10000000; + clock_t start_clock, end_clock; + + if (argc != 3) { + err_exit("usage: bench prec iter\n"); + } + prec = strtoul(argv[1], NULL, 10); + iter = strtol(argv[2], NULL, 10); + + mpd_init(&ctx, prec); + /* no more MPD_MINALLOC changes after here */ + + x0 = new_mpd(); + y0 = new_mpd(); + mpd_set_string(x0, "0.222", &ctx); + mpd_set_string(y0, "0.333", &ctx); + if (ctx.status & MPD_Errors) { + mpd_del(y0); + mpd_del(x0); + err_exit("unexpected error during conversion"); + } + + start_clock = clock(); + color_point(x0, y0, iter, &ctx); + end_clock = clock(); + + mpd_print(x0); + fprintf(stderr, "time: %f\n\n", (double)(end_clock-start_clock)/(double)CLOCKS_PER_SEC); + + mpd_del(y0); + mpd_del(x0); + + return 0; +} diff --git a/contrib/tools/python3/src/Modules/_decimal/libmpdec/bench_full.c b/contrib/tools/python3/src/Modules/_decimal/libmpdec/bench_full.c new file mode 100644 index 0000000000..6ab73917e1 --- /dev/null +++ b/contrib/tools/python3/src/Modules/_decimal/libmpdec/bench_full.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2008-2020 Stefan Krah. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include "mpdecimal.h" + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> + + +static void +err_exit(const char *msg) +{ + fprintf(stderr, "%s\n", msg); + exit(1); +} + +static mpd_t * +new_mpd(void) +{ + mpd_t *x = mpd_qnew(); + if (x == NULL) { + err_exit("out of memory"); + } + + return x; +} + +/* + * Example from: http://en.wikipedia.org/wiki/Mandelbrot_set + * + * Escape time algorithm for drawing the set: + * + * Point x0, y0 is deemed to be in the Mandelbrot set if the return + * value is maxiter. Lower return values indicate how quickly points + * escaped and can be used for coloring. + */ +static int +color_point(const mpd_t *x0, const mpd_t *y0, const long maxiter, mpd_context_t *ctx) +{ + mpd_t *x, *y, *sq_x, *sq_y; + mpd_t *two, *four, *c; + long i; + + x = new_mpd(); + y = new_mpd(); + mpd_set_u32(x, 0, ctx); + mpd_set_u32(y, 0, ctx); + + sq_x = new_mpd(); + sq_y = new_mpd(); + mpd_set_u32(sq_x, 0, ctx); + mpd_set_u32(sq_y, 0, ctx); + + two = new_mpd(); + four = new_mpd(); + mpd_set_u32(two, 2, ctx); + mpd_set_u32(four, 4, ctx); + + c = new_mpd(); + mpd_set_u32(c, 0, ctx); + + for (i = 0; i < maxiter && mpd_cmp(c, four, ctx) <= 0; i++) { + mpd_mul(y, x, y, ctx); + mpd_mul(y, y, two, ctx); + mpd_add(y, y, y0, ctx); + + mpd_sub(x, sq_x, sq_y, ctx); + mpd_add(x, x, x0, ctx); + + mpd_mul(sq_x, x, x, ctx); + mpd_mul(sq_y, y, y, ctx); + mpd_add(c, sq_x, sq_y, ctx); + } + + mpd_del(c); + mpd_del(four); + mpd_del(two); + mpd_del(sq_y); + mpd_del(sq_x); + mpd_del(y); + mpd_del(x); + + return i; +} + +int +main(int argc, char **argv) +{ + mpd_context_t ctx; + mpd_t *x0, *y0; + mpd_t *sqrt_2, *xstep, *ystep; + mpd_ssize_t prec = 19; + + long iter = 1000; + int points[40][80]; + int i, j; + clock_t start_clock, end_clock; + + + if (argc != 3) { + fprintf(stderr, "usage: ./bench prec iter\n"); + exit(1); + } + prec = strtoll(argv[1], NULL, 10); + iter = strtol(argv[2], NULL, 10); + + mpd_init(&ctx, prec); + /* no more MPD_MINALLOC changes after here */ + + sqrt_2 = new_mpd(); + xstep = new_mpd(); + ystep = new_mpd(); + x0 = new_mpd(); + y0 = new_mpd(); + + mpd_set_u32(sqrt_2, 2, &ctx); + mpd_sqrt(sqrt_2, sqrt_2, &ctx); + mpd_div_u32(xstep, sqrt_2, 40, &ctx); + mpd_div_u32(ystep, sqrt_2, 20, &ctx); + + start_clock = clock(); + mpd_copy(y0, sqrt_2, &ctx); + for (i = 0; i < 40; i++) { + mpd_copy(x0, sqrt_2, &ctx); + mpd_set_negative(x0); + for (j = 0; j < 80; j++) { + points[i][j] = color_point(x0, y0, iter, &ctx); + mpd_add(x0, x0, xstep, &ctx); + } + mpd_sub(y0, y0, ystep, &ctx); + } + end_clock = clock(); + +#ifdef BENCH_VERBOSE + for (i = 0; i < 40; i++) { + for (j = 0; j < 80; j++) { + if (points[i][j] == iter) { + putchar('*'); + } + else if (points[i][j] >= 10) { + putchar('+'); + } + else if (points[i][j] >= 5) { + putchar('.'); + } + else { + putchar(' '); + } + } + putchar('\n'); + } + putchar('\n'); +#else + (void)points; /* suppress gcc warning */ +#endif + + printf("time: %f\n\n", (double)(end_clock-start_clock)/(double)CLOCKS_PER_SEC); + + mpd_del(y0); + mpd_del(x0); + mpd_del(ystep); + mpd_del(xstep); + mpd_del(sqrt_2); + + return 0; +} diff --git a/contrib/tools/python3/src/Modules/_decimal/libmpdec/constants.c b/contrib/tools/python3/src/Modules/_decimal/libmpdec/constants.c index 4c4de622bc..ed074fa81c 100644 --- a/contrib/tools/python3/src/Modules/_decimal/libmpdec/constants.c +++ b/contrib/tools/python3/src/Modules/_decimal/libmpdec/constants.c @@ -27,6 +27,7 @@ #include "mpdecimal.h" +#include "basearith.h" #include "constants.h" @@ -111,7 +112,7 @@ #error "CONFIG_64 or CONFIG_32 must be defined." #endif -const char *mpd_round_string[MPD_ROUND_GUARD] = { +const char * const mpd_round_string[MPD_ROUND_GUARD] = { "ROUND_UP", /* round away from 0 */ "ROUND_DOWN", /* round toward 0 (truncate) */ "ROUND_CEILING", /* round toward +infinity */ @@ -123,7 +124,7 @@ const char *mpd_round_string[MPD_ROUND_GUARD] = { "ROUND_TRUNC", /* truncate, but set infinity */ }; -const char *mpd_clamp_string[MPD_CLAMP_GUARD] = { +const char * const mpd_clamp_string[MPD_CLAMP_GUARD] = { "CLAMP_DEFAULT", "CLAMP_IEEE_754" }; diff --git a/contrib/tools/python3/src/Modules/_decimal/libmpdec/context.c b/contrib/tools/python3/src/Modules/_decimal/libmpdec/context.c index 9cbc205095..172794b67d 100644 --- a/contrib/tools/python3/src/Modules/_decimal/libmpdec/context.c +++ b/contrib/tools/python3/src/Modules/_decimal/libmpdec/context.c @@ -235,12 +235,12 @@ mpd_qsetround(mpd_context_t *ctx, int round) } int -mpd_qsettraps(mpd_context_t *ctx, uint32_t traps) +mpd_qsettraps(mpd_context_t *ctx, uint32_t flags) { - if (traps > MPD_Max_status) { + if (flags > MPD_Max_status) { return 0; } - ctx->traps = traps; + ctx->traps = flags; return 1; } diff --git a/contrib/tools/python3/src/Modules/_decimal/libmpdec/crt.c b/contrib/tools/python3/src/Modules/_decimal/libmpdec/crt.c index 613274ee0c..babcce41bf 100644 --- a/contrib/tools/python3/src/Modules/_decimal/libmpdec/crt.c +++ b/contrib/tools/python3/src/Modules/_decimal/libmpdec/crt.c @@ -33,8 +33,8 @@ #include "constants.h" #include "crt.h" #include "numbertheory.h" -#include "umodarith.h" #include "typearith.h" +#include "umodarith.h" /* Bignum: Chinese Remainder Theorem, extends the maximum transform length. */ @@ -62,17 +62,17 @@ static inline void _crt_add3(mpd_uint_t w[3], mpd_uint_t v[3]) { mpd_uint_t carry; - mpd_uint_t s; - s = w[0] + v[0]; - carry = (s < w[0]); - w[0] = s; + w[0] = w[0] + v[0]; + carry = (w[0] < v[0]); + + w[1] = w[1] + v[1]; + if (w[1] < v[1]) w[2]++; - s = w[1] + (v[1] + carry); - carry = (s < w[1]); - w[1] = s; + w[1] = w[1] + carry; + if (w[1] < carry) w[2]++; - w[2] = w[2] + (v[2] + carry); + w[2] += v[2]; } /* Divide 3 words in u by v, store result in w, return remainder. */ diff --git a/contrib/tools/python3/src/Modules/_decimal/libmpdec/crt.h b/contrib/tools/python3/src/Modules/_decimal/libmpdec/crt.h index 15a347d4cb..ed66753c25 100644 --- a/contrib/tools/python3/src/Modules/_decimal/libmpdec/crt.h +++ b/contrib/tools/python3/src/Modules/_decimal/libmpdec/crt.h @@ -37,7 +37,7 @@ MPD_PRAGMA(MPD_HIDE_SYMBOLS_START) -void crt3(mpd_uint_t *x1, mpd_uint_t *x2, mpd_uint_t *x3, mpd_size_t nmemb); +void crt3(mpd_uint_t *x1, mpd_uint_t *x2, mpd_uint_t *x3, mpd_size_t rsize); MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */ diff --git a/contrib/tools/python3/src/Modules/_decimal/libmpdec/examples/compare.c b/contrib/tools/python3/src/Modules/_decimal/libmpdec/examples/compare.c new file mode 100644 index 0000000000..9051773e11 --- /dev/null +++ b/contrib/tools/python3/src/Modules/_decimal/libmpdec/examples/compare.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2008-2020 Stefan Krah. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <mpdecimal.h> + + +int +main(int argc, char **argv) +{ + mpd_context_t ctx; + mpd_t *a, *b; + mpd_t *result; + char *rstring; + char status_str[MPD_MAX_FLAG_STRING]; + clock_t start_clock, end_clock; + + if (argc != 3) { + fprintf(stderr, "compare: usage: ./compare x y\n"); + exit(1); + } + + mpd_init(&ctx, 38); + ctx.traps = 0; + + result = mpd_new(&ctx); + a = mpd_new(&ctx); + b = mpd_new(&ctx); + mpd_set_string(a, argv[1], &ctx); + mpd_set_string(b, argv[2], &ctx); + + start_clock = clock(); + mpd_compare(result, a, b, &ctx); + end_clock = clock(); + fprintf(stderr, "time: %f\n\n", + (double)(end_clock-start_clock)/(double)CLOCKS_PER_SEC); + + rstring = mpd_to_sci(result, 1); + mpd_snprint_flags(status_str, MPD_MAX_FLAG_STRING, ctx.status); + printf("%s %s\n", rstring, status_str); + + mpd_del(a); + mpd_del(b); + mpd_del(result); + mpd_free(rstring); + + return 0; +} + + diff --git a/contrib/tools/python3/src/Modules/_decimal/libmpdec/examples/div.c b/contrib/tools/python3/src/Modules/_decimal/libmpdec/examples/div.c new file mode 100644 index 0000000000..b76037d2a6 --- /dev/null +++ b/contrib/tools/python3/src/Modules/_decimal/libmpdec/examples/div.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2008-2020 Stefan Krah. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <mpdecimal.h> + + +int +main(int argc, char **argv) +{ + mpd_context_t ctx; + mpd_t *a, *b; + mpd_t *result; + char *rstring; + char status_str[MPD_MAX_FLAG_STRING]; + clock_t start_clock, end_clock; + + if (argc != 3) { + fprintf(stderr, "div: usage: ./div x y\n"); + exit(1); + } + + mpd_init(&ctx, 38); + ctx.traps = 0; + + result = mpd_new(&ctx); + a = mpd_new(&ctx); + b = mpd_new(&ctx); + mpd_set_string(a, argv[1], &ctx); + mpd_set_string(b, argv[2], &ctx); + + start_clock = clock(); + mpd_div(result, a, b, &ctx); + end_clock = clock(); + fprintf(stderr, "time: %f\n\n", + (double)(end_clock-start_clock)/(double)CLOCKS_PER_SEC); + + rstring = mpd_to_sci(result, 1); + mpd_snprint_flags(status_str, MPD_MAX_FLAG_STRING, ctx.status); + printf("%s %s\n", rstring, status_str); + + mpd_del(a); + mpd_del(b); + mpd_del(result); + mpd_free(rstring); + + return 0; +} + + diff --git a/contrib/tools/python3/src/Modules/_decimal/libmpdec/examples/divmod.c b/contrib/tools/python3/src/Modules/_decimal/libmpdec/examples/divmod.c new file mode 100644 index 0000000000..1f2b48306d --- /dev/null +++ b/contrib/tools/python3/src/Modules/_decimal/libmpdec/examples/divmod.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2008-2020 Stefan Krah. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <mpdecimal.h> + + +int +main(int argc, char **argv) +{ + mpd_context_t ctx; + mpd_t *a, *b; + mpd_t *q, *r; + char *qs, *rs; + char status_str[MPD_MAX_FLAG_STRING]; + clock_t start_clock, end_clock; + + if (argc != 3) { + fprintf(stderr, "divmod: usage: ./divmod x y\n"); + exit(1); + } + + mpd_init(&ctx, 38); + ctx.traps = 0; + + q = mpd_new(&ctx); + r = mpd_new(&ctx); + a = mpd_new(&ctx); + b = mpd_new(&ctx); + mpd_set_string(a, argv[1], &ctx); + mpd_set_string(b, argv[2], &ctx); + + start_clock = clock(); + mpd_divmod(q, r, a, b, &ctx); + end_clock = clock(); + fprintf(stderr, "time: %f\n\n", + (double)(end_clock-start_clock)/(double)CLOCKS_PER_SEC); + + qs = mpd_to_sci(q, 1); + rs = mpd_to_sci(r, 1); + + mpd_snprint_flags(status_str, MPD_MAX_FLAG_STRING, ctx.status); + printf("%s %s %s\n", qs, rs, status_str); + + mpd_del(q); + mpd_del(r); + mpd_del(a); + mpd_del(b); + mpd_free(qs); + mpd_free(rs); + + return 0; +} + + diff --git a/contrib/tools/python3/src/Modules/_decimal/libmpdec/examples/multiply.c b/contrib/tools/python3/src/Modules/_decimal/libmpdec/examples/multiply.c new file mode 100644 index 0000000000..7f2687d15f --- /dev/null +++ b/contrib/tools/python3/src/Modules/_decimal/libmpdec/examples/multiply.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2008-2020 Stefan Krah. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <mpdecimal.h> + + +int +main(int argc, char **argv) +{ + mpd_context_t ctx; + mpd_t *a, *b; + mpd_t *result; + char *rstring; + char status_str[MPD_MAX_FLAG_STRING]; + clock_t start_clock, end_clock; + + if (argc != 3) { + fprintf(stderr, "multiply: usage: ./multiply x y\n"); + exit(1); + } + + mpd_init(&ctx, 38); + ctx.traps = 0; + + result = mpd_new(&ctx); + a = mpd_new(&ctx); + b = mpd_new(&ctx); + mpd_set_string(a, argv[1], &ctx); + mpd_set_string(b, argv[2], &ctx); + + start_clock = clock(); + mpd_mul(result, a, b, &ctx); + end_clock = clock(); + fprintf(stderr, "time: %f\n\n", + (double)(end_clock-start_clock)/(double)CLOCKS_PER_SEC); + + rstring = mpd_to_sci(result, 1); + mpd_snprint_flags(status_str, MPD_MAX_FLAG_STRING, ctx.status); + printf("%s %s\n", rstring, status_str); + + mpd_del(a); + mpd_del(b); + mpd_del(result); + mpd_free(rstring); + + return 0; +} + + diff --git a/contrib/tools/python3/src/Modules/_decimal/libmpdec/examples/pow.c b/contrib/tools/python3/src/Modules/_decimal/libmpdec/examples/pow.c new file mode 100644 index 0000000000..628c143427 --- /dev/null +++ b/contrib/tools/python3/src/Modules/_decimal/libmpdec/examples/pow.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2008-2020 Stefan Krah. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <mpdecimal.h> + + +int +main(int argc, char **argv) +{ + mpd_context_t ctx; + mpd_t *a, *b; + mpd_t *result; + char *rstring; + char status_str[MPD_MAX_FLAG_STRING]; + clock_t start_clock, end_clock; + + if (argc != 3) { + fprintf(stderr, "pow: usage: ./pow x y\n"); + exit(1); + } + + mpd_init(&ctx, 38); + ctx.traps = 0; + + result = mpd_new(&ctx); + a = mpd_new(&ctx); + b = mpd_new(&ctx); + mpd_set_string(a, argv[1], &ctx); + mpd_set_string(b, argv[2], &ctx); + + start_clock = clock(); + mpd_pow(result, a, b, &ctx); + end_clock = clock(); + fprintf(stderr, "time: %f\n\n", + (double)(end_clock-start_clock)/(double)CLOCKS_PER_SEC); + + rstring = mpd_to_sci(result, 1); + mpd_snprint_flags(status_str, MPD_MAX_FLAG_STRING, ctx.status); + printf("%s %s\n", rstring, status_str); + + mpd_del(a); + mpd_del(b); + mpd_del(result); + mpd_free(rstring); + + return 0; +} + + diff --git a/contrib/tools/python3/src/Modules/_decimal/libmpdec/examples/powmod.c b/contrib/tools/python3/src/Modules/_decimal/libmpdec/examples/powmod.c new file mode 100644 index 0000000000..b422fdbbb9 --- /dev/null +++ b/contrib/tools/python3/src/Modules/_decimal/libmpdec/examples/powmod.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2008-2020 Stefan Krah. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <mpdecimal.h> + + +int +main(int argc, char **argv) +{ + mpd_context_t ctx; + mpd_t *a, *b, *c; + mpd_t *result; + char *rstring; + char status_str[MPD_MAX_FLAG_STRING]; + clock_t start_clock, end_clock; + + if (argc != 4) { + fprintf(stderr, "powmod: usage: ./powmod x y z\n"); + exit(1); + } + + mpd_init(&ctx, 38); + ctx.traps = 0; + + result = mpd_new(&ctx); + a = mpd_new(&ctx); + b = mpd_new(&ctx); + c = mpd_new(&ctx); + mpd_set_string(a, argv[1], &ctx); + mpd_set_string(b, argv[2], &ctx); + mpd_set_string(c, argv[3], &ctx); + + start_clock = clock(); + mpd_powmod(result, a, b, c, &ctx); + end_clock = clock(); + fprintf(stderr, "time: %f\n\n", + (double)(end_clock-start_clock)/(double)CLOCKS_PER_SEC); + + rstring = mpd_to_sci(result, 1); + mpd_snprint_flags(status_str, MPD_MAX_FLAG_STRING, ctx.status); + printf("%s %s\n", rstring, status_str); + + mpd_del(a); + mpd_del(b); + mpd_del(c); + mpd_del(result); + mpd_free(rstring); + + return 0; +} + + diff --git a/contrib/tools/python3/src/Modules/_decimal/libmpdec/examples/shift.c b/contrib/tools/python3/src/Modules/_decimal/libmpdec/examples/shift.c new file mode 100644 index 0000000000..6d54e108ca --- /dev/null +++ b/contrib/tools/python3/src/Modules/_decimal/libmpdec/examples/shift.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2008-2020 Stefan Krah. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <mpdecimal.h> + + +int +main(int argc, char **argv) +{ + mpd_context_t ctx; + mpd_t *a, *b; + mpd_t *result; + char *rstring; + char status_str[MPD_MAX_FLAG_STRING]; + clock_t start_clock, end_clock; + + if (argc != 3) { + fprintf(stderr, "shift: usage: ./shift x y\n"); + exit(1); + } + + mpd_init(&ctx, 38); + ctx.traps = 0; + + result = mpd_new(&ctx); + a = mpd_new(&ctx); + b = mpd_new(&ctx); + mpd_set_string(a, argv[1], &ctx); + mpd_set_string(b, argv[2], &ctx); + + start_clock = clock(); + mpd_shift(result, a, b, &ctx); + end_clock = clock(); + fprintf(stderr, "time: %f\n\n", + (double)(end_clock-start_clock)/(double)CLOCKS_PER_SEC); + + rstring = mpd_to_sci(result, 1); + mpd_snprint_flags(status_str, MPD_MAX_FLAG_STRING, ctx.status); + printf("%s %s\n", rstring, status_str); + + mpd_del(a); + mpd_del(b); + mpd_del(result); + mpd_free(rstring); + + return 0; +} + + diff --git a/contrib/tools/python3/src/Modules/_decimal/libmpdec/vccompat.h b/contrib/tools/python3/src/Modules/_decimal/libmpdec/examples/sqrt.c index e2e1c42cc0..d8272789b1 100644 --- a/contrib/tools/python3/src/Modules/_decimal/libmpdec/vccompat.h +++ b/contrib/tools/python3/src/Modules/_decimal/libmpdec/examples/sqrt.c @@ -26,31 +26,49 @@ */ -#ifndef LIBMPDEC_VCCOMPAT_H_ -#define LIBMPDEC_VCCOMPAT_H_ - - -/* Visual C fixes: no snprintf ... */ -#ifdef _MSC_VER - #ifndef __cplusplus - #undef inline - #define inline __inline - #endif - #undef random - #define random rand - #undef srandom - #define srandom srand - #undef snprintf - #define snprintf sprintf_s - #define HAVE_SNPRINTF - #undef strncasecmp - #define strncasecmp _strnicmp - #undef strcasecmp - #define strcasecmp _stricmp - #undef strtoll - #define strtoll _strtoi64 - #define strdup _strdup -#endif - - -#endif /* LIBMPDEC_VCCOMPAT_H_ */ +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <mpdecimal.h> + + +int +main(int argc, char **argv) +{ + mpd_context_t ctx; + mpd_t *a; + mpd_t *result; + char *rstring; + char status_str[MPD_MAX_FLAG_STRING]; + clock_t start_clock, end_clock; + + if (argc != 2) { + fprintf(stderr, "sqrt: usage: ./sqrt x\n"); + exit(1); + } + + mpd_init(&ctx, 38); + ctx.traps = 0; + + result = mpd_new(&ctx); + a = mpd_new(&ctx); + mpd_set_string(a, argv[1], &ctx); + + start_clock = clock(); + mpd_sqrt(result, a, &ctx); + end_clock = clock(); + fprintf(stderr, "time: %f\n\n", + (double)(end_clock-start_clock)/(double)CLOCKS_PER_SEC); + + rstring = mpd_to_sci(result, 1); + mpd_snprint_flags(status_str, MPD_MAX_FLAG_STRING, ctx.status); + printf("%s %s\n", rstring, status_str); + + mpd_del(a); + mpd_del(result); + mpd_free(rstring); + + return 0; +} + + diff --git a/contrib/tools/python3/src/Modules/_decimal/libmpdec/io.c b/contrib/tools/python3/src/Modules/_decimal/libmpdec/io.c index 03f2acfc1a..ecebe82e1f 100644 --- a/contrib/tools/python3/src/Modules/_decimal/libmpdec/io.c +++ b/contrib/tools/python3/src/Modules/_decimal/libmpdec/io.c @@ -37,17 +37,17 @@ #include <stdlib.h> #include <string.h> -#include "typearith.h" #include "mpd_io.h" +#include "typearith.h" /* This file contains functions for decimal <-> string conversions, including PEP-3101 formatting for numeric types. */ -/* Disable warning that is part of -Wextra since gcc 7.0. */ #if defined(__GNUC__) && !defined(__INTEL_COMPILER) && __GNUC__ >= 7 #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" + #pragma GCC diagnostic ignored "-Wmisleading-indentation" #endif @@ -155,13 +155,13 @@ scan_dpoint_exp(const char *s, const char **dpoint, const char **exp, s++; break; default: - if (!isdigit((uchar)*s)) + if (!isdigit((unsigned char)*s)) return NULL; if (coeff == NULL && *exp == NULL) { if (*s == '0') { - if (!isdigit((uchar)*(s+1))) + if (!isdigit((unsigned char)*(s+1))) if (!(*(s+1) == '.' && - isdigit((uchar)*(s+2)))) + isdigit((unsigned char)*(s+2)))) coeff = s; } else { @@ -187,7 +187,7 @@ scan_payload(const char *s, const char **end) s++; coeff = s; - while (isdigit((uchar)*s)) + while (isdigit((unsigned char)*s)) s++; *end = s; @@ -689,8 +689,8 @@ mpd_to_eng_size(char **res, const mpd_t *dec, int fmt) static int _mpd_copy_utf8(char dest[5], const char *s) { - const uchar *cp = (const uchar *)s; - uchar lb, ub; + const unsigned char *cp = (const unsigned char *)s; + unsigned char lb, ub; int count, i; @@ -843,7 +843,7 @@ mpd_parse_fmt_str(mpd_spec_t *spec, const char *fmt, int caps) } /* minimum width */ - if (isdigit((uchar)*cp)) { + if (isdigit((unsigned char)*cp)) { if (*cp == '0') { return 0; } @@ -865,7 +865,7 @@ mpd_parse_fmt_str(mpd_spec_t *spec, const char *fmt, int caps) /* fraction digits or significant digits */ if (*cp == '.') { cp++; - if (!isdigit((uchar)*cp)) { + if (!isdigit((unsigned char)*cp)) { return 0; } errno = 0; @@ -1105,9 +1105,9 @@ _mpd_apply_lconv(mpd_mbstr_t *result, const mpd_spec_t *spec, uint32_t *status) sign = dp++; } /* integer part */ - assert(isdigit((uchar)*dp)); + assert(isdigit((unsigned char)*dp)); intpart = dp++; - while (isdigit((uchar)*dp)) { + while (isdigit((unsigned char)*dp)) { dp++; } n_int = (mpd_ssize_t)(dp-intpart); @@ -1262,8 +1262,8 @@ mpd_qformat_spec(const mpd_t *dec, const mpd_spec_t *spec, return NULL; } - if (isupper((uchar)type)) { - type = (char)tolower((uchar)type); + if (isupper((unsigned char)type)) { + type = (char)tolower((unsigned char)type); flags |= MPD_FMT_UPPER; } if (spec->sign == ' ') { diff --git a/contrib/tools/python3/src/Modules/_decimal/libmpdec/mpalloc.c b/contrib/tools/python3/src/Modules/_decimal/libmpdec/mpalloc.c index eb5ee7a807..5871d5c0f5 100644 --- a/contrib/tools/python3/src/Modules/_decimal/libmpdec/mpalloc.c +++ b/contrib/tools/python3/src/Modules/_decimal/libmpdec/mpalloc.c @@ -61,13 +61,6 @@ mpd_callocfunc_em(size_t nmemb, size_t size) size_t req; mpd_size_t overflow; -#if MPD_SIZE_MAX < SIZE_MAX - /* full_coverage test only */ - if (nmemb > MPD_SIZE_MAX || size > MPD_SIZE_MAX) { - return NULL; - } -#endif - req = mul_size_t_overflow((mpd_size_t)nmemb, (mpd_size_t)size, &overflow); if (overflow) { diff --git a/contrib/tools/python3/src/Modules/_decimal/libmpdec/mpalloc.h b/contrib/tools/python3/src/Modules/_decimal/libmpdec/mpalloc.h index 186808457b..2265004421 100644 --- a/contrib/tools/python3/src/Modules/_decimal/libmpdec/mpalloc.h +++ b/contrib/tools/python3/src/Modules/_decimal/libmpdec/mpalloc.h @@ -39,12 +39,12 @@ MPD_PRAGMA(MPD_HIDE_SYMBOLS_START) -int mpd_switch_to_dyn(mpd_t *result, mpd_ssize_t size, uint32_t *status); -int mpd_switch_to_dyn_zero(mpd_t *result, mpd_ssize_t size, uint32_t *status); -int mpd_realloc_dyn(mpd_t *result, mpd_ssize_t size, uint32_t *status); +int mpd_switch_to_dyn(mpd_t *result, mpd_ssize_t nwords, uint32_t *status); +int mpd_switch_to_dyn_zero(mpd_t *result, mpd_ssize_t nwords, uint32_t *status); +int mpd_realloc_dyn(mpd_t *result, mpd_ssize_t nwords, uint32_t *status); -int mpd_switch_to_dyn_cxx(mpd_t *result, mpd_ssize_t size); -int mpd_realloc_dyn_cxx(mpd_t *result, mpd_ssize_t size); +int mpd_switch_to_dyn_cxx(mpd_t *result, mpd_ssize_t nwords); +int mpd_realloc_dyn_cxx(mpd_t *result, mpd_ssize_t nwords); MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */ diff --git a/contrib/tools/python3/src/Modules/_decimal/libmpdec/mpdecimal.c b/contrib/tools/python3/src/Modules/_decimal/libmpdec/mpdecimal.c index 28b639ccb4..f1626df46e 100644 --- a/contrib/tools/python3/src/Modules/_decimal/libmpdec/mpdecimal.c +++ b/contrib/tools/python3/src/Modules/_decimal/libmpdec/mpdecimal.c @@ -64,7 +64,7 @@ #if defined(_MSC_VER) #define ALWAYS_INLINE __forceinline -#elif defined(__IBMC__) || defined(LEGACY_COMPILER) +#elif defined (__IBMC__) || defined(LEGACY_COMPILER) #define ALWAYS_INLINE #undef inline #define inline @@ -4843,7 +4843,7 @@ _mpd_qln(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status) { mpd_context_t varcontext, maxcontext; - mpd_t *z = (mpd_t *) result; + mpd_t *z = result; MPD_NEW_STATIC(v,0,0,0,0); MPD_NEW_STATIC(vtmp,0,0,0,0); MPD_NEW_STATIC(tmp,0,0,0,0); @@ -6368,7 +6368,7 @@ _mpd_qpow_int(mpd_t *result, const mpd_t *base, const mpd_t *exp, mpd_context_t workctx; MPD_NEW_STATIC(tbase,0,0,0,0); MPD_NEW_STATIC(texp,0,0,0,0); - mpd_ssize_t n; + mpd_uint_t n; mpd_workcontext(&workctx, ctx); @@ -8090,7 +8090,6 @@ mpd_sizeinbase(const mpd_t *a, uint32_t base) } digits = a->digits+a->exp; - assert(digits > 0); #ifdef CONFIG_64 /* ceil(2711437152599294 / log10(2)) + 4 == 2**53 */ @@ -8656,3 +8655,355 @@ mpd_qimport_u32(mpd_t *result, mpd_qresize(result, result->len, status); mpd_qfinalize(result, ctx, status); } + + +/******************************************************************************/ +/* From triple */ +/******************************************************************************/ + +#if defined(CONFIG_64) && defined(__SIZEOF_INT128__) +static mpd_ssize_t +_set_coeff(uint64_t data[3], uint64_t hi, uint64_t lo) +{ + __uint128_t d = ((__uint128_t)hi << 64) + lo; + __uint128_t q, r; + + q = d / MPD_RADIX; + r = d % MPD_RADIX; + data[0] = (uint64_t)r; + d = q; + + q = d / MPD_RADIX; + r = d % MPD_RADIX; + data[1] = (uint64_t)r; + d = q; + + q = d / MPD_RADIX; + r = d % MPD_RADIX; + data[2] = (uint64_t)r; + + if (q != 0) { + abort(); /* GCOV_NOT_REACHED */ + } + + return data[2] != 0 ? 3 : (data[1] != 0 ? 2 : 1); +} +#else +static size_t +_uint_from_u16(mpd_uint_t *w, mpd_ssize_t wlen, const uint16_t *u, size_t ulen) +{ + const mpd_uint_t ubase = 1U<<16; + mpd_ssize_t n = 0; + mpd_uint_t carry; + + assert(wlen > 0 && ulen > 0); + + w[n++] = u[--ulen]; + while (--ulen != SIZE_MAX) { + carry = _mpd_shortmul_c(w, w, n, ubase); + if (carry) { + if (n >= wlen) { + abort(); /* GCOV_NOT_REACHED */ + } + w[n++] = carry; + } + carry = _mpd_shortadd(w, n, u[ulen]); + if (carry) { + if (n >= wlen) { + abort(); /* GCOV_NOT_REACHED */ + } + w[n++] = carry; + } + } + + return n; +} + +static mpd_ssize_t +_set_coeff(mpd_uint_t *data, mpd_ssize_t len, uint64_t hi, uint64_t lo) +{ + uint16_t u16[8] = {0}; + + u16[7] = (uint16_t)((hi & 0xFFFF000000000000ULL) >> 48); + u16[6] = (uint16_t)((hi & 0x0000FFFF00000000ULL) >> 32); + u16[5] = (uint16_t)((hi & 0x00000000FFFF0000ULL) >> 16); + u16[4] = (uint16_t) (hi & 0x000000000000FFFFULL); + + u16[3] = (uint16_t)((lo & 0xFFFF000000000000ULL) >> 48); + u16[2] = (uint16_t)((lo & 0x0000FFFF00000000ULL) >> 32); + u16[1] = (uint16_t)((lo & 0x00000000FFFF0000ULL) >> 16); + u16[0] = (uint16_t) (lo & 0x000000000000FFFFULL); + + return (mpd_ssize_t)_uint_from_u16(data, len, u16, 8); +} +#endif + +static int +_set_uint128_coeff_exp(mpd_t *result, uint64_t hi, uint64_t lo, mpd_ssize_t exp) +{ + mpd_uint_t data[5] = {0}; + uint32_t status = 0; + mpd_ssize_t len; + +#if defined(CONFIG_64) && defined(__SIZEOF_INT128__) + len = _set_coeff(data, hi, lo); +#else + len = _set_coeff(data, 5, hi, lo); +#endif + + if (!mpd_qresize(result, len, &status)) { + return -1; + } + + for (mpd_ssize_t i = 0; i < len; i++) { + result->data[i] = data[i]; + } + + result->exp = exp; + result->len = len; + mpd_setdigits(result); + + return 0; +} + +int +mpd_from_uint128_triple(mpd_t *result, const mpd_uint128_triple_t *triple, uint32_t *status) +{ + static const mpd_context_t maxcontext = { + .prec=MPD_MAX_PREC, + .emax=MPD_MAX_EMAX, + .emin=MPD_MIN_EMIN, + .round=MPD_ROUND_HALF_EVEN, + .traps=MPD_Traps, + .status=0, + .newtrap=0, + .clamp=0, + .allcr=1, + }; + const enum mpd_triple_class tag = triple->tag; + const uint8_t sign = triple->sign; + const uint64_t hi = triple->hi; + const uint64_t lo = triple->lo; + mpd_ssize_t exp; + +#ifdef CONFIG_32 + if (triple->exp < MPD_SSIZE_MIN || triple->exp > MPD_SSIZE_MAX) { + goto conversion_error; + } +#endif + exp = (mpd_ssize_t)triple->exp; + + switch (tag) { + case MPD_TRIPLE_QNAN: case MPD_TRIPLE_SNAN: { + if (sign > 1 || exp != 0) { + goto conversion_error; + } + + const uint8_t flags = tag == MPD_TRIPLE_QNAN ? MPD_NAN : MPD_SNAN; + mpd_setspecial(result, sign, flags); + + if (hi == 0 && lo == 0) { /* no payload */ + return 0; + } + + if (_set_uint128_coeff_exp(result, hi, lo, exp) < 0) { + goto malloc_error; + } + + return 0; + } + + case MPD_TRIPLE_INF: { + if (sign > 1 || hi != 0 || lo != 0 || exp != 0) { + goto conversion_error; + } + + mpd_setspecial(result, sign, MPD_INF); + + return 0; + } + + case MPD_TRIPLE_NORMAL: { + if (sign > 1) { + goto conversion_error; + } + + const uint8_t flags = sign ? MPD_NEG : MPD_POS; + mpd_set_flags(result, flags); + + if (exp > MPD_EXP_INF) { + exp = MPD_EXP_INF; + } + if (exp == MPD_SSIZE_MIN) { + exp = MPD_SSIZE_MIN+1; + } + + if (_set_uint128_coeff_exp(result, hi, lo, exp) < 0) { + goto malloc_error; + } + + uint32_t workstatus = 0; + mpd_qfinalize(result, &maxcontext, &workstatus); + if (workstatus & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) { + goto conversion_error; + } + + return 0; + } + + default: + goto conversion_error; + } + +conversion_error: + mpd_seterror(result, MPD_Conversion_syntax, status); + return -1; + +malloc_error: + mpd_seterror(result, MPD_Malloc_error, status); + return -1; +} + + +/******************************************************************************/ +/* As triple */ +/******************************************************************************/ + +#if defined(CONFIG_64) && defined(__SIZEOF_INT128__) +static void +_get_coeff(uint64_t *hi, uint64_t *lo, const mpd_t *a) +{ + __uint128_t u128 = 0; + + switch (a->len) { + case 3: + u128 = a->data[2]; /* fall through */ + case 2: + u128 = u128 * MPD_RADIX + a->data[1]; /* fall through */ + case 1: + u128 = u128 * MPD_RADIX + a->data[0]; + break; + default: + abort(); /* GCOV_NOT_REACHED */ + } + + *hi = u128 >> 64; + *lo = (uint64_t)u128; +} +#else +static size_t +_uint_to_u16(uint16_t w[8], mpd_uint_t *u, mpd_ssize_t ulen) +{ + const mpd_uint_t wbase = 1U<<16; + size_t n = 0; + + assert(ulen > 0); + + do { + if (n >= 8) { + abort(); /* GCOV_NOT_REACHED */ + } + w[n++] = (uint16_t)_mpd_shortdiv(u, u, ulen, wbase); + /* ulen is at least 1. u[ulen-1] can only be zero if ulen == 1. */ + ulen = _mpd_real_size(u, ulen); + + } while (u[ulen-1] != 0); + + return n; +} + +static void +_get_coeff(uint64_t *hi, uint64_t *lo, const mpd_t *a) +{ + uint16_t u16[8] = {0}; + mpd_uint_t data[5] = {0}; + + switch (a->len) { + case 5: + data[4] = a->data[4]; /* fall through */ + case 4: + data[3] = a->data[3]; /* fall through */ + case 3: + data[2] = a->data[2]; /* fall through */ + case 2: + data[1] = a->data[1]; /* fall through */ + case 1: + data[0] = a->data[0]; + break; + default: + abort(); /* GCOV_NOT_REACHED */ + } + + _uint_to_u16(u16, data, a->len); + + *hi = (uint64_t)u16[7] << 48; + *hi |= (uint64_t)u16[6] << 32; + *hi |= (uint64_t)u16[5] << 16; + *hi |= (uint64_t)u16[4]; + + *lo = (uint64_t)u16[3] << 48; + *lo |= (uint64_t)u16[2] << 32; + *lo |= (uint64_t)u16[1] << 16; + *lo |= (uint64_t)u16[0]; +} +#endif + +static enum mpd_triple_class +_coeff_as_uint128(uint64_t *hi, uint64_t *lo, const mpd_t *a) +{ +#ifdef CONFIG_64 + static mpd_uint_t uint128_max_data[3] = { 3374607431768211455ULL, 4028236692093846346ULL, 3ULL }; + static const mpd_t uint128_max = { MPD_STATIC|MPD_CONST_DATA, 0, 39, 3, 3, uint128_max_data }; +#else + static mpd_uint_t uint128_max_data[5] = { 768211455U, 374607431U, 938463463U, 282366920U, 340U }; + static const mpd_t uint128_max = { MPD_STATIC|MPD_CONST_DATA, 0, 39, 5, 5, uint128_max_data }; +#endif + enum mpd_triple_class ret = MPD_TRIPLE_NORMAL; + uint32_t status = 0; + mpd_t coeff; + + *hi = *lo = 0ULL; + + if (mpd_isspecial(a)) { + if (mpd_isinfinite(a)) { + return MPD_TRIPLE_INF; + } + + ret = mpd_isqnan(a) ? MPD_TRIPLE_QNAN : MPD_TRIPLE_SNAN; + if (a->len == 0) { /* no payload */ + return ret; + } + } + else if (mpd_iszero(a)) { + return ret; + } + + _mpd_copy_shared(&coeff, a); + mpd_set_flags(&coeff, 0); + coeff.exp = 0; + + if (mpd_qcmp(&coeff, &uint128_max, &status) > 0) { + return MPD_TRIPLE_ERROR; + } + + _get_coeff(hi, lo, &coeff); + return ret; +} + +mpd_uint128_triple_t +mpd_as_uint128_triple(const mpd_t *a) +{ + mpd_uint128_triple_t triple = { MPD_TRIPLE_ERROR, 0, 0, 0, 0 }; + + triple.tag = _coeff_as_uint128(&triple.hi, &triple.lo, a); + if (triple.tag == MPD_TRIPLE_ERROR) { + return triple; + } + + triple.sign = !!mpd_isnegative(a); + if (triple.tag == MPD_TRIPLE_NORMAL) { + triple.exp = a->exp; + } + + return triple; +} diff --git a/contrib/tools/python3/src/Modules/_decimal/libmpdec/mpdecimal.h b/contrib/tools/python3/src/Modules/_decimal/libmpdec/mpdecimal.h index f66f6e5920..8a5aa26b7b 100644 --- a/contrib/tools/python3/src/Modules/_decimal/libmpdec/mpdecimal.h +++ b/contrib/tools/python3/src/Modules/_decimal/libmpdec/mpdecimal.h @@ -40,6 +40,7 @@ #include <cstdint> #include <cstdio> #include <cstdlib> + #define MPD_UINT8_C(x) (static_cast<uint8_t>(x)) extern "C" { #else #include <inttypes.h> @@ -47,6 +48,7 @@ extern "C" { #include <stdint.h> #include <stdio.h> #include <stdlib.h> + #define MPD_UINT8_C(x) ((uint8_t)x) #endif @@ -62,7 +64,6 @@ extern "C" { #endif #if defined(_MSC_VER) - #include "vccompat.h" #define EXTINLINE extern inline #else #define EXTINLINE @@ -74,25 +75,15 @@ extern "C" { MPD_PRAGMA(MPD_HIDE_SYMBOLS_START) -#if !defined(LEGACY_COMPILER) - #if !defined(UINT64_MAX) - /* The following #error is just a warning. If the compiler indeed does - * not have uint64_t, it is perfectly safe to comment out the #error. */ - #error "Warning: Compiler without uint64_t. Comment out this line." - #define LEGACY_COMPILER - #endif -#endif - - /******************************************************************************/ /* Version */ /******************************************************************************/ #define MPD_MAJOR_VERSION 2 #define MPD_MINOR_VERSION 5 -#define MPD_MICRO_VERSION 0 +#define MPD_MICRO_VERSION 1 -#define MPD_VERSION "2.5.0" +#define MPD_VERSION "2.5.1" #define MPD_VERSION_HEX ((MPD_MAJOR_VERSION << 24) | \ (MPD_MINOR_VERSION << 16) | \ @@ -162,6 +153,7 @@ typedef int64_t mpd_ssize_t; #define MPD_EXP_INF 2000000000000000001LL #define MPD_EXP_CLAMP (-4000000000000000001LL) #define MPD_MAXIMPORT 105263157894736842L /* ceil((2*MPD_MAX_PREC)/MPD_RDIGITS) */ +#define MPD_IEEE_CONTEXT_MAX_BITS 512 /* 16*(log2(MPD_MAX_EMAX / 3)-3) */ /* conversion specifiers */ #define PRI_mpd_uint_t PRIu64 @@ -203,9 +195,10 @@ typedef int32_t mpd_ssize_t; #define MPD_MAX_EMAX 425000000L /* ELIMIT-1 */ #define MPD_MIN_EMIN (-425000000L) /* -EMAX */ #define MPD_MIN_ETINY (MPD_MIN_EMIN-(MPD_MAX_PREC-1)) -#define MPD_EXP_INF 1000000001L /* allows for emax=999999999 in the tests */ -#define MPD_EXP_CLAMP (-2000000001L) /* allows for emin=-999999999 in the tests */ -#define MPD_MAXIMPORT 94444445L /* ceil((2*MPD_MAX_PREC)/MPD_RDIGITS) */ +#define MPD_EXP_INF 1000000001L /* allows for emax=999999999 in the tests */ +#define MPD_EXP_CLAMP (-2000000001L) /* allows for emin=-999999999 in the tests */ +#define MPD_MAXIMPORT 94444445L /* ceil((2*MPD_MAX_PREC)/MPD_RDIGITS) */ +#define MPD_IEEE_CONTEXT_MAX_BITS 256 /* 16*(log2(MPD_MAX_EMAX / 3)-3) */ /* conversion specifiers */ #define PRI_mpd_uint_t PRIu32 @@ -242,8 +235,8 @@ enum { enum { MPD_CLAMP_DEFAULT, MPD_CLAMP_IEEE_754, MPD_CLAMP_GUARD }; -extern const char *mpd_round_string[MPD_ROUND_GUARD]; -extern const char *mpd_clamp_string[MPD_CLAMP_GUARD]; +extern const char * const mpd_round_string[MPD_ROUND_GUARD]; +extern const char * const mpd_clamp_string[MPD_CLAMP_GUARD]; typedef struct mpd_context_t { @@ -300,7 +293,6 @@ typedef struct mpd_context_t { #define MPD_Insufficient_storage MPD_Malloc_error /* IEEE 754 interchange format contexts */ -#define MPD_IEEE_CONTEXT_MAX_BITS 512 /* 16*(log2(MPD_MAX_EMAX / 3)-3) */ #define MPD_DECIMAL32 32 #define MPD_DECIMAL64 64 #define MPD_DECIMAL128 128 @@ -345,16 +337,16 @@ void mpd_addstatus_raise(mpd_context_t *ctx, uint32_t flags); /******************************************************************************/ /* mpd_t flags */ -#define MPD_POS ((uint8_t)0) -#define MPD_NEG ((uint8_t)1) -#define MPD_INF ((uint8_t)2) -#define MPD_NAN ((uint8_t)4) -#define MPD_SNAN ((uint8_t)8) +#define MPD_POS MPD_UINT8_C(0) +#define MPD_NEG MPD_UINT8_C(1) +#define MPD_INF MPD_UINT8_C(2) +#define MPD_NAN MPD_UINT8_C(4) +#define MPD_SNAN MPD_UINT8_C(8) #define MPD_SPECIAL (MPD_INF|MPD_NAN|MPD_SNAN) -#define MPD_STATIC ((uint8_t)16) -#define MPD_STATIC_DATA ((uint8_t)32) -#define MPD_SHARED_DATA ((uint8_t)64) -#define MPD_CONST_DATA ((uint8_t)128) +#define MPD_STATIC MPD_UINT8_C(16) +#define MPD_STATIC_DATA MPD_UINT8_C(32) +#define MPD_SHARED_DATA MPD_UINT8_C(64) +#define MPD_CONST_DATA MPD_UINT8_C(128) #define MPD_DATAFLAGS (MPD_STATIC_DATA|MPD_SHARED_DATA|MPD_CONST_DATA) /* mpd_t */ @@ -368,7 +360,29 @@ typedef struct mpd_t { } mpd_t; -typedef unsigned char uchar; +/******************************************************************************/ +/* Triple */ +/******************************************************************************/ + +/* status cases for getting a triple */ +enum mpd_triple_class { + MPD_TRIPLE_NORMAL, + MPD_TRIPLE_INF, + MPD_TRIPLE_QNAN, + MPD_TRIPLE_SNAN, + MPD_TRIPLE_ERROR, +}; + +typedef struct { + enum mpd_triple_class tag; + uint8_t sign; + uint64_t hi; + uint64_t lo; + int64_t exp; +} mpd_uint128_triple_t; + +int mpd_from_uint128_triple(mpd_t *result, const mpd_uint128_triple_t *triple, uint32_t *status); +mpd_uint128_triple_t mpd_as_uint128_triple(const mpd_t *a); /******************************************************************************/ @@ -417,7 +431,7 @@ void mpd_qset_string_exact(mpd_t *dec, const char *s, uint32_t *status); /* set to NaN with error flags */ void mpd_seterror(mpd_t *result, uint32_t flags, uint32_t *status); /* set a special with sign and type */ -void mpd_setspecial(mpd_t *dec, uint8_t sign, uint8_t type); +void mpd_setspecial(mpd_t *result, uint8_t sign, uint8_t type); /* set coefficient to zero or all nines */ void mpd_zerocoeff(mpd_t *result); void mpd_qmaxcoeff(mpd_t *result, const mpd_context_t *ctx, uint32_t *status); @@ -810,16 +824,16 @@ void *mpd_sh_alloc(mpd_size_t struct_size, mpd_size_t nmemb, mpd_size_t size); mpd_t *mpd_qnew(void); mpd_t *mpd_new(mpd_context_t *ctx); -mpd_t *mpd_qnew_size(mpd_ssize_t size); +mpd_t *mpd_qnew_size(mpd_ssize_t nwords); EXTINLINE void mpd_del(mpd_t *dec); EXTINLINE void mpd_uint_zero(mpd_uint_t *dest, mpd_size_t len); -EXTINLINE int mpd_qresize(mpd_t *result, mpd_ssize_t size, uint32_t *status); -EXTINLINE int mpd_qresize_zero(mpd_t *result, mpd_ssize_t size, uint32_t *status); +EXTINLINE int mpd_qresize(mpd_t *result, mpd_ssize_t nwords, uint32_t *status); +EXTINLINE int mpd_qresize_zero(mpd_t *result, mpd_ssize_t nwords, uint32_t *status); EXTINLINE void mpd_minalloc(mpd_t *result); -int mpd_resize(mpd_t *result, mpd_ssize_t size, mpd_context_t *ctx); -int mpd_resize_zero(mpd_t *result, mpd_ssize_t size, mpd_context_t *ctx); +int mpd_resize(mpd_t *result, mpd_ssize_t nwords, mpd_context_t *ctx); +int mpd_resize_zero(mpd_t *result, mpd_ssize_t nwords, mpd_context_t *ctx); MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */ diff --git a/contrib/tools/python3/src/Modules/_decimal/libmpdec/mpsignal.c b/contrib/tools/python3/src/Modules/_decimal/libmpdec/mpsignal.c new file mode 100644 index 0000000000..fc2af48f4f --- /dev/null +++ b/contrib/tools/python3/src/Modules/_decimal/libmpdec/mpsignal.c @@ -0,0 +1,967 @@ +/* + * Copyright (c) 2008-2020 Stefan Krah. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include "mpdecimal.h" + +#include <stddef.h> +#include <stdint.h> + + +/* Signaling wrappers for the quiet functions in mpdecimal.c. */ + + +char * +mpd_format(const mpd_t *dec, const char *fmt, mpd_context_t *ctx) +{ + char *ret; + uint32_t status = 0; + ret = mpd_qformat(dec, fmt, ctx, &status); + mpd_addstatus_raise(ctx, status); + return ret; +} + +void +mpd_import_u16(mpd_t *result, const uint16_t *srcdata, size_t srclen, + uint8_t srcsign, uint32_t base, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qimport_u16(result, srcdata, srclen, srcsign, base, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_import_u32(mpd_t *result, const uint32_t *srcdata, size_t srclen, + uint8_t srcsign, uint32_t base, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qimport_u32(result, srcdata, srclen, srcsign, base, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +size_t +mpd_export_u16(uint16_t **rdata, size_t rlen, uint32_t base, const mpd_t *src, + mpd_context_t *ctx) +{ + size_t n; + uint32_t status = 0; + n = mpd_qexport_u16(rdata, rlen, base, src, &status); + mpd_addstatus_raise(ctx, status); + return n; +} + +size_t +mpd_export_u32(uint32_t **rdata, size_t rlen, uint32_t base, const mpd_t *src, + mpd_context_t *ctx) +{ + size_t n; + uint32_t status = 0; + n = mpd_qexport_u32(rdata, rlen, base, src, &status); + mpd_addstatus_raise(ctx, status); + return n; +} + +void +mpd_finalize(mpd_t *result, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qfinalize(result, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +int +mpd_check_nan(mpd_t *result, const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + if (mpd_qcheck_nan(result, a, ctx, &status)) { + mpd_addstatus_raise(ctx, status); + return 1; + } + return 0; +} + +int +mpd_check_nans(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx) +{ + uint32_t status = 0; + if (mpd_qcheck_nans(result, a, b, ctx, &status)) { + mpd_addstatus_raise(ctx, status); + return 1; + } + return 0; +} + +void +mpd_set_string(mpd_t *result, const char *s, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qset_string(result, s, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_maxcoeff(mpd_t *result, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qmaxcoeff(result, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +/* set static mpd from signed integer */ +void +mpd_sset_ssize(mpd_t *result, mpd_ssize_t a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qsset_ssize(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_sset_i32(mpd_t *result, int32_t a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qsset_i32(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +#ifdef CONFIG_64 +void +mpd_sset_i64(mpd_t *result, int64_t a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qsset_i64(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} +#endif + +/* set static mpd from unsigned integer */ +void +mpd_sset_uint(mpd_t *result, mpd_uint_t a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qsset_uint(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_sset_u32(mpd_t *result, uint32_t a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qsset_u32(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +#ifdef CONFIG_64 +void +mpd_sset_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qsset_u64(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} +#endif + +/* set mpd from signed integer */ +void +mpd_set_ssize(mpd_t *result, mpd_ssize_t a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qset_ssize(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_set_i32(mpd_t *result, int32_t a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qset_i32(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +#ifndef LEGACY_COMPILER +void +mpd_set_i64(mpd_t *result, int64_t a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qset_i64(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} +#endif + +/* set mpd from unsigned integer */ +void +mpd_set_uint(mpd_t *result, mpd_uint_t a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qset_uint(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_set_u32(mpd_t *result, uint32_t a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qset_u32(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +#ifndef LEGACY_COMPILER +void +mpd_set_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qset_u64(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} +#endif + +/* convert mpd to signed integer */ +mpd_ssize_t +mpd_get_ssize(const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_ssize_t ret; + + ret = mpd_qget_ssize(a, &status); + mpd_addstatus_raise(ctx, status); + return ret; +} + +int32_t +mpd_get_i32(const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + int32_t ret; + + ret = mpd_qget_i32(a, &status); + mpd_addstatus_raise(ctx, status); + return ret; +} + +#ifndef LEGACY_COMPILER +int64_t +mpd_get_i64(const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + int64_t ret; + + ret = mpd_qget_i64(a, &status); + mpd_addstatus_raise(ctx, status); + return ret; +} +#endif + +mpd_uint_t +mpd_get_uint(const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_uint_t ret; + + ret = mpd_qget_uint(a, &status); + mpd_addstatus_raise(ctx, status); + return ret; +} + +mpd_uint_t +mpd_abs_uint(const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_uint_t ret; + + ret = mpd_qabs_uint(a, &status); + mpd_addstatus_raise(ctx, status); + return ret; +} + +uint32_t +mpd_get_u32(const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + uint32_t ret; + + ret = mpd_qget_u32(a, &status); + mpd_addstatus_raise(ctx, status); + return ret; +} + +#ifndef LEGACY_COMPILER +uint64_t +mpd_get_u64(const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + uint64_t ret; + + ret = mpd_qget_u64(a, &status); + mpd_addstatus_raise(ctx, status); + return ret; +} +#endif + +void +mpd_and(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qand(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_copy(mpd_t *result, const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + if (!mpd_qcopy(result, a, &status)) { + mpd_addstatus_raise(ctx, status); + } +} + +void +mpd_canonical(mpd_t *result, const mpd_t *a, mpd_context_t *ctx) +{ + mpd_copy(result, a, ctx); +} + +void +mpd_copy_abs(mpd_t *result, const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + if (!mpd_qcopy_abs(result, a, &status)) { + mpd_addstatus_raise(ctx, status); + } +} + +void +mpd_copy_negate(mpd_t *result, const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + if (!mpd_qcopy_negate(result, a, &status)) { + mpd_addstatus_raise(ctx, status); + } +} + +void +mpd_copy_sign(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx) +{ + uint32_t status = 0; + if (!mpd_qcopy_sign(result, a, b, &status)) { + mpd_addstatus_raise(ctx, status); + } +} + +void +mpd_invert(mpd_t *result, const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qinvert(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_logb(mpd_t *result, const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qlogb(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_or(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qor(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_rotate(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qrotate(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_scaleb(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qscaleb(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_shiftl(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qshiftl(result, a, n, &status); + mpd_addstatus_raise(ctx, status); +} + +mpd_uint_t +mpd_shiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_uint_t rnd; + + rnd = mpd_qshiftr(result, a, n, &status); + mpd_addstatus_raise(ctx, status); + return rnd; +} + +void +mpd_shiftn(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qshiftn(result, a, n, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_shift(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qshift(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_xor(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qxor(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_abs(mpd_t *result, const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qabs(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +int +mpd_cmp(const mpd_t *a, const mpd_t *b, mpd_context_t *ctx) +{ + uint32_t status = 0; + int c; + c = mpd_qcmp(a, b, &status); + mpd_addstatus_raise(ctx, status); + return c; +} + +int +mpd_compare(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx) +{ + uint32_t status = 0; + int c; + c = mpd_qcompare(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); + return c; +} + +int +mpd_compare_signal(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx) +{ + uint32_t status = 0; + int c; + c = mpd_qcompare_signal(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); + return c; +} + +void +mpd_add(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qadd(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_sub(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qsub(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_add_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qadd_ssize(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_add_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qadd_i32(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +#ifndef LEGACY_COMPILER +void +mpd_add_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qadd_i64(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} +#endif + +void +mpd_add_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qadd_uint(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_add_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qadd_u32(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +#ifndef LEGACY_COMPILER +void +mpd_add_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qadd_u64(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} +#endif + +void +mpd_sub_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qsub_ssize(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_sub_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qsub_i32(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +#ifndef LEGACY_COMPILER +void +mpd_sub_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qsub_i64(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} +#endif + +void +mpd_sub_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qsub_uint(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_sub_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qsub_u32(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +#ifndef LEGACY_COMPILER +void +mpd_sub_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qsub_u64(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} +#endif + +void +mpd_div(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qdiv(q, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_div_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qdiv_ssize(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_div_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qdiv_i32(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +#ifndef LEGACY_COMPILER +void +mpd_div_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qdiv_i64(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} +#endif + +void +mpd_div_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qdiv_uint(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_div_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qdiv_u32(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +#ifndef LEGACY_COMPILER +void +mpd_div_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qdiv_u64(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} +#endif + +void +mpd_divmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qdivmod(q, r, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_divint(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qdivint(q, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_exp(mpd_t *result, const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qexp(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_fma(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_t *c, + mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qfma(result, a, b, c, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_ln(mpd_t *result, const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qln(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_log10(mpd_t *result, const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qlog10(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_max(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qmax(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_max_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qmax_mag(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_min(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qmin(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_min_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qmin_mag(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_minus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qminus(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_mul(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qmul(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_mul_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qmul_ssize(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_mul_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qmul_i32(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +#ifndef LEGACY_COMPILER +void +mpd_mul_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qmul_i64(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} +#endif + +void +mpd_mul_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qmul_uint(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_mul_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qmul_u32(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +#ifndef LEGACY_COMPILER +void +mpd_mul_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qmul_u64(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} +#endif + +void +mpd_next_minus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qnext_minus(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_next_plus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qnext_plus(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_next_toward(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qnext_toward(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_plus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qplus(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_pow(mpd_t *result, const mpd_t *base, const mpd_t *exp, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qpow(result, base, exp, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_powmod(mpd_t *result, const mpd_t *base, const mpd_t *exp, const mpd_t *mod, + mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qpowmod(result, base, exp, mod, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_quantize(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qquantize(result, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_rescale(mpd_t *result, const mpd_t *a, mpd_ssize_t exp, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qrescale(result, a, exp, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_reduce(mpd_t *result, const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qreduce(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_rem(mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qrem(r, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_rem_near(mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qrem_near(r, a, b, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_round_to_intx(mpd_t *result, const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qround_to_intx(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_round_to_int(mpd_t *result, const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qround_to_int(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_trunc(mpd_t *result, const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qtrunc(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_floor(mpd_t *result, const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qfloor(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_ceil(mpd_t *result, const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qceil(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_sqrt(mpd_t *result, const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qsqrt(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} + +void +mpd_invroot(mpd_t *result, const mpd_t *a, mpd_context_t *ctx) +{ + uint32_t status = 0; + mpd_qinvroot(result, a, ctx, &status); + mpd_addstatus_raise(ctx, status); +} diff --git a/contrib/tools/python3/src/Modules/_decimal/libmpdec/typearith.h b/contrib/tools/python3/src/Modules/_decimal/libmpdec/typearith.h index 47961788d7..dd3776453d 100644 --- a/contrib/tools/python3/src/Modules/_decimal/libmpdec/typearith.h +++ b/contrib/tools/python3/src/Modules/_decimal/libmpdec/typearith.h @@ -638,10 +638,10 @@ add_size_t_overflow(mpd_size_t a, mpd_size_t b, mpd_size_t *overflow) static inline mpd_size_t mul_size_t_overflow(mpd_size_t a, mpd_size_t b, mpd_size_t *overflow) { - mpd_uint_t lo; + mpd_uint_t hi, lo; - _mpd_mul_words((mpd_uint_t *)overflow, &lo, (mpd_uint_t)a, - (mpd_uint_t)b); + _mpd_mul_words(&hi, &lo, (mpd_uint_t)a, (mpd_uint_t)b); + *overflow = (mpd_size_t)hi; return lo; } diff --git a/contrib/tools/python3/src/Modules/_elementtree.c b/contrib/tools/python3/src/Modules/_elementtree.c index 8d1b56b35d..8637bae0ae 100644 --- a/contrib/tools/python3/src/Modules/_elementtree.c +++ b/contrib/tools/python3/src/Modules/_elementtree.c @@ -2037,7 +2037,7 @@ element_attrib_setter(ElementObject *self, PyObject *value, void *closure) if (!PyDict_Check(value)) { PyErr_Format(PyExc_TypeError, "attrib must be dict, not %.200s", - value->ob_type->tp_name); + Py_TYPE(value)->tp_name); return -1; } if (!self->extra) { diff --git a/contrib/tools/python3/src/Modules/_functoolsmodule.c b/contrib/tools/python3/src/Modules/_functoolsmodule.c index 42764a181d..fa14521680 100644 --- a/contrib/tools/python3/src/Modules/_functoolsmodule.c +++ b/contrib/tools/python3/src/Modules/_functoolsmodule.c @@ -1,7 +1,9 @@ #include "Python.h" +#include "pycore_long.h" // _PyLong_GetZero() +#include "pycore_moduleobject.h" // _PyModule_GetState() #include "pycore_object.h" // _PyObject_GC_TRACK #include "pycore_pystate.h" // _PyThreadState_GET() -#include "pycore_tupleobject.h" +#include "pycore_tuple.h" // _PyTuple_ITEMS() #include "structmember.h" // PyMemberDef /* _functools module written and maintained @@ -11,6 +13,23 @@ All rights reserved. */ +typedef struct _functools_state { + /* this object is used delimit args and keywords in the cache keys */ + PyObject *kwd_mark; + PyTypeObject *partial_type; + PyTypeObject *keyobject_type; + PyTypeObject *lru_list_elem_type; +} _functools_state; + +static inline _functools_state * +get_functools_state(PyObject *module) +{ + void *state = _PyModule_GetState(module); + assert(state != NULL); + return (_functools_state *)state; +} + + /* partial object **********************************************************/ typedef struct { @@ -23,9 +42,20 @@ typedef struct { vectorcallfunc vectorcall; } partialobject; -static PyTypeObject partial_type; - static void partial_setvectorcall(partialobject *pto); +static struct PyModuleDef _functools_module; +static PyObject * +partial_call(partialobject *pto, PyObject *args, PyObject *kwargs); + +static inline _functools_state * +get_functools_state_by_type(PyTypeObject *type) +{ + PyObject *module = _PyType_GetModuleByDef(type, &_functools_module); + if (module == NULL) { + return NULL; + } + return get_functools_state(module); +} static PyObject * partial_new(PyTypeObject *type, PyObject *args, PyObject *kw) @@ -41,7 +71,11 @@ partial_new(PyTypeObject *type, PyObject *args, PyObject *kw) pargs = pkw = NULL; func = PyTuple_GET_ITEM(args, 0); - if (Py_IS_TYPE(func, &partial_type) && type == &partial_type) { + if (Py_TYPE(func)->tp_call == (ternaryfunc)partial_call) { + // The type of "func" might not be exactly the same type object + // as "type", but if it is called using partial_call, it must have the + // same memory layout (fn, args and kw members). + // We can use its underlying function directly and merge the arguments. partialobject *part = (partialobject *)func; if (part->dict == NULL) { pargs = part->args; @@ -113,18 +147,39 @@ partial_new(PyTypeObject *type, PyObject *args, PyObject *kw) return (PyObject *)pto; } +static int +partial_clear(partialobject *pto) +{ + Py_CLEAR(pto->fn); + Py_CLEAR(pto->args); + Py_CLEAR(pto->kw); + Py_CLEAR(pto->dict); + return 0; +} + +static int +partial_traverse(partialobject *pto, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(pto)); + Py_VISIT(pto->fn); + Py_VISIT(pto->args); + Py_VISIT(pto->kw); + Py_VISIT(pto->dict); + return 0; +} + static void partial_dealloc(partialobject *pto) { + PyTypeObject *tp = Py_TYPE(pto); /* bpo-31095: UnTrack is needed before calling any callbacks */ PyObject_GC_UnTrack(pto); - if (pto->weakreflist != NULL) + if (pto->weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject *) pto); - Py_XDECREF(pto->fn); - Py_XDECREF(pto->args); - Py_XDECREF(pto->kw); - Py_XDECREF(pto->dict); - Py_TYPE(pto)->tp_free(pto); + } + (void)partial_clear(pto); + tp->tp_free(pto); + Py_DECREF(tp); } @@ -271,16 +326,6 @@ partial_call(partialobject *pto, PyObject *args, PyObject *kwargs) return res; } -static int -partial_traverse(partialobject *pto, visitproc visit, void *arg) -{ - Py_VISIT(pto->fn); - Py_VISIT(pto->args); - Py_VISIT(pto->kw); - Py_VISIT(pto->dict); - return 0; -} - PyDoc_STRVAR(partial_doc, "partial(func, *args, **keywords) - new function with partial application\n\ of the given arguments and keywords.\n"); @@ -293,6 +338,12 @@ static PyMemberDef partial_memberlist[] = { "tuple of arguments to future partial calls"}, {"keywords", T_OBJECT, OFF(kw), READONLY, "dictionary of keyword arguments to future partial calls"}, + {"__weaklistoffset__", T_PYSSIZET, + offsetof(partialobject, weakreflist), READONLY}, + {"__dictoffset__", T_PYSSIZET, + offsetof(partialobject, dict), READONLY}, + {"__vectorcalloffset__", T_PYSSIZET, + offsetof(partialobject, vectorcall), READONLY}, {NULL} /* Sentinel */ }; @@ -419,49 +470,30 @@ static PyMethodDef partial_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject partial_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "functools.partial", /* tp_name */ - sizeof(partialobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)partial_dealloc, /* tp_dealloc */ - offsetof(partialobject, vectorcall),/* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)partial_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - (ternaryfunc)partial_call, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - PyObject_GenericSetAttr, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_VECTORCALL, /* tp_flags */ - partial_doc, /* tp_doc */ - (traverseproc)partial_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(partialobject, weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - partial_methods, /* tp_methods */ - partial_memberlist, /* tp_members */ - partial_getsetlist, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - offsetof(partialobject, dict), /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - partial_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ +static PyType_Slot partial_type_slots[] = { + {Py_tp_dealloc, partial_dealloc}, + {Py_tp_repr, partial_repr}, + {Py_tp_call, partial_call}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_setattro, PyObject_GenericSetAttr}, + {Py_tp_doc, (void *)partial_doc}, + {Py_tp_traverse, partial_traverse}, + {Py_tp_clear, partial_clear}, + {Py_tp_methods, partial_methods}, + {Py_tp_members, partial_memberlist}, + {Py_tp_getset, partial_getsetlist}, + {Py_tp_new, partial_new}, + {Py_tp_free, PyObject_GC_Del}, + {0, 0} +}; + +static PyType_Spec partial_type_spec = { + .name = "functools.partial", + .basicsize = sizeof(partialobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_VECTORCALL | + Py_TPFLAGS_IMMUTABLETYPE, + .slots = partial_type_slots }; @@ -473,29 +505,30 @@ typedef struct { PyObject *object; } keyobject; +static int +keyobject_clear(keyobject *ko) +{ + Py_CLEAR(ko->cmp); + Py_CLEAR(ko->object); + return 0; +} + static void keyobject_dealloc(keyobject *ko) { - Py_DECREF(ko->cmp); - Py_XDECREF(ko->object); - PyObject_FREE(ko); + PyTypeObject *tp = Py_TYPE(ko); + PyObject_GC_UnTrack(ko); + (void)keyobject_clear(ko); + tp->tp_free(ko); + Py_DECREF(tp); } static int keyobject_traverse(keyobject *ko, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(ko)); Py_VISIT(ko->cmp); - if (ko->object) - Py_VISIT(ko->object); - return 0; -} - -static int -keyobject_clear(keyobject *ko) -{ - Py_CLEAR(ko->cmp); - if (ko->object) - Py_CLEAR(ko->object); + Py_VISIT(ko->object); return 0; } @@ -512,38 +545,23 @@ keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds); static PyObject * keyobject_richcompare(PyObject *ko, PyObject *other, int op); -static PyTypeObject keyobject_type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "functools.KeyWrapper", /* tp_name */ - sizeof(keyobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)keyobject_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - (ternaryfunc)keyobject_call, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - 0, /* tp_doc */ - (traverseproc)keyobject_traverse, /* tp_traverse */ - (inquiry)keyobject_clear, /* tp_clear */ - keyobject_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - keyobject_members, /* tp_members */ - 0, /* tp_getset */ +static PyType_Slot keyobject_type_slots[] = { + {Py_tp_dealloc, keyobject_dealloc}, + {Py_tp_call, keyobject_call}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_traverse, keyobject_traverse}, + {Py_tp_clear, keyobject_clear}, + {Py_tp_richcompare, keyobject_richcompare}, + {Py_tp_members, keyobject_members}, + {0, 0} +}; + +static PyType_Spec keyobject_type_spec = { + .name = "functools.KeyWrapper", + .basicsize = sizeof(keyobject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), + .slots = keyobject_type_slots }; static PyObject * @@ -555,13 +573,16 @@ keyobject_call(keyobject *ko, PyObject *args, PyObject *kwds) if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:K", kwargs, &object)) return NULL; - result = PyObject_New(keyobject, &keyobject_type); - if (!result) + + result = PyObject_GC_New(keyobject, Py_TYPE(ko)); + if (result == NULL) { return NULL; + } Py_INCREF(ko->cmp); result->cmp = ko->cmp; Py_INCREF(object); result->object = object; + PyObject_GC_Track(result); return (PyObject *)result; } @@ -575,7 +596,7 @@ keyobject_richcompare(PyObject *ko, PyObject *other, int op) PyObject *answer; PyObject* stack[2]; - if (!Py_IS_TYPE(other, &keyobject_type)) { + if (!Py_IS_TYPE(other, Py_TYPE(ko))) { PyErr_Format(PyExc_TypeError, "other argument must be K instance"); return NULL; } @@ -598,7 +619,7 @@ keyobject_richcompare(PyObject *ko, PyObject *other, int op) return NULL; } - answer = PyObject_RichCompare(res, _PyLong_Zero, op); + answer = PyObject_RichCompare(res, _PyLong_GetZero(), op); Py_DECREF(res); return answer; } @@ -609,15 +630,19 @@ functools_cmp_to_key(PyObject *self, PyObject *args, PyObject *kwds) PyObject *cmp; static char *kwargs[] = {"mycmp", NULL}; keyobject *object; + _functools_state *state; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:cmp_to_key", kwargs, &cmp)) return NULL; - object = PyObject_New(keyobject, &keyobject_type); + + state = get_functools_state(self); + object = PyObject_GC_New(keyobject, state->keyobject_type); if (!object) return NULL; Py_INCREF(cmp); object->cmp = cmp; object->object = NULL; + PyObject_GC_Track(object); return (PyObject *)object; } @@ -686,7 +711,7 @@ functools_reduce(PyObject *self, PyObject *args) if (result == NULL) PyErr_SetString(PyExc_TypeError, - "reduce() of empty sequence with no initial value"); + "reduce() of empty iterable with no initial value"); Py_DECREF(it); return result; @@ -699,14 +724,14 @@ Fail: } PyDoc_STRVAR(functools_reduce_doc, -"reduce(function, sequence[, initial]) -> value\n\ +"reduce(function, iterable[, initial]) -> value\n\ \n\ -Apply a function of two arguments cumulatively to the items of a sequence,\n\ -from left to right, so as to reduce the sequence to a single value.\n\ -For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates\n\ +Apply a function of two arguments cumulatively to the items of a sequence\n\ +or iterable, from left to right, so as to reduce the iterable to a single\n\ +value. For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates\n\ ((((1+2)+3)+4)+5). If initial is present, it is placed before the items\n\ -of the sequence in the calculation, and serves as a default when the\n\ -sequence is empty."); +of the iterable in the calculation, and serves as a default when the\n\ +iterable is empty."); /* lru_cache object **********************************************************/ @@ -729,10 +754,6 @@ sequence is empty."); */ - -/* this object is used delimit args and keywords in the cache keys */ -static PyObject *kwd_mark = NULL; - struct lru_list_elem; struct lru_cache_object; @@ -746,33 +767,24 @@ typedef struct lru_list_elem { static void lru_list_elem_dealloc(lru_list_elem *link) { + PyTypeObject *tp = Py_TYPE(link); Py_XDECREF(link->key); Py_XDECREF(link->result); - PyObject_Del(link); + tp->tp_free(link); + Py_DECREF(tp); } -static PyTypeObject lru_list_elem_type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "functools._lru_list_elem", /* tp_name */ - sizeof(lru_list_elem), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)lru_list_elem_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ +static PyType_Slot lru_list_elem_type_slots[] = { + {Py_tp_dealloc, lru_list_elem_dealloc}, + {0, 0} +}; + +static PyType_Spec lru_list_elem_type_spec = { + .name = "functools._lru_list_elem", + .basicsize = sizeof(lru_list_elem), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_IMMUTABLETYPE, + .slots = lru_list_elem_type_slots }; @@ -787,15 +799,17 @@ typedef struct lru_cache_object { PyObject *func; Py_ssize_t maxsize; Py_ssize_t misses; + /* the kwd_mark is used delimit args and keywords in the cache keys */ + PyObject *kwd_mark; + PyTypeObject *lru_list_elem_type; PyObject *cache_info_type; PyObject *dict; PyObject *weakreflist; } lru_cache_object; -static PyTypeObject lru_cache_type; - static PyObject * -lru_cache_make_key(PyObject *args, PyObject *kwds, int typed) +lru_cache_make_key(PyObject *kwd_mark, PyObject *args, + PyObject *kwds, int typed) { PyObject *key, *keyword, *value; Py_ssize_t key_size, pos, key_pos, kwds_size; @@ -879,7 +893,7 @@ infinite_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwd { PyObject *result; Py_hash_t hash; - PyObject *key = lru_cache_make_key(args, kwds, self->typed); + PyObject *key = lru_cache_make_key(self->kwd_mark, args, kwds, self->typed); if (!key) return NULL; hash = PyObject_Hash(key); @@ -980,7 +994,7 @@ bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds PyObject *key, *result, *testresult; Py_hash_t hash; - key = lru_cache_make_key(args, kwds, self->typed); + key = lru_cache_make_key(self->kwd_mark, args, kwds, self->typed); if (!key) return NULL; hash = PyObject_Hash(key); @@ -1035,7 +1049,7 @@ bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds { /* Cache is not full, so put the result in a new link */ link = (lru_list_elem *)PyObject_New(lru_list_elem, - &lru_list_elem_type); + self->lru_list_elem_type); if (link == NULL) { Py_DECREF(key); Py_DECREF(result); @@ -1146,6 +1160,7 @@ lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw) lru_cache_object *obj; Py_ssize_t maxsize; PyObject *(*wrapper)(lru_cache_object *, PyObject *, PyObject *); + _functools_state *state; static char *keywords[] = {"user_function", "maxsize", "typed", "cache_info_type", NULL}; @@ -1161,6 +1176,11 @@ lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw) return NULL; } + state = get_functools_state_by_type(type); + if (state == NULL) { + return NULL; + } + /* select the caching function, and make/inc maxsize_O */ if (maxsize_O == Py_None) { wrapper = infinite_lru_cache_wrapper; @@ -1200,6 +1220,10 @@ lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw) obj->func = func; obj->misses = obj->hits = 0; obj->maxsize = maxsize; + Py_INCREF(state->kwd_mark); + obj->kwd_mark = state->kwd_mark; + Py_INCREF(state->lru_list_elem_type); + obj->lru_list_elem_type = state->lru_list_elem_type; Py_INCREF(cache_info_type); obj->cache_info_type = cache_info_type; obj->dict = NULL; @@ -1229,22 +1253,33 @@ lru_cache_clear_list(lru_list_elem *link) } } +static int +lru_cache_tp_clear(lru_cache_object *self) +{ + lru_list_elem *list = lru_cache_unlink_list(self); + Py_CLEAR(self->cache); + Py_CLEAR(self->func); + Py_CLEAR(self->kwd_mark); + Py_CLEAR(self->lru_list_elem_type); + Py_CLEAR(self->cache_info_type); + Py_CLEAR(self->dict); + lru_cache_clear_list(list); + return 0; +} + static void lru_cache_dealloc(lru_cache_object *obj) { - lru_list_elem *list; + PyTypeObject *tp = Py_TYPE(obj); /* bpo-31095: UnTrack is needed before calling any callbacks */ PyObject_GC_UnTrack(obj); - if (obj->weakreflist != NULL) + if (obj->weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject*)obj); + } - list = lru_cache_unlink_list(obj); - Py_XDECREF(obj->cache); - Py_XDECREF(obj->func); - Py_XDECREF(obj->cache_info_type); - Py_XDECREF(obj->dict); - lru_cache_clear_list(list); - Py_TYPE(obj)->tp_free(obj); + (void)lru_cache_tp_clear(obj); + tp->tp_free(obj); + Py_DECREF(tp); } static PyObject * @@ -1309,32 +1344,24 @@ lru_cache_deepcopy(PyObject *self, PyObject *unused) static int lru_cache_tp_traverse(lru_cache_object *self, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(self)); lru_list_elem *link = self->root.next; while (link != &self->root) { lru_list_elem *next = link->next; Py_VISIT(link->key); Py_VISIT(link->result); + Py_VISIT(Py_TYPE(link)); link = next; } - Py_VISIT(self->func); Py_VISIT(self->cache); + Py_VISIT(self->func); + Py_VISIT(self->kwd_mark); + Py_VISIT(self->lru_list_elem_type); Py_VISIT(self->cache_info_type); Py_VISIT(self->dict); return 0; } -static int -lru_cache_tp_clear(lru_cache_object *self) -{ - lru_list_elem *list = lru_cache_unlink_list(self); - Py_CLEAR(self->func); - Py_CLEAR(self->cache); - Py_CLEAR(self->cache_info_type); - Py_CLEAR(self->dict); - lru_cache_clear_list(list); - return 0; -} - PyDoc_STRVAR(lru_cache_doc, "Create a cached callable that wraps another function.\n\ @@ -1366,51 +1393,37 @@ static PyGetSetDef lru_cache_getsetlist[] = { {NULL} }; -static PyTypeObject lru_cache_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "functools._lru_cache_wrapper", /* tp_name */ - sizeof(lru_cache_object), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)lru_cache_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - (ternaryfunc)lru_cache_call, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_METHOD_DESCRIPTOR, - /* tp_flags */ - lru_cache_doc, /* tp_doc */ - (traverseproc)lru_cache_tp_traverse,/* tp_traverse */ - (inquiry)lru_cache_tp_clear, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(lru_cache_object, weakreflist), - /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - lru_cache_methods, /* tp_methods */ - 0, /* tp_members */ - lru_cache_getsetlist, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - lru_cache_descr_get, /* tp_descr_get */ - 0, /* tp_descr_set */ - offsetof(lru_cache_object, dict), /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - lru_cache_new, /* tp_new */ +static PyMemberDef lru_cache_memberlist[] = { + {"__dictoffset__", T_PYSSIZET, + offsetof(lru_cache_object, dict), READONLY}, + {"__weaklistoffset__", T_PYSSIZET, + offsetof(lru_cache_object, weakreflist), READONLY}, + {NULL} /* Sentinel */ +}; + +static PyType_Slot lru_cache_type_slots[] = { + {Py_tp_dealloc, lru_cache_dealloc}, + {Py_tp_call, lru_cache_call}, + {Py_tp_doc, (void *)lru_cache_doc}, + {Py_tp_traverse, lru_cache_tp_traverse}, + {Py_tp_clear, lru_cache_tp_clear}, + {Py_tp_methods, lru_cache_methods}, + {Py_tp_members, lru_cache_memberlist}, + {Py_tp_getset, lru_cache_getsetlist}, + {Py_tp_descr_get, lru_cache_descr_get}, + {Py_tp_new, lru_cache_new}, + {0, 0} }; +static PyType_Spec lru_cache_type_spec = { + .name = "functools._lru_cache_wrapper", + .basicsize = sizeof(lru_cache_object), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_METHOD_DESCRIPTOR | Py_TPFLAGS_IMMUTABLETYPE, + .slots = lru_cache_type_slots +}; + + /* module level code ********************************************************/ PyDoc_STRVAR(_functools_doc, @@ -1423,38 +1436,83 @@ static PyMethodDef _functools_methods[] = { {NULL, NULL} /* sentinel */ }; -static void -_functools_free(void *m) -{ - // FIXME: Do not clear kwd_mark to avoid NULL pointer dereferencing if we have - // other modules instances that could use it. Will fix when PEP-573 land - // and we could move kwd_mark to a per-module state. - // Py_CLEAR(kwd_mark); -} - static int _functools_exec(PyObject *module) { - PyTypeObject *typelist[] = { - &partial_type, - &lru_cache_type - }; - - if (!kwd_mark) { - kwd_mark = _PyObject_CallNoArg((PyObject *)&PyBaseObject_Type); - if (!kwd_mark) { - return -1; - } + _functools_state *state = get_functools_state(module); + state->kwd_mark = _PyObject_CallNoArg((PyObject *)&PyBaseObject_Type); + if (state->kwd_mark == NULL) { + return -1; } - for (size_t i = 0; i < Py_ARRAY_LENGTH(typelist); i++) { - if (PyModule_AddType(module, typelist[i]) < 0) { - return -1; - } + state->partial_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, + &partial_type_spec, NULL); + if (state->partial_type == NULL) { + return -1; } + if (PyModule_AddType(module, state->partial_type) < 0) { + return -1; + } + + PyObject *lru_cache_type = PyType_FromModuleAndSpec(module, + &lru_cache_type_spec, NULL); + if (lru_cache_type == NULL) { + return -1; + } + if (PyModule_AddType(module, (PyTypeObject *)lru_cache_type) < 0) { + Py_DECREF(lru_cache_type); + return -1; + } + Py_DECREF(lru_cache_type); + + state->keyobject_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, + &keyobject_type_spec, NULL); + if (state->keyobject_type == NULL) { + return -1; + } + if (PyModule_AddType(module, state->keyobject_type) < 0) { + return -1; + } + + state->lru_list_elem_type = (PyTypeObject *)PyType_FromModuleAndSpec( + module, &lru_list_elem_type_spec, NULL); + if (state->lru_list_elem_type == NULL) { + return -1; + } + // lru_list_elem is used only in _lru_cache_wrapper. + // So we don't expose it in module namespace. + + return 0; +} + +static int +_functools_traverse(PyObject *module, visitproc visit, void *arg) +{ + _functools_state *state = get_functools_state(module); + Py_VISIT(state->kwd_mark); + Py_VISIT(state->partial_type); + Py_VISIT(state->keyobject_type); + Py_VISIT(state->lru_list_elem_type); + return 0; +} + +static int +_functools_clear(PyObject *module) +{ + _functools_state *state = get_functools_state(module); + Py_CLEAR(state->kwd_mark); + Py_CLEAR(state->partial_type); + Py_CLEAR(state->keyobject_type); + Py_CLEAR(state->lru_list_elem_type); return 0; } +static void +_functools_free(void *module) +{ + _functools_clear((PyObject *)module); +} + static struct PyModuleDef_Slot _functools_slots[] = { {Py_mod_exec, _functools_exec}, {0, NULL} @@ -1462,14 +1520,14 @@ static struct PyModuleDef_Slot _functools_slots[] = { static struct PyModuleDef _functools_module = { PyModuleDef_HEAD_INIT, - "_functools", - _functools_doc, - 0, - _functools_methods, - _functools_slots, - NULL, - NULL, - _functools_free, + .m_name = "_functools", + .m_doc = _functools_doc, + .m_size = sizeof(_functools_state), + .m_methods = _functools_methods, + .m_slots = _functools_slots, + .m_traverse = _functools_traverse, + .m_clear = _functools_clear, + .m_free = _functools_free, }; PyMODINIT_FUNC diff --git a/contrib/tools/python3/src/Modules/_hashopenssl.c b/contrib/tools/python3/src/Modules/_hashopenssl.c index 4db058c062..65538f63f7 100644 --- a/contrib/tools/python3/src/Modules/_hashopenssl.c +++ b/contrib/tools/python3/src/Modules/_hashopenssl.c @@ -43,51 +43,12 @@ # error "OPENSSL_THREADS is not defined, Python requires thread-safe OpenSSL" #endif -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER) -/* OpenSSL < 1.1.0 */ -#define EVP_MD_CTX_new EVP_MD_CTX_create -#define EVP_MD_CTX_free EVP_MD_CTX_destroy - -HMAC_CTX * -HMAC_CTX_new(void) -{ - HMAC_CTX *ctx = OPENSSL_malloc(sizeof(HMAC_CTX)); - if (ctx != NULL) { - memset(ctx, 0, sizeof(HMAC_CTX)); - HMAC_CTX_init(ctx); - } - return ctx; -} - -void -HMAC_CTX_free(HMAC_CTX *ctx) -{ - if (ctx != NULL) { - HMAC_CTX_cleanup(ctx); - OPENSSL_free(ctx); - } -} - -const EVP_MD * -HMAC_CTX_get_md(const HMAC_CTX *ctx) -{ - return ctx->md; -} -#endif - #define MUNCH_SIZE INT_MAX -#ifdef NID_sha3_224 +#define PY_OPENSSL_HAS_SCRYPT 1 #define PY_OPENSSL_HAS_SHA3 1 -#endif - -#if defined(EVP_MD_FLAG_XOF) && defined(NID_shake128) #define PY_OPENSSL_HAS_SHAKE 1 -#endif - -#if defined(NID_blake2b512) && !defined(OPENSSL_NO_BLAKE2) #define PY_OPENSSL_HAS_BLAKE2 1 -#endif #if OPENSSL_VERSION_NUMBER >= 0x30000000L #define PY_EVP_MD EVP_MD @@ -159,27 +120,19 @@ static const py_hashentry_t py_hashes[] = { PY_HASH_ENTRY(Py_hash_sha384, "SHA384", SN_sha384, NID_sha384), PY_HASH_ENTRY(Py_hash_sha512, "SHA512", SN_sha512, NID_sha512), /* truncated sha2 */ -#ifdef NID_sha512_224 PY_HASH_ENTRY(Py_hash_sha512_224, "SHA512_224", SN_sha512_224, NID_sha512_224), PY_HASH_ENTRY(Py_hash_sha512_256, "SHA512_256", SN_sha512_256, NID_sha512_256), -#endif /* sha3 */ -#ifdef PY_OPENSSL_HAS_SHA3 PY_HASH_ENTRY(Py_hash_sha3_224, NULL, SN_sha3_224, NID_sha3_224), PY_HASH_ENTRY(Py_hash_sha3_256, NULL, SN_sha3_256, NID_sha3_256), PY_HASH_ENTRY(Py_hash_sha3_384, NULL, SN_sha3_384, NID_sha3_384), PY_HASH_ENTRY(Py_hash_sha3_512, NULL, SN_sha3_512, NID_sha3_512), -#endif /* sha3 shake */ -#ifdef PY_OPENSSL_HAS_SHAKE PY_HASH_ENTRY(Py_hash_shake_128, NULL, SN_shake128, NID_shake128), PY_HASH_ENTRY(Py_hash_shake_256, NULL, SN_shake256, NID_shake256), -#endif /* blake2 digest */ -#ifdef PY_OPENSSL_HAS_BLAKE2 PY_HASH_ENTRY(Py_hash_blake2s, "blake2s256", SN_blake2s256, NID_blake2s256), PY_HASH_ENTRY(Py_hash_blake2b, "blake2b512", SN_blake2b512, NID_blake2b512), -#endif PY_HASH_ENTRY(NULL, NULL, NULL, 0), }; @@ -259,6 +212,8 @@ typedef struct { #ifdef PY_OPENSSL_HAS_SHAKE PyTypeObject *EVPXOFtype; #endif + PyObject *constructs; + PyObject *unsupported_digestmod_error; _Py_hashtable_t *hashtable; } _hashlibstate; @@ -334,15 +289,6 @@ _setException(PyObject *exc, const char* altmsg, ...) } /* LCOV_EXCL_STOP */ -/* {Py_tp_new, NULL} doesn't block __new__ */ -static PyObject * -_disabled_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) -{ - PyErr_Format(PyExc_TypeError, - "cannot create '%.100s' instances", _PyType_Name(type)); - return NULL; -} - static PyObject* py_digest_name(const EVP_MD *md) { @@ -420,6 +366,48 @@ py_digest_by_name(PyObject *module, const char *name, enum Py_hash_type py_ht) return digest; } +/* Get digest EVP from object + * + * * string + * * _hashopenssl builtin function + * + * on error returns NULL with exception set. + */ +static PY_EVP_MD* +py_digest_by_digestmod(PyObject *module, PyObject *digestmod, enum Py_hash_type py_ht) { + PY_EVP_MD* evp; + PyObject *name_obj = NULL; + const char *name; + + if (PyUnicode_Check(digestmod)) { + name_obj = digestmod; + } else { + _hashlibstate *state = get_hashlib_state(module); + // borrowed ref + name_obj = PyDict_GetItem(state->constructs, digestmod); + } + if (name_obj == NULL) { + _hashlibstate *state = get_hashlib_state(module); + PyErr_Clear(); + PyErr_Format( + state->unsupported_digestmod_error, + "Unsupported digestmod %R", digestmod); + return NULL; + } + + name = PyUnicode_AsUTF8(name_obj); + if (name == NULL) { + return NULL; + } + + evp = py_digest_by_name(module, name, py_ht); + if (evp == NULL) { + return NULL; + } + + return evp; +} + static EVPobject * newEVPobject(PyTypeObject *type) { @@ -469,7 +457,7 @@ EVP_dealloc(EVPobject *self) if (self->lock != NULL) PyThread_free_lock(self->lock); EVP_MD_CTX_free(self->ctx); - PyObject_Del(self); + PyObject_Free(self); Py_DECREF(tp); } @@ -702,7 +690,6 @@ static PyType_Slot EVPtype_slots[] = { {Py_tp_doc, (char *)hashtype_doc}, {Py_tp_methods, EVP_methods}, {Py_tp_getset, EVP_getseters}, - {Py_tp_new, _disabled_new}, {0, 0}, }; @@ -710,7 +697,7 @@ static PyType_Spec EVPtype_spec = { "_hashlib.HASH", /*tp_name*/ sizeof(EVPobject), /*tp_basicsize*/ 0, /*tp_itemsize*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE, EVPtype_slots }; @@ -852,7 +839,6 @@ static PyType_Slot EVPXOFtype_slots[] = { {Py_tp_doc, (char *)hashxoftype_doc}, {Py_tp_methods, EVPXOF_methods}, {Py_tp_getset, EVPXOF_getseters}, - {Py_tp_new, _disabled_new}, {0, 0}, }; @@ -860,7 +846,7 @@ static PyType_Spec EVPXOFtype_spec = { "_hashlib.HASHXOF", /*tp_name*/ sizeof(EVPobject), /*tp_basicsize*/ 0, /*tp_itemsize*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE, EVPXOFtype_slots }; @@ -887,12 +873,9 @@ py_evp_fromname(PyObject *module, const char *digestname, PyObject *data_obj, goto exit; } -#ifdef PY_OPENSSL_HAS_SHAKE if ((EVP_MD_flags(digest) & EVP_MD_FLAG_XOF) == EVP_MD_FLAG_XOF) { type = get_hashlib_state(module)->EVPXOFtype; - } else -#endif - { + } else { type = get_hashlib_state(module)->EVPtype; } @@ -1238,7 +1221,6 @@ pbkdf2_hmac_impl(PyObject *module, const char *hash_name, PY_EVP_MD *digest = py_digest_by_name(module, hash_name, Py_ht_pbkdf2); if (digest == NULL) { - PyErr_SetString(PyExc_ValueError, "unsupported hash type"); goto end; } @@ -1311,8 +1293,7 @@ pbkdf2_hmac_impl(PyObject *module, const char *hash_name, return key_obj; } -#if OPENSSL_VERSION_NUMBER > 0x10100000L && !defined(OPENSSL_NO_SCRYPT) && !defined(LIBRESSL_VERSION_NUMBER) -#define PY_SCRYPT 1 +#ifdef PY_OPENSSL_HAS_SCRYPT /* XXX: Parameters salt, n, r and p should be required keyword-only parameters. They are optional in the Argument Clinic declaration only due to a @@ -1433,7 +1414,7 @@ _hashlib_scrypt_impl(PyObject *module, Py_buffer *password, Py_buffer *salt, } return key_obj; } -#endif +#endif /* PY_OPENSSL_HAS_SCRYPT */ /* Fast HMAC for hmac.digest() */ @@ -1443,25 +1424,21 @@ _hashlib.hmac_digest as _hashlib_hmac_singleshot key: Py_buffer msg: Py_buffer - digest: str + digest: object Single-shot HMAC. [clinic start generated code]*/ static PyObject * _hashlib_hmac_singleshot_impl(PyObject *module, Py_buffer *key, - Py_buffer *msg, const char *digest) -/*[clinic end generated code: output=15658ede5ab98185 input=019dffc571909a46]*/ + Py_buffer *msg, PyObject *digest) +/*[clinic end generated code: output=82f19965d12706ac input=0a0790cc3db45c2e]*/ { unsigned char md[EVP_MAX_MD_SIZE] = {0}; unsigned int md_len = 0; unsigned char *result; PY_EVP_MD *evp; - evp = py_digest_by_name(module, digest, Py_ht_mac); - if (evp == NULL) { - return NULL; - } if (key->len > INT_MAX) { PyErr_SetString(PyExc_OverflowError, "key is too long."); @@ -1473,7 +1450,7 @@ _hashlib_hmac_singleshot_impl(PyObject *module, Py_buffer *key, return NULL; } - evp = py_digest_by_name(module, digest, Py_ht_mac); + evp = py_digest_by_digestmod(module, digest, Py_ht_mac); if (evp == NULL) { return NULL; } @@ -1505,15 +1482,15 @@ _hashlib.hmac_new key: Py_buffer msg as msg_obj: object(c_default="NULL") = b'' - digestmod: str(c_default="NULL") = None + digestmod: object(c_default="NULL") = None Return a new hmac object. [clinic start generated code]*/ static PyObject * _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, PyObject *msg_obj, - const char *digestmod) -/*[clinic end generated code: output=9a35673be0cbea1b input=a0878868eb190134]*/ + PyObject *digestmod) +/*[clinic end generated code: output=c20d9e4d9ed6d219 input=5f4071dcc7f34362]*/ { PyTypeObject *type = get_hashlib_state(module)->HMACtype; PY_EVP_MD *digest; @@ -1527,14 +1504,14 @@ _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, PyObject *msg_obj, return NULL; } - if ((digestmod == NULL) || !strlen(digestmod)) { + if (digestmod == NULL) { PyErr_SetString( PyExc_TypeError, "Missing required parameter 'digestmod'."); return NULL; } - digest = py_digest_by_name(module, digestmod, Py_ht_mac); - if (!digest) { + digest = py_digest_by_digestmod(module, digestmod, Py_ht_mac); + if (digest == NULL) { return NULL; } @@ -1573,7 +1550,7 @@ _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, PyObject *msg_obj, error: if (ctx) HMAC_CTX_free(ctx); - if (self) PyObject_Del(self); + if (self) PyObject_Free(self); return NULL; } @@ -1668,7 +1645,7 @@ _hmac_dealloc(HMACobject *self) PyThread_free_lock(self->lock); } HMAC_CTX_free(self->ctx); - PyObject_Del(self); + PyObject_Free(self); Py_DECREF(tp); } @@ -1839,14 +1816,13 @@ static PyType_Slot HMACtype_slots[] = { {Py_tp_dealloc,(destructor)_hmac_dealloc}, {Py_tp_methods, HMAC_methods}, {Py_tp_getset, HMAC_getset}, - {Py_tp_new, _disabled_new}, {0, NULL} }; PyType_Spec HMACtype_spec = { "_hashlib.HMAC", /* name */ sizeof(HMACobject), /* basicsize */ - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE, .slots = HMACtype_slots, }; @@ -1860,21 +1836,15 @@ typedef struct _internal_name_mapper_state { /* A callback function to pass to OpenSSL's OBJ_NAME_do_all(...) */ static void -#if OPENSSL_VERSION_NUMBER >= 0x30000000L -_openssl_hash_name_mapper(EVP_MD *md, void *arg) -#else _openssl_hash_name_mapper(const EVP_MD *md, const char *from, const char *to, void *arg) -#endif { _InternalNameMapperState *state = (_InternalNameMapperState *)arg; PyObject *py_name; assert(state != NULL); - // ignore all undefined providers - if ((md == NULL) || (EVP_MD_nid(md) == NID_undef)) { + if (md == NULL) return; - } py_name = py_digest_name(md); if (py_name == NULL) { @@ -1900,12 +1870,7 @@ hashlib_md_meth_names(PyObject *module) return -1; } -#if OPENSSL_VERSION_NUMBER >= 0x30000000L - // get algorithms from all activated providers in default context - EVP_MD_do_all_provided(NULL, &_openssl_hash_name_mapper, &state); -#else EVP_MD_do_all(&_openssl_hash_name_mapper, &state); -#endif if (state.error) { Py_DECREF(state.set); @@ -1920,12 +1885,6 @@ hashlib_md_meth_names(PyObject *module) return 0; } -/* LibreSSL doesn't support FIPS: - https://marc.info/?l=openbsd-misc&m=139819485423701&w=2 - - Ted Unangst wrote: "I figured I should mention our current libressl policy - wrt FIPS mode. It's gone and it's not coming back." */ -#ifndef LIBRESSL_VERSION_NUMBER /*[clinic input] _hashlib.get_fips_mode -> int @@ -1963,7 +1922,6 @@ _hashlib_get_fips_mode_impl(PyObject *module) return result; #endif } -#endif // !LIBRESSL_VERSION_NUMBER static int @@ -2117,6 +2075,8 @@ hashlib_traverse(PyObject *m, visitproc visit, void *arg) #ifdef PY_OPENSSL_HAS_SHAKE Py_VISIT(state->EVPXOFtype); #endif + Py_VISIT(state->constructs); + Py_VISIT(state->unsupported_digestmod_error); return 0; } @@ -2129,10 +2089,14 @@ hashlib_clear(PyObject *m) #ifdef PY_OPENSSL_HAS_SHAKE Py_CLEAR(state->EVPXOFtype); #endif + Py_CLEAR(state->constructs); + Py_CLEAR(state->unsupported_digestmod_error); + if (state->hashtable != NULL) { _Py_hashtable_destroy(state->hashtable); state->hashtable = NULL; } + return 0; } @@ -2144,17 +2108,6 @@ hashlib_free(void *m) /* Py_mod_exec functions */ static int -hashlib_openssl_legacy_init(PyObject *module) -{ -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER) - /* Load all digest algorithms and initialize cpuid */ - OPENSSL_add_all_algorithms_noconf(); - ERR_load_crypto_strings(); -#endif - return 0; -} - -static int hashlib_init_hashtable(PyObject *module) { _hashlibstate *state = get_hashlib_state(module); @@ -2187,21 +2140,14 @@ hashlib_init_evpxoftype(PyObject *module) { #ifdef PY_OPENSSL_HAS_SHAKE _hashlibstate *state = get_hashlib_state(module); - PyObject *bases; if (state->EVPtype == NULL) { return -1; } - bases = PyTuple_Pack(1, state->EVPtype); - if (bases == NULL) { - return -1; - } - state->EVPXOFtype = (PyTypeObject *)PyType_FromSpecWithBases( - &EVPXOFtype_spec, bases + &EVPXOFtype_spec, (PyObject *)state->EVPtype ); - Py_DECREF(bases); if (state->EVPXOFtype == NULL) { return -1; } @@ -2227,18 +2173,89 @@ hashlib_init_hmactype(PyObject *module) return 0; } -#if 0 +static int +hashlib_init_constructors(PyObject *module) +{ + /* Create dict from builtin openssl_hash functions to name + * {_hashlib.openssl_sha256: "sha256", ...} + */ + PyModuleDef *mdef; + PyMethodDef *fdef; + PyObject *proxy; + PyObject *func, *name_obj; + _hashlibstate *state = get_hashlib_state(module); + + mdef = PyModule_GetDef(module); + if (mdef == NULL) { + return -1; + } + + state->constructs = PyDict_New(); + if (state->constructs == NULL) { + return -1; + } + + for (fdef = mdef->m_methods; fdef->ml_name != NULL; fdef++) { + if (strncmp(fdef->ml_name, "openssl_", 8)) { + continue; + } + name_obj = PyUnicode_FromString(fdef->ml_name + 8); + if (name_obj == NULL) { + return -1; + } + func = PyObject_GetAttrString(module, fdef->ml_name); + if (func == NULL) { + Py_DECREF(name_obj); + return -1; + } + int rc = PyDict_SetItem(state->constructs, func, name_obj); + Py_DECREF(func); + Py_DECREF(name_obj); + if (rc < 0) { + return -1; + } + } + + proxy = PyDictProxy_New(state->constructs); + if (proxy == NULL) { + return -1; + } + + int rc = PyModule_AddObjectRef(module, "_constructors", proxy); + Py_DECREF(proxy); + if (rc < 0) { + return -1; + } + return 0; +} + +static int +hashlib_exception(PyObject *module) +{ + _hashlibstate *state = get_hashlib_state(module); + state->unsupported_digestmod_error = PyErr_NewException( + "_hashlib.UnsupportedDigestmodError", PyExc_ValueError, NULL); + if (state->unsupported_digestmod_error == NULL) { + return -1; + } + if (PyModule_AddObjectRef(module, "UnsupportedDigestmodError", + state->unsupported_digestmod_error) < 0) { + return -1; + } + return 0; +} + + static PyModuleDef_Slot hashlib_slots[] = { - /* OpenSSL 1.0.2 and LibreSSL */ - {Py_mod_exec, hashlib_openssl_legacy_init}, {Py_mod_exec, hashlib_init_hashtable}, {Py_mod_exec, hashlib_init_evptype}, {Py_mod_exec, hashlib_init_evpxoftype}, {Py_mod_exec, hashlib_init_hmactype}, {Py_mod_exec, hashlib_md_meth_names}, + {Py_mod_exec, hashlib_init_constructors}, + {Py_mod_exec, hashlib_exception}, {0, NULL} }; -#endif static struct PyModuleDef _hashlibmodule = { PyModuleDef_HEAD_INIT, @@ -2246,7 +2263,7 @@ static struct PyModuleDef _hashlibmodule = { .m_doc = "OpenSSL interface for hashlib module", .m_size = sizeof(_hashlibstate), .m_methods = EVP_functions, - .m_slots = NULL, + .m_slots = hashlib_slots, .m_traverse = hashlib_traverse, .m_clear = hashlib_clear, .m_free = hashlib_free @@ -2255,41 +2272,5 @@ static struct PyModuleDef _hashlibmodule = { PyMODINIT_FUNC PyInit__hashlib(void) { - PyObject *m = PyState_FindModule(&_hashlibmodule); - if (m != NULL) { - Py_INCREF(m); - return m; - } - - m = PyModule_Create(&_hashlibmodule); - if (m == NULL) { - return NULL; - } - - if (hashlib_openssl_legacy_init(m) < 0) { - Py_DECREF(m); - return NULL; - } - if (hashlib_init_hashtable(m) < 0) { - Py_DECREF(m); - return NULL; - } - if (hashlib_init_evptype(m) < 0) { - Py_DECREF(m); - return NULL; - } - if (hashlib_init_evpxoftype(m) < 0) { - Py_DECREF(m); - return NULL; - } - if (hashlib_init_hmactype(m) < 0) { - Py_DECREF(m); - return NULL; - } - if (hashlib_md_meth_names(m) == -1) { - Py_DECREF(m); - return NULL; - } - - return m; + return PyModuleDef_Init(&_hashlibmodule); } diff --git a/contrib/tools/python3/src/Modules/_heapqmodule.c b/contrib/tools/python3/src/Modules/_heapqmodule.c index 4e85e046d3..20468c28f2 100644 --- a/contrib/tools/python3/src/Modules/_heapqmodule.c +++ b/contrib/tools/python3/src/Modules/_heapqmodule.c @@ -7,9 +7,11 @@ annotated by François Pinard, and converted to C by Raymond Hettinger. */ #include "Python.h" +#include "pycore_list.h" // _PyList_ITEMS() #include "clinic/_heapqmodule.c.h" + /*[clinic input] module _heapq [clinic start generated code]*/ @@ -113,7 +115,7 @@ siftup(PyListObject *heap, Py_ssize_t pos) /*[clinic input] _heapq.heappush - heap: object + heap: object(subclass_of='&PyList_Type') item: object / @@ -122,13 +124,8 @@ Push item onto heap, maintaining the heap invariant. static PyObject * _heapq_heappush_impl(PyObject *module, PyObject *heap, PyObject *item) -/*[clinic end generated code: output=912c094f47663935 input=7913545cb5118842]*/ +/*[clinic end generated code: output=912c094f47663935 input=7c69611f3698aceb]*/ { - if (!PyList_Check(heap)) { - PyErr_SetString(PyExc_TypeError, "heap argument must be a list"); - return NULL; - } - if (PyList_Append(heap, item)) return NULL; @@ -143,11 +140,6 @@ heappop_internal(PyObject *heap, int siftup_func(PyListObject *, Py_ssize_t)) PyObject *lastelt, *returnitem; Py_ssize_t n; - if (!PyList_Check(heap)) { - PyErr_SetString(PyExc_TypeError, "heap argument must be a list"); - return NULL; - } - /* raises IndexError if the heap is empty */ n = PyList_GET_SIZE(heap); if (n == 0) { @@ -177,15 +169,15 @@ heappop_internal(PyObject *heap, int siftup_func(PyListObject *, Py_ssize_t)) /*[clinic input] _heapq.heappop - heap: object + heap: object(subclass_of='&PyList_Type') / Pop the smallest item off the heap, maintaining the heap invariant. [clinic start generated code]*/ static PyObject * -_heapq_heappop(PyObject *module, PyObject *heap) -/*[clinic end generated code: output=e1bbbc9866bce179 input=9bd36317b806033d]*/ +_heapq_heappop_impl(PyObject *module, PyObject *heap) +/*[clinic end generated code: output=96dfe82d37d9af76 input=91487987a583c856]*/ { return heappop_internal(heap, siftup); } @@ -195,11 +187,6 @@ heapreplace_internal(PyObject *heap, PyObject *item, int siftup_func(PyListObjec { PyObject *returnitem; - if (!PyList_Check(heap)) { - PyErr_SetString(PyExc_TypeError, "heap argument must be a list"); - return NULL; - } - if (PyList_GET_SIZE(heap) == 0) { PyErr_SetString(PyExc_IndexError, "index out of range"); return NULL; @@ -219,7 +206,7 @@ heapreplace_internal(PyObject *heap, PyObject *item, int siftup_func(PyListObjec /*[clinic input] _heapq.heapreplace - heap: object + heap: object(subclass_of='&PyList_Type') item: object / @@ -236,7 +223,7 @@ this routine unless written as part of a conditional replacement: static PyObject * _heapq_heapreplace_impl(PyObject *module, PyObject *heap, PyObject *item) -/*[clinic end generated code: output=82ea55be8fbe24b4 input=e57ae8f4ecfc88e3]*/ +/*[clinic end generated code: output=82ea55be8fbe24b4 input=719202ac02ba10c8]*/ { return heapreplace_internal(heap, item, siftup); } @@ -244,7 +231,7 @@ _heapq_heapreplace_impl(PyObject *module, PyObject *heap, PyObject *item) /*[clinic input] _heapq.heappushpop - heap: object + heap: object(subclass_of='&PyList_Type') item: object / @@ -256,16 +243,11 @@ a separate call to heappop(). static PyObject * _heapq_heappushpop_impl(PyObject *module, PyObject *heap, PyObject *item) -/*[clinic end generated code: output=67231dc98ed5774f input=eb48c90ba77b2214]*/ +/*[clinic end generated code: output=67231dc98ed5774f input=5dc701f1eb4a4aa7]*/ { PyObject *returnitem; int cmp; - if (!PyList_Check(heap)) { - PyErr_SetString(PyExc_TypeError, "heap argument must be a list"); - return NULL; - } - if (PyList_GET_SIZE(heap) == 0) { Py_INCREF(item); return item; @@ -367,11 +349,6 @@ heapify_internal(PyObject *heap, int siftup_func(PyListObject *, Py_ssize_t)) { Py_ssize_t i, n; - if (!PyList_Check(heap)) { - PyErr_SetString(PyExc_TypeError, "heap argument must be a list"); - return NULL; - } - /* For heaps likely to be bigger than L1 cache, we use the cache friendly heapify function. For smaller heaps that fit entirely in cache, we prefer the simpler algorithm with less branching. @@ -396,15 +373,15 @@ heapify_internal(PyObject *heap, int siftup_func(PyListObject *, Py_ssize_t)) /*[clinic input] _heapq.heapify - heap: object + heap: object(subclass_of='&PyList_Type') / Transform list into a heap, in-place, in O(len(heap)) time. [clinic start generated code]*/ static PyObject * -_heapq_heapify(PyObject *module, PyObject *heap) -/*[clinic end generated code: output=11483f23627c4616 input=872c87504b8de970]*/ +_heapq_heapify_impl(PyObject *module, PyObject *heap) +/*[clinic end generated code: output=e63a636fcf83d6d0 input=53bb7a2166febb73]*/ { return heapify_internal(heap, siftup); } @@ -508,15 +485,15 @@ siftup_max(PyListObject *heap, Py_ssize_t pos) /*[clinic input] _heapq._heappop_max - heap: object + heap: object(subclass_of='&PyList_Type') / Maxheap variant of heappop. [clinic start generated code]*/ static PyObject * -_heapq__heappop_max(PyObject *module, PyObject *heap) -/*[clinic end generated code: output=acd30acf6384b13c input=62ede3ba9117f541]*/ +_heapq__heappop_max_impl(PyObject *module, PyObject *heap) +/*[clinic end generated code: output=9e77aadd4e6a8760 input=362c06e1c7484793]*/ { return heappop_internal(heap, siftup_max); } @@ -524,7 +501,7 @@ _heapq__heappop_max(PyObject *module, PyObject *heap) /*[clinic input] _heapq._heapreplace_max - heap: object + heap: object(subclass_of='&PyList_Type') item: object / @@ -534,7 +511,7 @@ Maxheap variant of heapreplace. static PyObject * _heapq__heapreplace_max_impl(PyObject *module, PyObject *heap, PyObject *item) -/*[clinic end generated code: output=8ad7545e4a5e8adb input=6d8f25131e0f0e5f]*/ +/*[clinic end generated code: output=8ad7545e4a5e8adb input=f2dd27cbadb948d7]*/ { return heapreplace_internal(heap, item, siftup_max); } @@ -542,15 +519,15 @@ _heapq__heapreplace_max_impl(PyObject *module, PyObject *heap, /*[clinic input] _heapq._heapify_max - heap: object + heap: object(subclass_of='&PyList_Type') / Maxheap variant of heapify. [clinic start generated code]*/ static PyObject * -_heapq__heapify_max(PyObject *module, PyObject *heap) -/*[clinic end generated code: output=1c6bb6b60d6a2133 input=cdfcc6835b14110d]*/ +_heapq__heapify_max_impl(PyObject *module, PyObject *heap) +/*[clinic end generated code: output=2cb028beb4a8b65e input=c1f765ee69f124b8]*/ { return heapify_internal(heap, siftup_max); } diff --git a/contrib/tools/python3/src/Modules/_io/_iomodule.c b/contrib/tools/python3/src/Modules/_io/_iomodule.c index d7cadacea1..170dea41e8 100644 --- a/contrib/tools/python3/src/Modules/_io/_iomodule.c +++ b/contrib/tools/python3/src/Modules/_io/_iomodule.c @@ -10,6 +10,7 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" #include "_iomodule.h" +#include "pycore_pystate.h" // _PyInterpreterState_GET() #ifdef HAVE_SYS_TYPES_H #include <sys/types.h> @@ -33,6 +34,7 @@ PyObject *_PyIO_str_fileno = NULL; PyObject *_PyIO_str_flush = NULL; PyObject *_PyIO_str_getstate = NULL; PyObject *_PyIO_str_isatty = NULL; +PyObject *_PyIO_str_locale = NULL; PyObject *_PyIO_str_newlines = NULL; PyObject *_PyIO_str_nl = NULL; PyObject *_PyIO_str_peek = NULL; @@ -504,6 +506,45 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode, return NULL; } + +/*[clinic input] +_io.text_encoding + encoding: object + stacklevel: int = 2 + / + +A helper function to choose the text encoding. + +When encoding is not None, just return it. +Otherwise, return the default text encoding (i.e. "locale"). + +This function emits an EncodingWarning if encoding is None and +sys.flags.warn_default_encoding is true. + +This can be used in APIs with an encoding=None parameter. +However, please consider using encoding="utf-8" for new APIs. +[clinic start generated code]*/ + +static PyObject * +_io_text_encoding_impl(PyObject *module, PyObject *encoding, int stacklevel) +/*[clinic end generated code: output=91b2cfea6934cc0c input=bf70231213e2a7b4]*/ +{ + if (encoding == NULL || encoding == Py_None) { + PyInterpreterState *interp = _PyInterpreterState_GET(); + if (_PyInterpreterState_GetConfig(interp)->warn_default_encoding) { + if (PyErr_WarnEx(PyExc_EncodingWarning, + "'encoding' argument not specified", stacklevel)) { + return NULL; + } + } + Py_INCREF(_PyIO_str_locale); + return _PyIO_str_locale; + } + Py_INCREF(encoding); + return encoding; +} + + /*[clinic input] _io.open_code @@ -532,7 +573,7 @@ PyNumber_AsOff_t(PyObject *item, PyObject *err) { Py_off_t result; PyObject *runerr; - PyObject *value = PyNumber_Index(item); + PyObject *value = _PyNumber_Index(item); if (value == NULL) return -1; @@ -593,39 +634,12 @@ _PyIO_get_module_state(void) return state; } -PyObject * -_PyIO_get_locale_module(_PyIO_State *state) -{ - PyObject *mod; - if (state->locale_module != NULL) { - assert(PyWeakref_CheckRef(state->locale_module)); - mod = PyWeakref_GET_OBJECT(state->locale_module); - if (mod != Py_None) { - Py_INCREF(mod); - return mod; - } - Py_CLEAR(state->locale_module); - } - mod = PyImport_ImportModule("_bootlocale"); - if (mod == NULL) - return NULL; - state->locale_module = PyWeakref_NewRef(mod, NULL); - if (state->locale_module == NULL) { - Py_DECREF(mod); - return NULL; - } - return mod; -} - - static int iomodule_traverse(PyObject *mod, visitproc visit, void *arg) { _PyIO_State *state = get_io_state(mod); if (!state->initialized) return 0; - if (state->locale_module != NULL) { - Py_VISIT(state->locale_module); - } + Py_VISIT(state->locale_module); Py_VISIT(state->unsupported_operation); return 0; } @@ -656,6 +670,7 @@ iomodule_free(PyObject *mod) { static PyMethodDef module_methods[] = { _IO_OPEN_METHODDEF + _IO_TEXT_ENCODING_METHODDEF _IO_OPEN_CODE_METHODDEF {NULL, NULL} }; @@ -774,6 +789,7 @@ PyInit__io(void) ADD_INTERNED(flush) ADD_INTERNED(getstate) ADD_INTERNED(isatty) + ADD_INTERNED(locale) ADD_INTERNED(newlines) ADD_INTERNED(peek) ADD_INTERNED(read) diff --git a/contrib/tools/python3/src/Modules/_io/_iomodule.h b/contrib/tools/python3/src/Modules/_io/_iomodule.h index a8f3951e57..638797fd35 100644 --- a/contrib/tools/python3/src/Modules/_io/_iomodule.h +++ b/contrib/tools/python3/src/Modules/_io/_iomodule.h @@ -150,7 +150,6 @@ typedef struct { #define IO_STATE() _PyIO_get_module_state() extern _PyIO_State *_PyIO_get_module_state(void); -extern PyObject *_PyIO_get_locale_module(_PyIO_State *); #ifdef MS_WINDOWS extern char _PyIO_get_console_type(PyObject *); diff --git a/contrib/tools/python3/src/Modules/_io/bufferedio.c b/contrib/tools/python3/src/Modules/_io/bufferedio.c index b0fe9e4589..ba966f568b 100644 --- a/contrib/tools/python3/src/Modules/_io/bufferedio.c +++ b/contrib/tools/python3/src/Modules/_io/bufferedio.c @@ -1485,6 +1485,15 @@ _bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len) } n = PyNumber_AsSsize_t(res, PyExc_ValueError); Py_DECREF(res); + + if (n == -1 && PyErr_Occurred()) { + _PyErr_FormatFromCause( + PyExc_OSError, + "raw readinto() failed" + ); + return -1; + } + if (n < 0 || n > len) { PyErr_Format(PyExc_OSError, "raw readinto() returned invalid length %zd " diff --git a/contrib/tools/python3/src/Modules/_io/clinic/_iomodule.c.h b/contrib/tools/python3/src/Modules/_io/clinic/_iomodule.c.h index 1a9651d340..91c55b1816 100644 --- a/contrib/tools/python3/src/Modules/_io/clinic/_iomodule.c.h +++ b/contrib/tools/python3/src/Modules/_io/clinic/_iomodule.c.h @@ -178,11 +178,6 @@ _io_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw } } if (args[2]) { - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } buffering = _PyLong_AsInt(args[2]); if (buffering == -1 && PyErr_Occurred()) { goto exit; @@ -261,11 +256,6 @@ _io_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw } } if (args[6]) { - if (PyFloat_Check(args[6])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } closefd = _PyLong_AsInt(args[6]); if (closefd == -1 && PyErr_Occurred()) { goto exit; @@ -282,6 +272,52 @@ exit: return return_value; } +PyDoc_STRVAR(_io_text_encoding__doc__, +"text_encoding($module, encoding, stacklevel=2, /)\n" +"--\n" +"\n" +"A helper function to choose the text encoding.\n" +"\n" +"When encoding is not None, just return it.\n" +"Otherwise, return the default text encoding (i.e. \"locale\").\n" +"\n" +"This function emits an EncodingWarning if encoding is None and\n" +"sys.flags.warn_default_encoding is true.\n" +"\n" +"This can be used in APIs with an encoding=None parameter.\n" +"However, please consider using encoding=\"utf-8\" for new APIs."); + +#define _IO_TEXT_ENCODING_METHODDEF \ + {"text_encoding", (PyCFunction)(void(*)(void))_io_text_encoding, METH_FASTCALL, _io_text_encoding__doc__}, + +static PyObject * +_io_text_encoding_impl(PyObject *module, PyObject *encoding, int stacklevel); + +static PyObject * +_io_text_encoding(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *encoding; + int stacklevel = 2; + + if (!_PyArg_CheckPositional("text_encoding", nargs, 1, 2)) { + goto exit; + } + encoding = args[0]; + if (nargs < 2) { + goto skip_optional; + } + stacklevel = _PyLong_AsInt(args[1]); + if (stacklevel == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = _io_text_encoding_impl(module, encoding, stacklevel); + +exit: + return return_value; +} + PyDoc_STRVAR(_io_open_code__doc__, "open_code($module, /, path)\n" "--\n" @@ -323,4 +359,4 @@ _io_open_code(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec exit: return return_value; } -/*[clinic end generated code: output=3df6bc6d91697545 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=06e055d1d80b835d input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/_io/clinic/bufferedio.c.h b/contrib/tools/python3/src/Modules/_io/clinic/bufferedio.c.h index 56d6332a25..19543fdf79 100644 --- a/contrib/tools/python3/src/Modules/_io/clinic/bufferedio.c.h +++ b/contrib/tools/python3/src/Modules/_io/clinic/bufferedio.c.h @@ -120,14 +120,9 @@ _io__Buffered_peek(buffered *self, PyObject *const *args, Py_ssize_t nargs) if (nargs < 1) { goto skip_optional; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[0]); + PyObject *iobj = _PyNumber_Index(args[0]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -200,14 +195,9 @@ _io__Buffered_read1(buffered *self, PyObject *const *args, Py_ssize_t nargs) if (nargs < 1) { goto skip_optional; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[0]); + PyObject *iobj = _PyNumber_Index(args[0]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -356,11 +346,6 @@ _io__Buffered_seek(buffered *self, PyObject *const *args, Py_ssize_t nargs) if (nargs < 2) { goto skip_optional; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } whence = _PyLong_AsInt(args[1]); if (whence == -1 && PyErr_Occurred()) { goto exit; @@ -434,14 +419,9 @@ _io_BufferedReader___init__(PyObject *self, PyObject *args, PyObject *kwargs) if (!noptargs) { goto skip_optional_pos; } - if (PyFloat_Check(fastargs[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(fastargs[1]); + PyObject *iobj = _PyNumber_Index(fastargs[1]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -493,14 +473,9 @@ _io_BufferedWriter___init__(PyObject *self, PyObject *args, PyObject *kwargs) if (!noptargs) { goto skip_optional_pos; } - if (PyFloat_Check(fastargs[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(fastargs[1]); + PyObject *iobj = _PyNumber_Index(fastargs[1]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -590,14 +565,9 @@ _io_BufferedRWPair___init__(PyObject *self, PyObject *args, PyObject *kwargs) if (PyTuple_GET_SIZE(args) < 3) { goto skip_optional; } - if (PyFloat_Check(PyTuple_GET_ITEM(args, 2))) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(PyTuple_GET_ITEM(args, 2)); + PyObject *iobj = _PyNumber_Index(PyTuple_GET_ITEM(args, 2)); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -649,14 +619,9 @@ _io_BufferedRandom___init__(PyObject *self, PyObject *args, PyObject *kwargs) if (!noptargs) { goto skip_optional_pos; } - if (PyFloat_Check(fastargs[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(fastargs[1]); + PyObject *iobj = _PyNumber_Index(fastargs[1]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -672,4 +637,4 @@ skip_optional_pos: exit: return return_value; } -/*[clinic end generated code: output=7d9ad40c95bdd808 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=98ccf7610c0e82ba input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/_io/clinic/bytesio.c.h b/contrib/tools/python3/src/Modules/_io/clinic/bytesio.c.h index 83cd490dc5..5ea80ae01c 100644 --- a/contrib/tools/python3/src/Modules/_io/clinic/bytesio.c.h +++ b/contrib/tools/python3/src/Modules/_io/clinic/bytesio.c.h @@ -402,14 +402,9 @@ _io_BytesIO_seek(bytesio *self, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("seek", nargs, 1, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[0]); + PyObject *iobj = _PyNumber_Index(args[0]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -422,11 +417,6 @@ _io_BytesIO_seek(bytesio *self, PyObject *const *args, Py_ssize_t nargs) if (nargs < 2) { goto skip_optional; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } whence = _PyLong_AsInt(args[1]); if (whence == -1 && PyErr_Occurred()) { goto exit; @@ -515,4 +505,4 @@ skip_optional_pos: exit: return return_value; } -/*[clinic end generated code: output=4ec2506def9c8eb9 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=49a32140eb8c5555 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/_io/clinic/fileio.c.h b/contrib/tools/python3/src/Modules/_io/clinic/fileio.c.h index 53e7067cf7..9b237c156d 100644 --- a/contrib/tools/python3/src/Modules/_io/clinic/fileio.c.h +++ b/contrib/tools/python3/src/Modules/_io/clinic/fileio.c.h @@ -87,11 +87,6 @@ _io_FileIO___init__(PyObject *self, PyObject *args, PyObject *kwargs) } } if (fastargs[2]) { - if (PyFloat_Check(fastargs[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } closefd = _PyLong_AsInt(fastargs[2]); if (closefd == -1 && PyErr_Occurred()) { goto exit; @@ -351,11 +346,6 @@ _io_FileIO_seek(fileio *self, PyObject *const *args, Py_ssize_t nargs) if (nargs < 2) { goto skip_optional; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } whence = _PyLong_AsInt(args[1]); if (whence == -1 && PyErr_Occurred()) { goto exit; @@ -447,4 +437,4 @@ _io_FileIO_isatty(fileio *self, PyObject *Py_UNUSED(ignored)) #ifndef _IO_FILEIO_TRUNCATE_METHODDEF #define _IO_FILEIO_TRUNCATE_METHODDEF #endif /* !defined(_IO_FILEIO_TRUNCATE_METHODDEF) */ -/*[clinic end generated code: output=e7682d0a3264d284 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3479912ec0f7e029 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/_io/clinic/iobase.c.h b/contrib/tools/python3/src/Modules/_io/clinic/iobase.c.h index ddaff7b5d1..4fd6e18c4e 100644 --- a/contrib/tools/python3/src/Modules/_io/clinic/iobase.c.h +++ b/contrib/tools/python3/src/Modules/_io/clinic/iobase.c.h @@ -274,14 +274,9 @@ _io__RawIOBase_read(PyObject *self, PyObject *const *args, Py_ssize_t nargs) if (nargs < 1) { goto skip_optional; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[0]); + PyObject *iobj = _PyNumber_Index(args[0]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -315,4 +310,4 @@ _io__RawIOBase_readall(PyObject *self, PyObject *Py_UNUSED(ignored)) { return _io__RawIOBase_readall_impl(self); } -/*[clinic end generated code: output=61b6ea7153ef9940 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=83c1361a7a51ca84 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/_io/clinic/stringio.c.h b/contrib/tools/python3/src/Modules/_io/clinic/stringio.c.h index 77a720c2a6..147ef668a0 100644 --- a/contrib/tools/python3/src/Modules/_io/clinic/stringio.c.h +++ b/contrib/tools/python3/src/Modules/_io/clinic/stringio.c.h @@ -177,14 +177,9 @@ _io_StringIO_seek(stringio *self, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("seek", nargs, 1, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[0]); + PyObject *iobj = _PyNumber_Index(args[0]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -197,11 +192,6 @@ _io_StringIO_seek(stringio *self, PyObject *const *args, Py_ssize_t nargs) if (nargs < 2) { goto skip_optional; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } whence = _PyLong_AsInt(args[1]); if (whence == -1 && PyErr_Occurred()) { goto exit; @@ -348,4 +338,4 @@ _io_StringIO_seekable(stringio *self, PyObject *Py_UNUSED(ignored)) { return _io_StringIO_seekable_impl(self); } -/*[clinic end generated code: output=7aad5ab2e64a25b8 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=eea93dcab10d0a97 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/_io/clinic/textio.c.h b/contrib/tools/python3/src/Modules/_io/clinic/textio.c.h index b8b507543e..0b047ac0aa 100644 --- a/contrib/tools/python3/src/Modules/_io/clinic/textio.c.h +++ b/contrib/tools/python3/src/Modules/_io/clinic/textio.c.h @@ -39,11 +39,6 @@ _io_IncrementalNewlineDecoder___init__(PyObject *self, PyObject *args, PyObject goto exit; } decoder = fastargs[0]; - if (PyFloat_Check(fastargs[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } translate = _PyLong_AsInt(fastargs[1]); if (translate == -1 && PyErr_Occurred()) { goto exit; @@ -90,11 +85,6 @@ _io_IncrementalNewlineDecoder_decode(nldecoder_object *self, PyObject *const *ar if (!noptargs) { goto skip_optional_pos; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } final = _PyLong_AsInt(args[1]); if (final == -1 && PyErr_Occurred()) { goto exit; @@ -266,11 +256,6 @@ _io_TextIOWrapper___init__(PyObject *self, PyObject *args, PyObject *kwargs) } } if (fastargs[4]) { - if (PyFloat_Check(fastargs[4])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } line_buffering = _PyLong_AsInt(fastargs[4]); if (line_buffering == -1 && PyErr_Occurred()) { goto exit; @@ -279,11 +264,6 @@ _io_TextIOWrapper___init__(PyObject *self, PyObject *args, PyObject *kwargs) goto skip_optional_pos; } } - if (PyFloat_Check(fastargs[5])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } write_through = _PyLong_AsInt(fastargs[5]); if (write_through == -1 && PyErr_Occurred()) { goto exit; @@ -470,14 +450,9 @@ _io_TextIOWrapper_readline(textio *self, PyObject *const *args, Py_ssize_t nargs if (nargs < 1) { goto skip_optional; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[0]); + PyObject *iobj = _PyNumber_Index(args[0]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -519,11 +494,6 @@ _io_TextIOWrapper_seek(textio *self, PyObject *const *args, Py_ssize_t nargs) if (nargs < 2) { goto skip_optional; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } whence = _PyLong_AsInt(args[1]); if (whence == -1 && PyErr_Occurred()) { goto exit; @@ -701,4 +671,4 @@ _io_TextIOWrapper_close(textio *self, PyObject *Py_UNUSED(ignored)) { return _io_TextIOWrapper_close_impl(self); } -/*[clinic end generated code: output=b1bae4f4cdf6019e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2604c8f3a45b9a03 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/_io/clinic/winconsoleio.c.h b/contrib/tools/python3/src/Modules/_io/clinic/winconsoleio.c.h index 3e501a5853..84e73dcaf7 100644 --- a/contrib/tools/python3/src/Modules/_io/clinic/winconsoleio.c.h +++ b/contrib/tools/python3/src/Modules/_io/clinic/winconsoleio.c.h @@ -8,10 +8,10 @@ PyDoc_STRVAR(_io__WindowsConsoleIO_close__doc__, "close($self, /)\n" "--\n" "\n" -"Close the handle.\n" +"Close the console object.\n" "\n" -"A closed handle cannot be used for further I/O operations. close() may be\n" -"called more than once without error."); +"A closed console object cannot be used for further I/O operations.\n" +"close() may be called more than once without error."); #define _IO__WINDOWSCONSOLEIO_CLOSE_METHODDEF \ {"close", (PyCFunction)_io__WindowsConsoleIO_close, METH_NOARGS, _io__WindowsConsoleIO_close__doc__}, @@ -86,11 +86,6 @@ _io__WindowsConsoleIO___init__(PyObject *self, PyObject *args, PyObject *kwargs) } } if (fastargs[2]) { - if (PyFloat_Check(fastargs[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } closefd = _PyLong_AsInt(fastargs[2]); if (closefd == -1 && PyErr_Occurred()) { goto exit; @@ -115,10 +110,7 @@ PyDoc_STRVAR(_io__WindowsConsoleIO_fileno__doc__, "fileno($self, /)\n" "--\n" "\n" -"Return the underlying file descriptor (an integer).\n" -"\n" -"fileno is only set when a file descriptor is used to open\n" -"one of the standard streams."); +"Return the underlying file descriptor (an integer)."); #define _IO__WINDOWSCONSOLEIO_FILENO_METHODDEF \ {"fileno", (PyCFunction)_io__WindowsConsoleIO_fileno, METH_NOARGS, _io__WindowsConsoleIO_fileno__doc__}, @@ -386,4 +378,4 @@ _io__WindowsConsoleIO_isatty(winconsoleio *self, PyObject *Py_UNUSED(ignored)) #ifndef _IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF #define _IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF #endif /* !defined(_IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF) */ -/*[clinic end generated code: output=f5b8860a658a001a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=48080572ffee22f5 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/_io/fileio.c b/contrib/tools/python3/src/Modules/_io/fileio.c index 048484bde5..b9856b3b63 100644 --- a/contrib/tools/python3/src/Modules/_io/fileio.c +++ b/contrib/tools/python3/src/Modules/_io/fileio.c @@ -255,12 +255,6 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode, self->fd = -1; } - if (PyFloat_Check(nameobj)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float"); - return -1; - } - fd = _PyLong_AsInt(nameobj); if (fd < 0) { if (!PyErr_Occurred()) { @@ -276,10 +270,14 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode, if (!PyUnicode_FSDecoder(nameobj, &stringobj)) { return -1; } +#if USE_UNICODE_WCHAR_CACHE _Py_COMP_DIAG_PUSH _Py_COMP_DIAG_IGNORE_DEPR_DECLS widename = PyUnicode_AsUnicode(stringobj); _Py_COMP_DIAG_POP +#else /* USE_UNICODE_WCHAR_CACHE */ + widename = PyUnicode_AsWideCharString(stringobj, NULL); +#endif /* USE_UNICODE_WCHAR_CACHE */ if (widename == NULL) return -1; #else @@ -500,6 +498,11 @@ _Py_COMP_DIAG_POP internal_close(self); done: +#ifdef MS_WINDOWS +#if !USE_UNICODE_WCHAR_CACHE + PyMem_Free(widename); +#endif /* USE_UNICODE_WCHAR_CACHE */ +#endif Py_CLEAR(stringobj); return ret; } @@ -898,10 +901,6 @@ portable_lseek(fileio *self, PyObject *posobj, int whence, bool suppress_pipe_er pos = 0; } else { - if(PyFloat_Check(posobj)) { - PyErr_SetString(PyExc_TypeError, "an integer is required"); - return NULL; - } #if defined(HAVE_LARGEFILE_SUPPORT) pos = PyLong_AsLongLong(posobj); #else diff --git a/contrib/tools/python3/src/Modules/_io/iobase.c b/contrib/tools/python3/src/Modules/_io/iobase.c index 0f150a3583..4c81befebd 100644 --- a/contrib/tools/python3/src/Modules/_io/iobase.c +++ b/contrib/tools/python3/src/Modules/_io/iobase.c @@ -10,6 +10,7 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" +#include "pycore_long.h" // _PyLong_GetOne() #include "pycore_object.h" #include <stddef.h> // offsetof() #include "_iomodule.h" @@ -348,8 +349,9 @@ iobase_dealloc(iobase *self) if (_PyIOBase_finalize((PyObject *) self) < 0) { /* When called from a heap type's dealloc, the type will be decref'ed on return (see e.g. subtype_dealloc in typeobject.c). */ - if (PyType_HasFeature(Py_TYPE(self), Py_TPFLAGS_HEAPTYPE)) + if (_PyType_HasFeature(Py_TYPE(self), Py_TPFLAGS_HEAPTYPE)) { Py_INCREF(Py_TYPE(self)); + } return; } _PyObject_GC_UNTRACK(self); @@ -554,7 +556,7 @@ _io__IOBase_readline_impl(PyObject *self, Py_ssize_t limit) PyObject *b; if (peek != NULL) { - PyObject *readahead = PyObject_CallOneArg(peek, _PyLong_One); + PyObject *readahead = PyObject_CallOneArg(peek, _PyLong_GetOne()); if (readahead == NULL) { /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR occurs so we needn't do it ourselves. */ diff --git a/contrib/tools/python3/src/Modules/_io/textio.c b/contrib/tools/python3/src/Modules/_io/textio.c index f9903e2500..e28dbaa7b7 100644 --- a/contrib/tools/python3/src/Modules/_io/textio.c +++ b/contrib/tools/python3/src/Modules/_io/textio.c @@ -9,6 +9,8 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" #include "pycore_interp.h" // PyInterpreterState.fs_codec +#include "pycore_long.h" // _PyLong_GetZero() +#include "pycore_fileutils.h" // _Py_GetLocaleEncoding() #include "pycore_object.h" #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "structmember.h" // PyMemberDef @@ -26,7 +28,6 @@ _Py_IDENTIFIER(_dealloc_warn); _Py_IDENTIFIER(decode); _Py_IDENTIFIER(fileno); _Py_IDENTIFIER(flush); -_Py_IDENTIFIER(getpreferredencoding); _Py_IDENTIFIER(isatty); _Py_IDENTIFIER(mode); _Py_IDENTIFIER(name); @@ -971,7 +972,7 @@ _textiowrapper_fix_encoder_state(textio *self) return -1; } - int cmp = PyObject_RichCompareBool(cookieObj, _PyLong_Zero, Py_EQ); + int cmp = PyObject_RichCompareBool(cookieObj, _PyLong_GetZero(), Py_EQ); Py_DECREF(cookieObj); if (cmp < 0) { return -1; @@ -980,7 +981,7 @@ _textiowrapper_fix_encoder_state(textio *self) if (cmp == 0) { self->encoding_start_of_stream = 0; PyObject *res = PyObject_CallMethodOneArg( - self->encoder, _PyIO_str_setstate, _PyLong_Zero); + self->encoder, _PyIO_str_setstate, _PyLong_GetZero()); if (res == NULL) { return -1; } @@ -1084,6 +1085,19 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, self->ok = 0; self->detached = 0; + if (encoding == NULL) { + PyInterpreterState *interp = _PyInterpreterState_GET(); + if (_PyInterpreterState_GetConfig(interp)->warn_default_encoding) { + if (PyErr_WarnEx(PyExc_EncodingWarning, + "'encoding' argument not specified", 1)) { + return -1; + } + } + } + else if (strcmp(encoding, "locale") == 0) { + encoding = NULL; + } + if (errors == Py_None) { errors = _PyUnicode_FromId(&PyId_strict); /* borrowed */ if (errors == NULL) { @@ -1154,29 +1168,11 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, } } if (encoding == NULL && self->encoding == NULL) { - PyObject *locale_module = _PyIO_get_locale_module(state); - if (locale_module == NULL) - goto catch_ImportError; - self->encoding = _PyObject_CallMethodIdOneArg( - locale_module, &PyId_getpreferredencoding, Py_False); - Py_DECREF(locale_module); + self->encoding = _Py_GetLocaleEncodingObject(); if (self->encoding == NULL) { - catch_ImportError: - /* - Importing locale can raise an ImportError because of - _functools, and locale.getpreferredencoding can raise an - ImportError if _locale is not available. These will happen - during module building. - */ - if (PyErr_ExceptionMatches(PyExc_ImportError)) { - PyErr_Clear(); - self->encoding = PyUnicode_FromString("ascii"); - } - else - goto error; + goto error; } - else if (!PyUnicode_Check(self->encoding)) - Py_CLEAR(self->encoding); + assert(PyUnicode_Check(self->encoding)); } if (self->encoding != NULL) { encoding = PyUnicode_AsUTF8(self->encoding); @@ -2429,7 +2425,7 @@ _textiowrapper_encoder_reset(textio *self, int start_of_stream) } else { res = PyObject_CallMethodOneArg(self->encoder, _PyIO_str_setstate, - _PyLong_Zero); + _PyLong_GetZero()); self->encoding_start_of_stream = 0; } if (res == NULL) @@ -2473,10 +2469,12 @@ _io_TextIOWrapper_seek_impl(textio *self, PyObject *cookieObj, int whence) goto fail; } + PyObject *zero = _PyLong_GetZero(); // borrowed reference + switch (whence) { case SEEK_CUR: /* seek relative to current position */ - cmp = PyObject_RichCompareBool(cookieObj, _PyLong_Zero, Py_EQ); + cmp = PyObject_RichCompareBool(cookieObj, zero, Py_EQ); if (cmp < 0) goto fail; @@ -2496,7 +2494,7 @@ _io_TextIOWrapper_seek_impl(textio *self, PyObject *cookieObj, int whence) case SEEK_END: /* seek relative to end of file */ - cmp = PyObject_RichCompareBool(cookieObj, _PyLong_Zero, Py_EQ); + cmp = PyObject_RichCompareBool(cookieObj, zero, Py_EQ); if (cmp < 0) goto fail; @@ -2525,7 +2523,7 @@ _io_TextIOWrapper_seek_impl(textio *self, PyObject *cookieObj, int whence) goto fail; if (self->encoder) { /* If seek() == 0, we are at the start of stream, otherwise not */ - cmp = PyObject_RichCompareBool(res, _PyLong_Zero, Py_EQ); + cmp = PyObject_RichCompareBool(res, zero, Py_EQ); if (cmp < 0 || _textiowrapper_encoder_reset(self, cmp)) { Py_DECREF(res); goto fail; @@ -2543,7 +2541,7 @@ _io_TextIOWrapper_seek_impl(textio *self, PyObject *cookieObj, int whence) goto fail; } - cmp = PyObject_RichCompareBool(cookieObj, _PyLong_Zero, Py_LT); + cmp = PyObject_RichCompareBool(cookieObj, zero, Py_LT); if (cmp < 0) goto fail; diff --git a/contrib/tools/python3/src/Modules/_io/winconsoleio.c b/contrib/tools/python3/src/Modules/_io/winconsoleio.c index a83ef37a1f..460f2d3fa0 100644 --- a/contrib/tools/python3/src/Modules/_io/winconsoleio.c +++ b/contrib/tools/python3/src/Modules/_io/winconsoleio.c @@ -64,10 +64,7 @@ char _PyIO_get_console_type(PyObject *path_or_fd) { int fd = PyLong_AsLong(path_or_fd); PyErr_Clear(); if (fd >= 0) { - HANDLE handle; - _Py_BEGIN_SUPPRESS_IPH - handle = (HANDLE)_get_osfhandle(fd); - _Py_END_SUPPRESS_IPH + HANDLE handle = _Py_get_osfhandle_noraise(fd); if (handle == INVALID_HANDLE_VALUE) return '\0'; return _get_console_type(handle); @@ -143,12 +140,11 @@ class _io._WindowsConsoleIO "winconsoleio *" "&PyWindowsConsoleIO_Type" typedef struct { PyObject_HEAD - HANDLE handle; int fd; unsigned int created : 1; unsigned int readable : 1; unsigned int writable : 1; - unsigned int closehandle : 1; + unsigned int closefd : 1; char finalizing; unsigned int blksize; PyObject *weakreflist; @@ -164,7 +160,7 @@ _Py_IDENTIFIER(name); int _PyWindowsConsoleIO_closed(PyObject *self) { - return ((winconsoleio *)self)->handle == INVALID_HANDLE_VALUE; + return ((winconsoleio *)self)->fd == -1; } @@ -172,16 +168,12 @@ _PyWindowsConsoleIO_closed(PyObject *self) static int internal_close(winconsoleio *self) { - if (self->handle != INVALID_HANDLE_VALUE) { - if (self->closehandle) { - if (self->fd >= 0) { - _Py_BEGIN_SUPPRESS_IPH - close(self->fd); - _Py_END_SUPPRESS_IPH - } - CloseHandle(self->handle); + if (self->fd != -1) { + if (self->closefd) { + _Py_BEGIN_SUPPRESS_IPH + close(self->fd); + _Py_END_SUPPRESS_IPH } - self->handle = INVALID_HANDLE_VALUE; self->fd = -1; } return 0; @@ -190,15 +182,15 @@ internal_close(winconsoleio *self) /*[clinic input] _io._WindowsConsoleIO.close -Close the handle. +Close the console object. -A closed handle cannot be used for further I/O operations. close() may be -called more than once without error. +A closed console object cannot be used for further I/O operations. +close() may be called more than once without error. [clinic start generated code]*/ static PyObject * _io__WindowsConsoleIO_close_impl(winconsoleio *self) -/*[clinic end generated code: output=27ef95b66c29057b input=185617e349ae4c7b]*/ +/*[clinic end generated code: output=27ef95b66c29057b input=68c4e5754f8136c2]*/ { PyObject *res; PyObject *exc, *val, *tb; @@ -206,8 +198,8 @@ _io__WindowsConsoleIO_close_impl(winconsoleio *self) _Py_IDENTIFIER(close); res = _PyObject_CallMethodIdOneArg((PyObject*)&PyRawIOBase_Type, &PyId_close, (PyObject*)self); - if (!self->closehandle) { - self->handle = INVALID_HANDLE_VALUE; + if (!self->closefd) { + self->fd = -1; return res; } if (res == NULL) @@ -229,12 +221,11 @@ winconsoleio_new(PyTypeObject *type, PyObject *args, PyObject *kwds) self = (winconsoleio *) type->tp_alloc(type, 0); if (self != NULL) { - self->handle = INVALID_HANDLE_VALUE; self->fd = -1; self->created = 0; self->readable = 0; self->writable = 0; - self->closehandle = 0; + self->closefd = 0; self->blksize = 0; self->weakreflist = NULL; } @@ -269,22 +260,17 @@ _io__WindowsConsoleIO___init___impl(winconsoleio *self, PyObject *nameobj, int rwa = 0; int fd = -1; int fd_is_own = 0; + HANDLE handle = NULL; assert(PyWindowsConsoleIO_Check(self)); - if (self->handle >= 0) { - if (self->closehandle) { + if (self->fd >= 0) { + if (self->closefd) { /* Have to close the existing file first. */ if (internal_close(self) < 0) return -1; } else - self->handle = INVALID_HANDLE_VALUE; - } - - if (PyFloat_Check(nameobj)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float"); - return -1; + self->fd = -1; } fd = _PyLong_AsInt(nameobj); @@ -347,14 +333,12 @@ _io__WindowsConsoleIO___init___impl(winconsoleio *self, PyObject *nameobj, goto bad_mode; if (fd >= 0) { - _Py_BEGIN_SUPPRESS_IPH - self->handle = (HANDLE)_get_osfhandle(fd); - _Py_END_SUPPRESS_IPH - self->closehandle = 0; + handle = _Py_get_osfhandle_noraise(fd); + self->closefd = 0; } else { DWORD access = GENERIC_READ; - self->closehandle = 1; + self->closefd = 1; if (!closefd) { PyErr_SetString(PyExc_ValueError, "Cannot use closefd=False with file name"); @@ -369,21 +353,31 @@ _io__WindowsConsoleIO___init___impl(winconsoleio *self, PyObject *nameobj, on the specific access. This is required for modern names CONIN$ and CONOUT$, which allow reading/writing state as well as reading/writing content. */ - self->handle = CreateFileW(name, GENERIC_READ | GENERIC_WRITE, + handle = CreateFileW(name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - if (self->handle == INVALID_HANDLE_VALUE) - self->handle = CreateFileW(name, access, + if (handle == INVALID_HANDLE_VALUE) + handle = CreateFileW(name, access, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); Py_END_ALLOW_THREADS - if (self->handle == INVALID_HANDLE_VALUE) { + if (handle == INVALID_HANDLE_VALUE) { PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, GetLastError(), nameobj); goto error; } + + if (self->writable) + self->fd = _Py_open_osfhandle_noraise(handle, _O_WRONLY | _O_BINARY); + else + self->fd = _Py_open_osfhandle_noraise(handle, _O_RDONLY | _O_BINARY); + if (self->fd < 0) { + CloseHandle(handle); + PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, nameobj); + goto error; + } } if (console_type == '\0') - console_type = _get_console_type(self->handle); + console_type = _get_console_type(handle); if (self->writable && console_type != 'w') { PyErr_SetString(PyExc_ValueError, @@ -466,25 +460,14 @@ _io._WindowsConsoleIO.fileno Return the underlying file descriptor (an integer). -fileno is only set when a file descriptor is used to open -one of the standard streams. - [clinic start generated code]*/ static PyObject * _io__WindowsConsoleIO_fileno_impl(winconsoleio *self) -/*[clinic end generated code: output=006fa74ce3b5cfbf input=079adc330ddaabe6]*/ +/*[clinic end generated code: output=006fa74ce3b5cfbf input=845c47ebbc3a2f67]*/ { - if (self->fd < 0 && self->handle != INVALID_HANDLE_VALUE) { - _Py_BEGIN_SUPPRESS_IPH - if (self->writable) - self->fd = _open_osfhandle((intptr_t)self->handle, _O_WRONLY | _O_BINARY); - else - self->fd = _open_osfhandle((intptr_t)self->handle, _O_RDONLY | _O_BINARY); - _Py_END_SUPPRESS_IPH - } if (self->fd < 0) - return err_mode("fileno"); + return err_closed(); return PyLong_FromLong(self->fd); } @@ -498,7 +481,7 @@ static PyObject * _io__WindowsConsoleIO_readable_impl(winconsoleio *self) /*[clinic end generated code: output=daf9cef2743becf0 input=6be9defb5302daae]*/ { - if (self->handle == INVALID_HANDLE_VALUE) + if (self->fd == -1) return err_closed(); return PyBool_FromLong((long) self->readable); } @@ -513,7 +496,7 @@ static PyObject * _io__WindowsConsoleIO_writable_impl(winconsoleio *self) /*[clinic end generated code: output=e0a2ad7eae5abf67 input=cefbd8abc24df6a0]*/ { - if (self->handle == INVALID_HANDLE_VALUE) + if (self->fd == -1) return err_closed(); return PyBool_FromLong((long) self->writable); } @@ -648,7 +631,7 @@ error: static Py_ssize_t readinto(winconsoleio *self, char *buf, Py_ssize_t len) { - if (self->handle == INVALID_HANDLE_VALUE) { + if (self->fd == -1) { err_closed(); return -1; } @@ -663,6 +646,10 @@ readinto(winconsoleio *self, char *buf, Py_ssize_t len) return -1; } + HANDLE handle = _Py_get_osfhandle(self->fd); + if (handle == INVALID_HANDLE_VALUE) + return -1; + /* Each character may take up to 4 bytes in the final buffer. This is highly conservative, but necessary to avoid failure for any given Unicode input (e.g. \U0010ffff). @@ -684,7 +671,7 @@ readinto(winconsoleio *self, char *buf, Py_ssize_t len) return read_len; DWORD n; - wchar_t *wbuf = read_console_w(self->handle, wlen, &n); + wchar_t *wbuf = read_console_w(handle, wlen, &n); if (wbuf == NULL) return -1; if (n == 0) { @@ -790,10 +777,15 @@ _io__WindowsConsoleIO_readall_impl(winconsoleio *self) DWORD bufsize, n, len = 0; PyObject *bytes; DWORD bytes_size, rn; + HANDLE handle; - if (self->handle == INVALID_HANDLE_VALUE) + if (self->fd == -1) return err_closed(); + handle = _Py_get_osfhandle(self->fd); + if (handle == INVALID_HANDLE_VALUE) + return NULL; + bufsize = BUFSIZ; buf = (wchar_t*)PyMem_Malloc((bufsize + 1) * sizeof(wchar_t)); @@ -825,7 +817,7 @@ _io__WindowsConsoleIO_readall_impl(winconsoleio *self) buf = tmp; } - subbuf = read_console_w(self->handle, bufsize - len, &n); + subbuf = read_console_w(handle, bufsize - len, &n); if (subbuf == NULL) { PyMem_Free(buf); @@ -915,7 +907,7 @@ _io__WindowsConsoleIO_read_impl(winconsoleio *self, Py_ssize_t size) PyObject *bytes; Py_ssize_t bytes_size; - if (self->handle == INVALID_HANDLE_VALUE) + if (self->fd == -1) return err_closed(); if (!self->readable) return err_mode("reading"); @@ -965,12 +957,17 @@ _io__WindowsConsoleIO_write_impl(winconsoleio *self, Py_buffer *b) BOOL res = TRUE; wchar_t *wbuf; DWORD len, wlen, n = 0; + HANDLE handle; - if (self->handle == INVALID_HANDLE_VALUE) + if (self->fd == -1) return err_closed(); if (!self->writable) return err_mode("writing"); + handle = _Py_get_osfhandle(self->fd); + if (handle == INVALID_HANDLE_VALUE) + return NULL; + if (!b->len) { return PyLong_FromLong(0); } @@ -1001,7 +998,7 @@ _io__WindowsConsoleIO_write_impl(winconsoleio *self, Py_buffer *b) Py_BEGIN_ALLOW_THREADS wlen = MultiByteToWideChar(CP_UTF8, 0, b->buf, len, wbuf, wlen); if (wlen) { - res = WriteConsoleW(self->handle, wbuf, wlen, &n, NULL); + res = WriteConsoleW(handle, wbuf, wlen, &n, NULL); if (res && n < wlen) { /* Wrote fewer characters than expected, which means our * len value may be wrong. So recalculate it from the @@ -1033,15 +1030,15 @@ _io__WindowsConsoleIO_write_impl(winconsoleio *self, Py_buffer *b) static PyObject * winconsoleio_repr(winconsoleio *self) { - if (self->handle == INVALID_HANDLE_VALUE) + if (self->fd == -1) return PyUnicode_FromFormat("<_io._WindowsConsoleIO [closed]>"); if (self->readable) return PyUnicode_FromFormat("<_io._WindowsConsoleIO mode='rb' closefd=%s>", - self->closehandle ? "True" : "False"); + self->closefd ? "True" : "False"); if (self->writable) return PyUnicode_FromFormat("<_io._WindowsConsoleIO mode='wb' closefd=%s>", - self->closehandle ? "True" : "False"); + self->closefd ? "True" : "False"); PyErr_SetString(PyExc_SystemError, "_WindowsConsoleIO has invalid mode"); return NULL; @@ -1057,7 +1054,7 @@ static PyObject * _io__WindowsConsoleIO_isatty_impl(winconsoleio *self) /*[clinic end generated code: output=9eac09d287c11bd7 input=9b91591dbe356f86]*/ { - if (self->handle == INVALID_HANDLE_VALUE) + if (self->fd == -1) return err_closed(); Py_RETURN_TRUE; @@ -1083,13 +1080,13 @@ static PyMethodDef winconsoleio_methods[] = { static PyObject * get_closed(winconsoleio *self, void *closure) { - return PyBool_FromLong((long)(self->handle == INVALID_HANDLE_VALUE)); + return PyBool_FromLong((long)(self->fd == -1)); } static PyObject * get_closefd(winconsoleio *self, void *closure) { - return PyBool_FromLong((long)(self->closehandle)); + return PyBool_FromLong((long)(self->closefd)); } static PyObject * diff --git a/contrib/tools/python3/src/Modules/_json.c b/contrib/tools/python3/src/Modules/_json.c index faa3944eed..6f68c1f7f9 100644 --- a/contrib/tools/python3/src/Modules/_json.c +++ b/contrib/tools/python3/src/Modules/_json.c @@ -79,7 +79,6 @@ static PyObject * ascii_escape_unicode(PyObject *pystr); static PyObject * py_encode_basestring_ascii(PyObject* Py_UNUSED(self), PyObject *pystr); -void init_json(void); static PyObject * scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr); static PyObject * @@ -317,18 +316,22 @@ static void raise_errmsg(const char *msg, PyObject *s, Py_ssize_t end) { /* Use JSONDecodeError exception to raise a nice looking ValueError subclass */ - static PyObject *JSONDecodeError = NULL; - PyObject *exc; + _Py_static_string(PyId_decoder, "json.decoder"); + PyObject *decoder = _PyImport_GetModuleId(&PyId_decoder); + if (decoder == NULL) { + return; + } + + _Py_IDENTIFIER(JSONDecodeError); + PyObject *JSONDecodeError = _PyObject_GetAttrId(decoder, &PyId_JSONDecodeError); + Py_DECREF(decoder); if (JSONDecodeError == NULL) { - PyObject *decoder = PyImport_ImportModule("json.decoder"); - if (decoder == NULL) - return; - JSONDecodeError = PyObject_GetAttrString(decoder, "JSONDecodeError"); - Py_DECREF(decoder); - if (JSONDecodeError == NULL) - return; + return; } + + PyObject *exc; exc = PyObject_CallFunction(JSONDecodeError, "zOn", msg, s, end); + Py_DECREF(JSONDecodeError); if (exc) { PyErr_SetObject(JSONDecodeError, exc); Py_DECREF(exc); @@ -1308,28 +1311,28 @@ _encoded_const(PyObject *obj) { /* Return the JSON string representation of None, True, False */ if (obj == Py_None) { - static PyObject *s_null = NULL; + _Py_static_string(PyId_null, "null"); + PyObject *s_null = _PyUnicode_FromId(&PyId_null); if (s_null == NULL) { - s_null = PyUnicode_InternFromString("null"); + return NULL; } - Py_XINCREF(s_null); - return s_null; + return Py_NewRef(s_null); } else if (obj == Py_True) { - static PyObject *s_true = NULL; + _Py_static_string(PyId_true, "true"); + PyObject *s_true = _PyUnicode_FromId(&PyId_true); if (s_true == NULL) { - s_true = PyUnicode_InternFromString("true"); + return NULL; } - Py_XINCREF(s_true); - return s_true; + return Py_NewRef(s_true); } else if (obj == Py_False) { - static PyObject *s_false = NULL; + _Py_static_string(PyId_false, "false"); + PyObject *s_false = _PyUnicode_FromId(&PyId_false); if (s_false == NULL) { - s_false = PyUnicode_InternFromString("false"); + return NULL; } - Py_XINCREF(s_false); - return s_false; + return Py_NewRef(s_false); } else { PyErr_SetString(PyExc_ValueError, "not a const"); @@ -1493,9 +1496,12 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc, PyObject *dct, Py_ssize_t indent_level) { /* Encode Python dict dct a JSON term */ - static PyObject *open_dict = NULL; - static PyObject *close_dict = NULL; - static PyObject *empty_dict = NULL; + _Py_static_string(PyId_open_dict, "{"); + _Py_static_string(PyId_close_dict, "}"); + _Py_static_string(PyId_empty_dict, "{}"); + PyObject *open_dict = _PyUnicode_FromId(&PyId_open_dict); // borrowed ref + PyObject *close_dict = _PyUnicode_FromId(&PyId_close_dict); // borrowed ref + PyObject *empty_dict = _PyUnicode_FromId(&PyId_empty_dict); // borrowed ref PyObject *kstr = NULL; PyObject *ident = NULL; PyObject *it = NULL; @@ -1504,11 +1510,7 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc, Py_ssize_t idx; if (open_dict == NULL || close_dict == NULL || empty_dict == NULL) { - open_dict = PyUnicode_InternFromString("{"); - close_dict = PyUnicode_InternFromString("}"); - empty_dict = PyUnicode_InternFromString("{}"); - if (open_dict == NULL || close_dict == NULL || empty_dict == NULL) - return -1; + return -1; } if (PyDict_GET_SIZE(dct) == 0) /* Fast path */ return _PyAccu_Accumulate(acc, empty_dict); @@ -1650,19 +1652,18 @@ encoder_listencode_list(PyEncoderObject *s, _PyAccu *acc, PyObject *seq, Py_ssize_t indent_level) { /* Encode Python list seq to a JSON term */ - static PyObject *open_array = NULL; - static PyObject *close_array = NULL; - static PyObject *empty_array = NULL; + _Py_static_string(PyId_open_array, "["); + _Py_static_string(PyId_close_array, "]"); + _Py_static_string(PyId_empty_array, "[]"); + PyObject *open_array = _PyUnicode_FromId(&PyId_open_array); // borrowed ref + PyObject *close_array = _PyUnicode_FromId(&PyId_close_array); // borrowed ref + PyObject *empty_array = _PyUnicode_FromId(&PyId_empty_array); // borrowed ref PyObject *ident = NULL; PyObject *s_fast = NULL; Py_ssize_t i; if (open_array == NULL || close_array == NULL || empty_array == NULL) { - open_array = PyUnicode_InternFromString("["); - close_array = PyUnicode_InternFromString("]"); - empty_array = PyUnicode_InternFromString("[]"); - if (open_array == NULL || close_array == NULL || empty_array == NULL) - return -1; + return -1; } ident = NULL; s_fast = PySequence_Fast(seq, "_iterencode_list needs a sequence"); diff --git a/contrib/tools/python3/src/Modules/_localemodule.c b/contrib/tools/python3/src/Modules/_localemodule.c index 2e353bba00..564f5598ed 100644 --- a/contrib/tools/python3/src/Modules/_localemodule.c +++ b/contrib/tools/python3/src/Modules/_localemodule.c @@ -53,10 +53,14 @@ get_locale_state(PyObject *m) return (_locale_state *)state; } -/* support functions for formatting floating point numbers */ +#include "clinic/_localemodule.c.h" + +/*[clinic input] +module _locale +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ed98569b726feada]*/ -PyDoc_STRVAR(setlocale__doc__, -"(integer,string=None) -> string. Activates/queries locale processing."); +/* support functions for formatting floating point numbers */ /* the grouping is terminated by either 0 or CHAR_MAX */ static PyObject* @@ -91,20 +95,27 @@ copy_grouping(const char* s) return result; } -static PyObject* -PyLocale_setlocale(PyObject* self, PyObject* args) +/*[clinic input] +_locale.setlocale + + category: int + locale: str(accept={str, NoneType}) = NULL + / + +Activates/queries locale processing. +[clinic start generated code]*/ + +static PyObject * +_locale_setlocale_impl(PyObject *module, int category, const char *locale) +/*[clinic end generated code: output=a0e777ae5d2ff117 input=dbe18f1d66c57a6a]*/ { - int category; - char *locale = NULL, *result; + char *result; PyObject *result_object; - if (!PyArg_ParseTuple(args, "i|z:setlocale", &category, &locale)) - return NULL; - #if defined(MS_WINDOWS) if (category < LC_MIN || category > LC_MAX) { - PyErr_SetString(get_locale_state(self)->Error, + PyErr_SetString(get_locale_state(module)->Error, "invalid locale category"); return NULL; } @@ -115,7 +126,7 @@ PyLocale_setlocale(PyObject* self, PyObject* args) result = setlocale(category, locale); if (!result) { /* operation failed, no setting was changed */ - PyErr_SetString(get_locale_state(self)->Error, + PyErr_SetString(get_locale_state(module)->Error, "unsupported locale setting"); return NULL; } @@ -126,7 +137,7 @@ PyLocale_setlocale(PyObject* self, PyObject* args) /* get locale */ result = setlocale(category, NULL); if (!result) { - PyErr_SetString(get_locale_state(self)->Error, + PyErr_SetString(get_locale_state(module)->Error, "locale query failed"); return NULL; } @@ -221,11 +232,15 @@ done: return res; } -PyDoc_STRVAR(localeconv__doc__, -"() -> dict. Returns numeric and monetary locale-specific parameters."); +/*[clinic input] +_locale.localeconv -static PyObject* -PyLocale_localeconv(PyObject* self, PyObject *Py_UNUSED(ignored)) +Returns numeric and monetary locale-specific parameters. +[clinic start generated code]*/ + +static PyObject * +_locale_localeconv_impl(PyObject *module) +/*[clinic end generated code: output=43a54515e0a2aef5 input=f1132d15accf4444]*/ { PyObject* result; struct lconv *lc; @@ -326,17 +341,24 @@ PyLocale_localeconv(PyObject* self, PyObject *Py_UNUSED(ignored)) } #if defined(HAVE_WCSCOLL) -PyDoc_STRVAR(strcoll__doc__, -"string,string -> int. Compares two strings according to the locale."); -static PyObject* -PyLocale_strcoll(PyObject* self, PyObject* args) +/*[clinic input] +_locale.strcoll + + os1: unicode + os2: unicode + / + +Compares two strings according to the locale. +[clinic start generated code]*/ + +static PyObject * +_locale_strcoll_impl(PyObject *module, PyObject *os1, PyObject *os2) +/*[clinic end generated code: output=82ddc6d62c76d618 input=693cd02bcbf38dd8]*/ { - PyObject *os1, *os2, *result = NULL; + PyObject *result = NULL; wchar_t *ws1 = NULL, *ws2 = NULL; - if (!PyArg_ParseTuple(args, "UU:strcoll", &os1, &os2)) - return NULL; /* Convert the unicode strings to wchar[]. */ ws1 = PyUnicode_AsWideCharString(os1, NULL); if (ws1 == NULL) @@ -348,30 +370,32 @@ PyLocale_strcoll(PyObject* self, PyObject* args) result = PyLong_FromLong(wcscoll(ws1, ws2)); done: /* Deallocate everything. */ - if (ws1) PyMem_FREE(ws1); - if (ws2) PyMem_FREE(ws2); + if (ws1) PyMem_Free(ws1); + if (ws2) PyMem_Free(ws2); return result; } #endif #ifdef HAVE_WCSXFRM -PyDoc_STRVAR(strxfrm__doc__, -"strxfrm(string) -> string.\n\ -\n\ -Return a string that can be used as a key for locale-aware comparisons."); -static PyObject* -PyLocale_strxfrm(PyObject* self, PyObject* args) +/*[clinic input] +_locale.strxfrm + + string as str: unicode + / + +Return a string that can be used as a key for locale-aware comparisons. +[clinic start generated code]*/ + +static PyObject * +_locale_strxfrm_impl(PyObject *module, PyObject *str) +/*[clinic end generated code: output=3081866ebffc01af input=1378bbe6a88b4780]*/ { - PyObject *str; Py_ssize_t n1; wchar_t *s = NULL, *buf = NULL; size_t n2; PyObject *result = NULL; - if (!PyArg_ParseTuple(args, "U:strxfrm", &str)) - return NULL; - s = PyUnicode_AsWideCharString(str, &n1); if (s == NULL) goto exit; @@ -418,8 +442,15 @@ exit: #endif #if defined(MS_WINDOWS) -static PyObject* -PyLocale_getdefaultlocale(PyObject* self, PyObject *Py_UNUSED(ignored)) + +/*[clinic input] +_locale._getdefaultlocale + +[clinic start generated code]*/ + +static PyObject * +_locale__getdefaultlocale_impl(PyObject *module) +/*[clinic end generated code: output=e6254088579534c2 input=003ea41acd17f7c7]*/ { char encoding[20]; char locale[100]; @@ -525,7 +556,6 @@ static struct langinfo_constant{ LANGINFO(PM_STR), /* The following constants are available only with XPG4, but... - AIX 3.2. only has CODESET. OpenBSD doesn't have CODESET but has T_FMT_AMPM, and doesn't have a few of the others. Solution: ifdef-test them all. */ @@ -563,16 +593,20 @@ static struct langinfo_constant{ {0, 0} }; -PyDoc_STRVAR(nl_langinfo__doc__, -"nl_langinfo(key) -> string\n" -"Return the value for the locale information associated with key."); +/*[clinic input] +_locale.nl_langinfo -static PyObject* -PyLocale_nl_langinfo(PyObject* self, PyObject* args) + key as item: int + / + +Return the value for the locale information associated with key. +[clinic start generated code]*/ + +static PyObject * +_locale_nl_langinfo_impl(PyObject *module, int item) +/*[clinic end generated code: output=6aea457b47e077a3 input=00798143eecfeddc]*/ { - int item, i; - if (!PyArg_ParseTuple(args, "i:nl_langinfo", &item)) - return NULL; + int i; /* Check whether this is a supported constant. GNU libc sometimes returns numeric values in the char* return value, which would crash PyUnicode_FromString. */ @@ -591,56 +625,75 @@ PyLocale_nl_langinfo(PyObject* self, PyObject* args) #ifdef HAVE_LIBINTL_H -PyDoc_STRVAR(gettext__doc__, -"gettext(msg) -> string\n" -"Return translation of msg."); +/*[clinic input] +_locale.gettext -static PyObject* -PyIntl_gettext(PyObject* self, PyObject *args) + msg as in: str + / + +gettext(msg) -> string + +Return translation of msg. +[clinic start generated code]*/ + +static PyObject * +_locale_gettext_impl(PyObject *module, const char *in) +/*[clinic end generated code: output=493bb4b38a4704fe input=949fc8efc2bb3bc3]*/ { - char *in; - if (!PyArg_ParseTuple(args, "s", &in)) - return 0; return PyUnicode_DecodeLocale(gettext(in), NULL); } -PyDoc_STRVAR(dgettext__doc__, -"dgettext(domain, msg) -> string\n" -"Return translation of msg in domain."); +/*[clinic input] +_locale.dgettext -static PyObject* -PyIntl_dgettext(PyObject* self, PyObject *args) + domain: str(accept={str, NoneType}) + msg as in: str + / + +dgettext(domain, msg) -> string + +Return translation of msg in domain. +[clinic start generated code]*/ + +static PyObject * +_locale_dgettext_impl(PyObject *module, const char *domain, const char *in) +/*[clinic end generated code: output=3c0cd5287b972c8f input=a277388a635109d8]*/ { - char *domain, *in; - if (!PyArg_ParseTuple(args, "zs", &domain, &in)) - return 0; return PyUnicode_DecodeLocale(dgettext(domain, in), NULL); } -PyDoc_STRVAR(dcgettext__doc__, -"dcgettext(domain, msg, category) -> string\n" -"Return translation of msg in domain and category."); +/*[clinic input] +_locale.dcgettext -static PyObject* -PyIntl_dcgettext(PyObject *self, PyObject *args) + domain: str(accept={str, NoneType}) + msg as msgid: str + category: int + / + +Return translation of msg in domain and category. +[clinic start generated code]*/ + +static PyObject * +_locale_dcgettext_impl(PyObject *module, const char *domain, + const char *msgid, int category) +/*[clinic end generated code: output=0f4cc4fce0aa283f input=ec5f8fed4336de67]*/ { - char *domain, *msgid; - int category; - if (!PyArg_ParseTuple(args, "zsi", &domain, &msgid, &category)) - return 0; return PyUnicode_DecodeLocale(dcgettext(domain,msgid,category), NULL); } -PyDoc_STRVAR(textdomain__doc__, -"textdomain(domain) -> string\n" -"Set the C library's textdmain to domain, returning the new domain."); +/*[clinic input] +_locale.textdomain -static PyObject* -PyIntl_textdomain(PyObject* self, PyObject* args) + domain: str(accept={str, NoneType}) + / + +Set the C library's textdmain to domain, returning the new domain. +[clinic start generated code]*/ + +static PyObject * +_locale_textdomain_impl(PyObject *module, const char *domain) +/*[clinic end generated code: output=7992df06aadec313 input=66359716f5eb1d38]*/ { - char *domain; - if (!PyArg_ParseTuple(args, "z", &domain)) - return 0; domain = textdomain(domain); if (!domain) { PyErr_SetFromErrno(PyExc_OSError); @@ -649,20 +702,26 @@ PyIntl_textdomain(PyObject* self, PyObject* args) return PyUnicode_DecodeLocale(domain, NULL); } -PyDoc_STRVAR(bindtextdomain__doc__, -"bindtextdomain(domain, dir) -> string\n" -"Bind the C library's domain to dir."); +/*[clinic input] +_locale.bindtextdomain -static PyObject* -PyIntl_bindtextdomain(PyObject* self, PyObject*args) + domain: str + dir as dirname_obj: object + / + +Bind the C library's domain to dir. +[clinic start generated code]*/ + +static PyObject * +_locale_bindtextdomain_impl(PyObject *module, const char *domain, + PyObject *dirname_obj) +/*[clinic end generated code: output=6d6f3c7b345d785c input=c0dff085acfe272b]*/ { - const char *domain, *dirname, *current_dirname; - PyObject *dirname_obj, *dirname_bytes = NULL, *result; + const char *dirname, *current_dirname; + PyObject *dirname_bytes = NULL, *result; - if (!PyArg_ParseTuple(args, "sO", &domain, &dirname_obj)) - return 0; if (!strlen(domain)) { - PyErr_SetString(get_locale_state(self)->Error, + PyErr_SetString(get_locale_state(module)->Error, "domain must be a non-empty string"); return 0; } @@ -686,61 +745,73 @@ PyIntl_bindtextdomain(PyObject* self, PyObject*args) } #ifdef HAVE_BIND_TEXTDOMAIN_CODESET -PyDoc_STRVAR(bind_textdomain_codeset__doc__, -"bind_textdomain_codeset(domain, codeset) -> string\n" -"Bind the C library's domain to codeset."); -static PyObject* -PyIntl_bind_textdomain_codeset(PyObject* self,PyObject*args) +/*[clinic input] +_locale.bind_textdomain_codeset + + domain: str + codeset: str(accept={str, NoneType}) + / + +Bind the C library's domain to codeset. +[clinic start generated code]*/ + +static PyObject * +_locale_bind_textdomain_codeset_impl(PyObject *module, const char *domain, + const char *codeset) +/*[clinic end generated code: output=fa452f9c8b1b9e89 input=23fbe3540400f259]*/ { - char *domain,*codeset; - if (!PyArg_ParseTuple(args, "sz", &domain, &codeset)) - return NULL; codeset = bind_textdomain_codeset(domain, codeset); if (codeset) { return PyUnicode_DecodeLocale(codeset, NULL); } Py_RETURN_NONE; } -#endif +#endif // HAVE_BIND_TEXTDOMAIN_CODESET + +#endif // HAVE_LIBINTL_H + + +/*[clinic input] +_locale._get_locale_encoding + +Get the current locale encoding. +[clinic start generated code]*/ + +static PyObject * +_locale__get_locale_encoding_impl(PyObject *module) +/*[clinic end generated code: output=e8e2f6f6f184591a input=513d9961d2f45c76]*/ +{ + return _Py_GetLocaleEncodingObject(); +} -#endif static struct PyMethodDef PyLocale_Methods[] = { - {"setlocale", (PyCFunction) PyLocale_setlocale, - METH_VARARGS, setlocale__doc__}, - {"localeconv", PyLocale_localeconv, METH_NOARGS, localeconv__doc__}, + _LOCALE_SETLOCALE_METHODDEF + _LOCALE_LOCALECONV_METHODDEF #ifdef HAVE_WCSCOLL - {"strcoll", (PyCFunction) PyLocale_strcoll, - METH_VARARGS, strcoll__doc__}, + _LOCALE_STRCOLL_METHODDEF #endif #ifdef HAVE_WCSXFRM - {"strxfrm", (PyCFunction) PyLocale_strxfrm, - METH_VARARGS, strxfrm__doc__}, + _LOCALE_STRXFRM_METHODDEF #endif #if defined(MS_WINDOWS) - {"_getdefaultlocale", PyLocale_getdefaultlocale, METH_NOARGS}, + _LOCALE__GETDEFAULTLOCALE_METHODDEF #endif #ifdef HAVE_LANGINFO_H - {"nl_langinfo", (PyCFunction) PyLocale_nl_langinfo, - METH_VARARGS, nl_langinfo__doc__}, + _LOCALE_NL_LANGINFO_METHODDEF #endif #ifdef HAVE_LIBINTL_H - {"gettext",(PyCFunction)PyIntl_gettext,METH_VARARGS, - gettext__doc__}, - {"dgettext",(PyCFunction)PyIntl_dgettext,METH_VARARGS, - dgettext__doc__}, - {"dcgettext",(PyCFunction)PyIntl_dcgettext,METH_VARARGS, - dcgettext__doc__}, - {"textdomain",(PyCFunction)PyIntl_textdomain,METH_VARARGS, - textdomain__doc__}, - {"bindtextdomain",(PyCFunction)PyIntl_bindtextdomain,METH_VARARGS, - bindtextdomain__doc__}, + _LOCALE_GETTEXT_METHODDEF + _LOCALE_DGETTEXT_METHODDEF + _LOCALE_DCGETTEXT_METHODDEF + _LOCALE_TEXTDOMAIN_METHODDEF + _LOCALE_BINDTEXTDOMAIN_METHODDEF #ifdef HAVE_BIND_TEXTDOMAIN_CODESET - {"bind_textdomain_codeset",(PyCFunction)PyIntl_bind_textdomain_codeset, - METH_VARARGS, bind_textdomain_codeset__doc__}, + _LOCALE_BIND_TEXTDOMAIN_CODESET_METHODDEF #endif #endif + _LOCALE__GET_LOCALE_ENCODING_METHODDEF {NULL, NULL} }; diff --git a/contrib/tools/python3/src/Modules/_lsprof.c b/contrib/tools/python3/src/Modules/_lsprof.c index 5e53d83964..703067cc74 100644 --- a/contrib/tools/python3/src/Modules/_lsprof.c +++ b/contrib/tools/python3/src/Modules/_lsprof.c @@ -50,10 +50,27 @@ typedef struct { #define POF_BUILTINS 0x004 #define POF_NOMEMORY 0x100 -static PyTypeObject PyProfiler_Type; +/*[clinic input] +module _lsprof +class _lsprof.Profiler "ProfilerObject *" "&ProfilerType" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e349ac952152f336]*/ -#define PyProfiler_Check(op) PyObject_TypeCheck(op, &PyProfiler_Type) -#define PyProfiler_CheckExact(op) Py_IS_TYPE(op, &PyProfiler_Type) +#include "clinic/_lsprof.c.h" + +typedef struct { + PyTypeObject *profiler_type; + PyTypeObject *stats_entry_type; + PyTypeObject *stats_subentry_type; +} _lsprof_state; + +static inline _lsprof_state* +_lsprof_get_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (_lsprof_state *)state; +} /*** External Timers ***/ @@ -471,28 +488,24 @@ static PyStructSequence_Field profiler_subentry_fields[] = { }; static PyStructSequence_Desc profiler_entry_desc = { - "_lsprof.profiler_entry", /* name */ - NULL, /* doc */ - profiler_entry_fields, - 6 + .name = "_lsprof.profiler_entry", + .fields = profiler_entry_fields, + .doc = NULL, + .n_in_sequence = 6 }; static PyStructSequence_Desc profiler_subentry_desc = { - "_lsprof.profiler_subentry", /* name */ - NULL, /* doc */ - profiler_subentry_fields, - 5 + .name = "_lsprof.profiler_subentry", + .fields = profiler_subentry_fields, + .doc = NULL, + .n_in_sequence = 5 }; -static int initialized; -static PyTypeObject StatsEntryType; -static PyTypeObject StatsSubEntryType; - - typedef struct { PyObject *list; PyObject *sublist; double factor; + _lsprof_state *state; } statscollector_t; static int statsForSubEntry(rotating_node_t *node, void *arg) @@ -502,7 +515,7 @@ static int statsForSubEntry(rotating_node_t *node, void *arg) ProfilerEntry *entry = (ProfilerEntry*) sentry->header.key; int err; PyObject *sinfo; - sinfo = PyObject_CallFunction((PyObject*) &StatsSubEntryType, + sinfo = PyObject_CallFunction((PyObject*) collect->state->stats_subentry_type, "((Olldd))", entry->userObj, sentry->callcount, @@ -540,7 +553,7 @@ static int statsForEntry(rotating_node_t *node, void *arg) collect->sublist = Py_None; } - info = PyObject_CallFunction((PyObject*) &StatsEntryType, + info = PyObject_CallFunction((PyObject*) collect->state->stats_entry_type, "((OllddO))", entry->userObj, entry->callcount, @@ -556,49 +569,57 @@ static int statsForEntry(rotating_node_t *node, void *arg) return err; } -PyDoc_STRVAR(getstats_doc, "\ -getstats() -> list of profiler_entry objects\n\ -\n\ -Return all information collected by the profiler.\n\ -Each profiler_entry is a tuple-like object with the\n\ -following attributes:\n\ -\n\ - code code object\n\ - callcount how many times this was called\n\ - reccallcount how many times called recursively\n\ - totaltime total time in this entry\n\ - inlinetime inline time in this entry (not in subcalls)\n\ - calls details of the calls\n\ -\n\ -The calls attribute is either None or a list of\n\ -profiler_subentry objects:\n\ -\n\ - code called code object\n\ - callcount how many times this is called\n\ - reccallcount how many times this is called recursively\n\ - totaltime total time spent in this call\n\ - inlinetime inline time (not in further subcalls)\n\ -"); +/*[clinic input] +_lsprof.Profiler.getstats -static PyObject* -profiler_getstats(ProfilerObject *pObj, PyObject* noarg) + cls: defining_class + +list of profiler_entry objects. + +getstats() -> list of profiler_entry objects + +Return all information collected by the profiler. +Each profiler_entry is a tuple-like object with the +following attributes: + + code code object + callcount how many times this was called + reccallcount how many times called recursively + totaltime total time in this entry + inlinetime inline time in this entry (not in subcalls) + calls details of the calls + +The calls attribute is either None or a list of +profiler_subentry objects: + + code called code object + callcount how many times this is called + reccallcount how many times this is called recursively + totaltime total time spent in this call + inlinetime inline time (not in further subcalls) +[clinic start generated code]*/ + +static PyObject * +_lsprof_Profiler_getstats_impl(ProfilerObject *self, PyTypeObject *cls) +/*[clinic end generated code: output=1806ef720019ee03 input=445e193ef4522902]*/ { statscollector_t collect; - if (pending_exception(pObj)) { + collect.state = PyType_GetModuleState(cls); + if (pending_exception(self)) { return NULL; } - if (!pObj->externalTimer || pObj->externalTimerUnit == 0.0) { + if (!self->externalTimer || self->externalTimerUnit == 0.0) { _PyTime_t onesec = _PyTime_FromSeconds(1); collect.factor = (double)1 / onesec; } else { - collect.factor = pObj->externalTimerUnit; + collect.factor = self->externalTimerUnit; } collect.list = PyList_New(0); if (collect.list == NULL) return NULL; - if (RotatingTree_Enum(pObj->profilerEntries, statsForEntry, &collect) + if (RotatingTree_Enum(self->profilerEntries, statsForEntry, &collect) != 0) { Py_DECREF(collect.list); return NULL; @@ -710,6 +731,13 @@ profiler_clear(ProfilerObject *pObj, PyObject* noarg) Py_RETURN_NONE; } +static int +profiler_traverse(ProfilerObject *op, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(op)); + return 0; +} + static void profiler_dealloc(ProfilerObject *op) { @@ -723,7 +751,9 @@ profiler_dealloc(ProfilerObject *op) flush_unmatched(op); clearEntries(op); Py_XDECREF(op->externalTimer); - Py_TYPE(op)->tp_free(op); + PyTypeObject *tp = Py_TYPE(op); + tp->tp_free(op); + Py_DECREF(tp); } static int @@ -750,8 +780,7 @@ profiler_init(ProfilerObject *pObj, PyObject *args, PyObject *kw) } static PyMethodDef profiler_methods[] = { - {"getstats", (PyCFunction)profiler_getstats, - METH_NOARGS, getstats_doc}, + _LSPROF_PROFILER_GETSTATS_METHODDEF {"enable", (PyCFunction)(void(*)(void))profiler_enable, METH_VARARGS | METH_KEYWORDS, enable_doc}, {"disable", (PyCFunction)profiler_disable, @@ -771,91 +800,106 @@ Profiler(timer=None, timeunit=None, subcalls=True, builtins=True)\n\ is, in seconds).\n\ "); -static PyTypeObject PyProfiler_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_lsprof.Profiler", /* tp_name */ - sizeof(ProfilerObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)profiler_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - profiler_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - profiler_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)profiler_init, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ - PyObject_Del, /* tp_free */ +static PyType_Slot _lsprof_profiler_type_spec_slots[] = { + {Py_tp_doc, (void *)profiler_doc}, + {Py_tp_methods, profiler_methods}, + {Py_tp_dealloc, profiler_dealloc}, + {Py_tp_init, profiler_init}, + {Py_tp_traverse, profiler_traverse}, + {0, 0} +}; + +static PyType_Spec _lsprof_profiler_type_spec = { + .name = "_lsprof.Profiler", + .basicsize = sizeof(ProfilerObject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), + .slots = _lsprof_profiler_type_spec_slots, }; static PyMethodDef moduleMethods[] = { {NULL, NULL} }; +static int +_lsprof_traverse(PyObject *module, visitproc visit, void *arg) +{ + _lsprof_state *state = _lsprof_get_state(module); + Py_VISIT(state->profiler_type); + Py_VISIT(state->stats_entry_type); + Py_VISIT(state->stats_subentry_type); + return 0; +} + +static int +_lsprof_clear(PyObject *module) +{ + _lsprof_state *state = _lsprof_get_state(module); + Py_CLEAR(state->profiler_type); + Py_CLEAR(state->stats_entry_type); + Py_CLEAR(state->stats_subentry_type); + return 0; +} + +static void +_lsprof_free(void *module) +{ + _lsprof_clear((PyObject *)module); +} + +static int +_lsprof_exec(PyObject *module) +{ + _lsprof_state *state = PyModule_GetState(module); + + state->profiler_type = (PyTypeObject *)PyType_FromModuleAndSpec( + module, &_lsprof_profiler_type_spec, NULL); + if (state->profiler_type == NULL) { + return -1; + } + + if (PyModule_AddType(module, state->profiler_type) < 0) { + return -1; + } + + state->stats_entry_type = PyStructSequence_NewType(&profiler_entry_desc); + if (state->stats_entry_type == NULL) { + return -1; + } + if (PyModule_AddType(module, state->stats_entry_type) < 0) { + return -1; + } + + state->stats_subentry_type = PyStructSequence_NewType(&profiler_subentry_desc); + if (state->stats_subentry_type == NULL) { + return -1; + } + if (PyModule_AddType(module, state->stats_subentry_type) < 0) { + return -1; + } + + return 0; +} + +static PyModuleDef_Slot _lsprofslots[] = { + {Py_mod_exec, _lsprof_exec}, + {0, NULL} +}; static struct PyModuleDef _lsprofmodule = { PyModuleDef_HEAD_INIT, - "_lsprof", - "Fast profiler", - -1, - moduleMethods, - NULL, - NULL, - NULL, - NULL + .m_name = "_lsprof", + .m_doc = "Fast profiler", + .m_size = sizeof(_lsprof_state), + .m_methods = moduleMethods, + .m_slots = _lsprofslots, + .m_traverse = _lsprof_traverse, + .m_clear = _lsprof_clear, + .m_free = _lsprof_free }; PyMODINIT_FUNC PyInit__lsprof(void) { - PyObject *module, *d; - module = PyModule_Create(&_lsprofmodule); - if (module == NULL) - return NULL; - d = PyModule_GetDict(module); - if (PyType_Ready(&PyProfiler_Type) < 0) - return NULL; - PyDict_SetItemString(d, "Profiler", (PyObject *)&PyProfiler_Type); - - if (!initialized) { - if (PyStructSequence_InitType2(&StatsEntryType, - &profiler_entry_desc) < 0) - return NULL; - if (PyStructSequence_InitType2(&StatsSubEntryType, - &profiler_subentry_desc) < 0) - return NULL; - } - Py_INCREF((PyObject*) &StatsEntryType); - Py_INCREF((PyObject*) &StatsSubEntryType); - PyModule_AddObject(module, "profiler_entry", - (PyObject*) &StatsEntryType); - PyModule_AddObject(module, "profiler_subentry", - (PyObject*) &StatsSubEntryType); - initialized = 1; - return module; + return PyModuleDef_Init(&_lsprofmodule); } diff --git a/contrib/tools/python3/src/Modules/_lzmamodule.c b/contrib/tools/python3/src/Modules/_lzmamodule.c index 2a62a68356..915c0c918f 100644 --- a/contrib/tools/python3/src/Modules/_lzmamodule.c +++ b/contrib/tools/python3/src/Modules/_lzmamodule.c @@ -15,6 +15,60 @@ #include <lzma.h> +// Blocks output buffer wrappers +#include "pycore_blocks_output_buffer.h" + +#if OUTPUT_BUFFER_MAX_BLOCK_SIZE > SIZE_MAX + #error "The maximum block size accepted by liblzma is SIZE_MAX." +#endif + +/* On success, return value >= 0 + On failure, return -1 */ +static inline Py_ssize_t +OutputBuffer_InitAndGrow(_BlocksOutputBuffer *buffer, Py_ssize_t max_length, + uint8_t **next_out, size_t *avail_out) +{ + Py_ssize_t allocated; + + allocated = _BlocksOutputBuffer_InitAndGrow( + buffer, max_length, (void**) next_out); + *avail_out = (size_t) allocated; + return allocated; +} + +/* On success, return value >= 0 + On failure, return -1 */ +static inline Py_ssize_t +OutputBuffer_Grow(_BlocksOutputBuffer *buffer, + uint8_t **next_out, size_t *avail_out) +{ + Py_ssize_t allocated; + + allocated = _BlocksOutputBuffer_Grow( + buffer, (void**) next_out, (Py_ssize_t) *avail_out); + *avail_out = (size_t) allocated; + return allocated; +} + +static inline Py_ssize_t +OutputBuffer_GetDataSize(_BlocksOutputBuffer *buffer, size_t avail_out) +{ + return _BlocksOutputBuffer_GetDataSize(buffer, (Py_ssize_t) avail_out); +} + +static inline PyObject * +OutputBuffer_Finish(_BlocksOutputBuffer *buffer, size_t avail_out) +{ + return _BlocksOutputBuffer_Finish(buffer, (Py_ssize_t) avail_out); +} + +static inline void +OutputBuffer_OnError(_BlocksOutputBuffer *buffer) +{ + _BlocksOutputBuffer_OnError(buffer); +} + + #define ACQUIRE_LOCK(obj) do { \ if (!PyThread_acquire_lock((obj)->lock, 0)) { \ Py_BEGIN_ALLOW_THREADS \ @@ -23,6 +77,20 @@ } } while (0) #define RELEASE_LOCK(obj) PyThread_release_lock((obj)->lock) +typedef struct { + PyTypeObject *lzma_compressor_type; + PyTypeObject *lzma_decompressor_type; + PyObject *error; + PyObject *empty_tuple; +} _lzma_state; + +static inline _lzma_state* +get_lzma_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (_lzma_state *)state; +} /* Container formats: */ enum { @@ -56,17 +124,10 @@ typedef struct { PyThread_type_lock lock; } Decompressor; -/* LZMAError class object. */ -static PyObject *Error; - -/* An empty tuple, used by the filter specifier parsing code. */ -static PyObject *empty_tuple; - - /* Helper functions. */ static int -catch_lzma_error(lzma_ret lzret) +catch_lzma_error(_lzma_state *state, lzma_ret lzret) { switch (lzret) { case LZMA_OK: @@ -75,31 +136,31 @@ catch_lzma_error(lzma_ret lzret) case LZMA_STREAM_END: return 0; case LZMA_UNSUPPORTED_CHECK: - PyErr_SetString(Error, "Unsupported integrity check"); + PyErr_SetString(state->error, "Unsupported integrity check"); return 1; case LZMA_MEM_ERROR: PyErr_NoMemory(); return 1; case LZMA_MEMLIMIT_ERROR: - PyErr_SetString(Error, "Memory usage limit exceeded"); + PyErr_SetString(state->error, "Memory usage limit exceeded"); return 1; case LZMA_FORMAT_ERROR: - PyErr_SetString(Error, "Input format not supported by decoder"); + PyErr_SetString(state->error, "Input format not supported by decoder"); return 1; case LZMA_OPTIONS_ERROR: - PyErr_SetString(Error, "Invalid or unsupported options"); + PyErr_SetString(state->error, "Invalid or unsupported options"); return 1; case LZMA_DATA_ERROR: - PyErr_SetString(Error, "Corrupt input data"); + PyErr_SetString(state->error, "Corrupt input data"); return 1; case LZMA_BUF_ERROR: - PyErr_SetString(Error, "Insufficient buffer space"); + PyErr_SetString(state->error, "Insufficient buffer space"); return 1; case LZMA_PROG_ERROR: - PyErr_SetString(Error, "Internal error"); + PyErr_SetString(state->error, "Internal error"); return 1; default: - PyErr_Format(Error, "Unrecognized error from liblzma: %d", lzret); + PyErr_Format(state->error, "Unrecognized error from liblzma: %d", lzret); return 1; } } @@ -107,8 +168,9 @@ catch_lzma_error(lzma_ret lzret) static void* PyLzma_Malloc(void *opaque, size_t items, size_t size) { - if (size != 0 && items > (size_t)PY_SSIZE_T_MAX / size) + if (size != 0 && items > (size_t)PY_SSIZE_T_MAX / size) { return NULL; + } /* PyMem_Malloc() cannot be used: the GIL is not held when lzma_code() is called */ return PyMem_RawMalloc(items * size); @@ -120,24 +182,6 @@ PyLzma_Free(void *opaque, void *ptr) PyMem_RawFree(ptr); } -#if BUFSIZ < 8192 -#define INITIAL_BUFFER_SIZE 8192 -#else -#define INITIAL_BUFFER_SIZE BUFSIZ -#endif - -static int -grow_buffer(PyObject **buf, Py_ssize_t max_length) -{ - Py_ssize_t size = PyBytes_GET_SIZE(*buf); - Py_ssize_t newsize = size + (size >> 3) + 6; - - if (max_length > 0 && newsize > max_length) - newsize = max_length; - - return _PyBytes_Resize(buf, newsize); -} - /* Some custom type conversions for PyArg_ParseTupleAndKeywords(), since the predefined conversion specifiers do not suit our needs: @@ -186,7 +230,7 @@ INT_TYPE_CONVERTER_FUNC(lzma_match_finder, lzma_mf_converter) the C lzma_filter structs expected by liblzma. */ static void * -parse_filter_spec_lzma(PyObject *spec) +parse_filter_spec_lzma(_lzma_state *state, PyObject *spec) { static char *optnames[] = {"id", "preset", "dict_size", "lc", "lp", "pb", "mode", "nice_len", "mf", "depth", NULL}; @@ -200,28 +244,32 @@ parse_filter_spec_lzma(PyObject *spec) preset_obj = PyMapping_GetItemString(spec, "preset"); if (preset_obj == NULL) { - if (PyErr_ExceptionMatches(PyExc_KeyError)) + if (PyErr_ExceptionMatches(PyExc_KeyError)) { PyErr_Clear(); - else + } + else { return NULL; + } } else { int ok = uint32_converter(preset_obj, &preset); Py_DECREF(preset_obj); - if (!ok) + if (!ok) { return NULL; + } } options = (lzma_options_lzma *)PyMem_Calloc(1, sizeof *options); - if (options == NULL) + if (options == NULL) { return PyErr_NoMemory(); + } if (lzma_lzma_preset(options, preset)) { PyMem_Free(options); - PyErr_Format(Error, "Invalid compression preset: %u", preset); + PyErr_Format(state->error, "Invalid compression preset: %u", preset); return NULL; } - if (!PyArg_ParseTupleAndKeywords(empty_tuple, spec, + if (!PyArg_ParseTupleAndKeywords(state->empty_tuple, spec, "|OOO&O&O&O&O&O&O&O&", optnames, &id, &preset_obj, uint32_converter, &options->dict_size, @@ -235,20 +283,21 @@ parse_filter_spec_lzma(PyObject *spec) PyErr_SetString(PyExc_ValueError, "Invalid filter specifier for LZMA filter"); PyMem_Free(options); - options = NULL; + return NULL; } + return options; } static void * -parse_filter_spec_delta(PyObject *spec) +parse_filter_spec_delta(_lzma_state *state, PyObject *spec) { static char *optnames[] = {"id", "dist", NULL}; PyObject *id; uint32_t dist = 1; lzma_options_delta *options; - if (!PyArg_ParseTupleAndKeywords(empty_tuple, spec, "|OO&", optnames, + if (!PyArg_ParseTupleAndKeywords(state->empty_tuple, spec, "|OO&", optnames, &id, uint32_converter, &dist)) { PyErr_SetString(PyExc_ValueError, "Invalid filter specifier for delta filter"); @@ -256,22 +305,23 @@ parse_filter_spec_delta(PyObject *spec) } options = (lzma_options_delta *)PyMem_Calloc(1, sizeof *options); - if (options == NULL) + if (options == NULL) { return PyErr_NoMemory(); + } options->type = LZMA_DELTA_TYPE_BYTE; options->dist = dist; return options; } static void * -parse_filter_spec_bcj(PyObject *spec) +parse_filter_spec_bcj(_lzma_state *state, PyObject *spec) { static char *optnames[] = {"id", "start_offset", NULL}; PyObject *id; uint32_t start_offset = 0; lzma_options_bcj *options; - if (!PyArg_ParseTupleAndKeywords(empty_tuple, spec, "|OO&", optnames, + if (!PyArg_ParseTupleAndKeywords(state->empty_tuple, spec, "|OO&", optnames, &id, uint32_converter, &start_offset)) { PyErr_SetString(PyExc_ValueError, "Invalid filter specifier for BCJ filter"); @@ -279,14 +329,15 @@ parse_filter_spec_bcj(PyObject *spec) } options = (lzma_options_bcj *)PyMem_Calloc(1, sizeof *options); - if (options == NULL) + if (options == NULL) { return PyErr_NoMemory(); + } options->start_offset = start_offset; return options; } static int -lzma_filter_converter(PyObject *spec, void *ptr) +lzma_filter_converter(_lzma_state *state, PyObject *spec, void *ptr) { lzma_filter *f = (lzma_filter *)ptr; PyObject *id_obj; @@ -305,16 +356,17 @@ lzma_filter_converter(PyObject *spec, void *ptr) } f->id = PyLong_AsUnsignedLongLong(id_obj); Py_DECREF(id_obj); - if (PyErr_Occurred()) + if (PyErr_Occurred()) { return 0; + } switch (f->id) { case LZMA_FILTER_LZMA1: case LZMA_FILTER_LZMA2: - f->options = parse_filter_spec_lzma(spec); + f->options = parse_filter_spec_lzma(state, spec); return f->options != NULL; case LZMA_FILTER_DELTA: - f->options = parse_filter_spec_delta(spec); + f->options = parse_filter_spec_delta(state, spec); return f->options != NULL; case LZMA_FILTER_X86: case LZMA_FILTER_POWERPC: @@ -322,7 +374,7 @@ lzma_filter_converter(PyObject *spec, void *ptr) case LZMA_FILTER_ARM: case LZMA_FILTER_ARMTHUMB: case LZMA_FILTER_SPARC: - f->options = parse_filter_spec_bcj(spec); + f->options = parse_filter_spec_bcj(state, spec); return f->options != NULL; default: PyErr_Format(PyExc_ValueError, "Invalid filter ID: %llu", f->id); @@ -333,20 +385,20 @@ lzma_filter_converter(PyObject *spec, void *ptr) static void free_filter_chain(lzma_filter filters[]) { - int i; - - for (i = 0; filters[i].id != LZMA_VLI_UNKNOWN; i++) + for (int i = 0; filters[i].id != LZMA_VLI_UNKNOWN; i++) { PyMem_Free(filters[i].options); + } } static int -parse_filter_chain_spec(lzma_filter filters[], PyObject *filterspecs) +parse_filter_chain_spec(_lzma_state *state, lzma_filter filters[], PyObject *filterspecs) { Py_ssize_t i, num_filters; num_filters = PySequence_Length(filterspecs); - if (num_filters == -1) + if (num_filters == -1) { return -1; + } if (num_filters > LZMA_FILTERS_MAX) { PyErr_Format(PyExc_ValueError, "Too many filters - liblzma supports a maximum of %d", @@ -357,8 +409,9 @@ parse_filter_chain_spec(lzma_filter filters[], PyObject *filterspecs) for (i = 0; i < num_filters; i++) { int ok = 1; PyObject *spec = PySequence_GetItem(filterspecs, i); - if (spec == NULL || !lzma_filter_converter(spec, &filters[i])) + if (spec == NULL || !lzma_filter_converter(state, spec, &filters[i])) { ok = 0; + } Py_XDECREF(spec); if (!ok) { filters[i].id = LZMA_VLI_UNKNOWN; @@ -383,8 +436,9 @@ spec_add_field(PyObject *spec, _Py_Identifier *key, unsigned long long value) PyObject *value_object; value_object = PyLong_FromUnsignedLongLong(value); - if (value_object == NULL) + if (value_object == NULL) { return -1; + } status = _PyDict_SetItemId(spec, key, value_object); Py_DECREF(value_object); @@ -397,8 +451,9 @@ build_filter_spec(const lzma_filter *f) PyObject *spec; spec = PyDict_New(); - if (spec == NULL) + if (spec == NULL) { return NULL; + } #define ADD_FIELD(SOURCE, FIELD) \ do { \ @@ -490,44 +545,47 @@ class lzma_filter_converter(CConverter): static PyObject * compress(Compressor *c, uint8_t *data, size_t len, lzma_action action) { - Py_ssize_t data_size = 0; PyObject *result; + _BlocksOutputBuffer buffer = {.list = NULL}; + _lzma_state *state = PyType_GetModuleState(Py_TYPE(c)); + assert(state != NULL); - result = PyBytes_FromStringAndSize(NULL, INITIAL_BUFFER_SIZE); - if (result == NULL) - return NULL; + if (OutputBuffer_InitAndGrow(&buffer, -1, &c->lzs.next_out, &c->lzs.avail_out) < 0) { + goto error; + } c->lzs.next_in = data; c->lzs.avail_in = len; - c->lzs.next_out = (uint8_t *)PyBytes_AS_STRING(result); - c->lzs.avail_out = PyBytes_GET_SIZE(result); + for (;;) { lzma_ret lzret; Py_BEGIN_ALLOW_THREADS lzret = lzma_code(&c->lzs, action); - data_size = (char *)c->lzs.next_out - PyBytes_AS_STRING(result); - if (lzret == LZMA_BUF_ERROR && len == 0 && c->lzs.avail_out > 0) - lzret = LZMA_OK; /* That wasn't a real error */ Py_END_ALLOW_THREADS - if (catch_lzma_error(lzret)) + + if (lzret == LZMA_BUF_ERROR && len == 0 && c->lzs.avail_out > 0) { + lzret = LZMA_OK; /* That wasn't a real error */ + } + if (catch_lzma_error(state, lzret)) { goto error; + } if ((action == LZMA_RUN && c->lzs.avail_in == 0) || (action == LZMA_FINISH && lzret == LZMA_STREAM_END)) { break; } else if (c->lzs.avail_out == 0) { - if (grow_buffer(&result, -1) == -1) + if (OutputBuffer_Grow(&buffer, &c->lzs.next_out, &c->lzs.avail_out) < 0) { goto error; - c->lzs.next_out = (uint8_t *)PyBytes_AS_STRING(result) + data_size; - c->lzs.avail_out = PyBytes_GET_SIZE(result) - data_size; + } } } - if (data_size != PyBytes_GET_SIZE(result)) - if (_PyBytes_Resize(&result, data_size) == -1) - goto error; - return result; + + result = OutputBuffer_Finish(&buffer, c->lzs.avail_out); + if (result != NULL) { + return result; + } error: - Py_XDECREF(result); + OutputBuffer_OnError(&buffer); return NULL; } @@ -552,10 +610,12 @@ _lzma_LZMACompressor_compress_impl(Compressor *self, Py_buffer *data) PyObject *result = NULL; ACQUIRE_LOCK(self); - if (self->flushed) + if (self->flushed) { PyErr_SetString(PyExc_ValueError, "Compressor has been flushed"); - else + } + else { result = compress(self, data->buf, data->len, LZMA_RUN); + } RELEASE_LOCK(self); return result; } @@ -588,8 +648,8 @@ _lzma_LZMACompressor_flush_impl(Compressor *self) } static int -Compressor_init_xz(lzma_stream *lzs, int check, uint32_t preset, - PyObject *filterspecs) +Compressor_init_xz(_lzma_state *state, lzma_stream *lzs, + int check, uint32_t preset, PyObject *filterspecs) { lzma_ret lzret; @@ -598,19 +658,21 @@ Compressor_init_xz(lzma_stream *lzs, int check, uint32_t preset, } else { lzma_filter filters[LZMA_FILTERS_MAX + 1]; - if (parse_filter_chain_spec(filters, filterspecs) == -1) + if (parse_filter_chain_spec(state, filters, filterspecs) == -1) return -1; lzret = lzma_stream_encoder(lzs, filters, check); free_filter_chain(filters); } - if (catch_lzma_error(lzret)) + if (catch_lzma_error(state, lzret)) { return -1; - else + } + else { return 0; + } } static int -Compressor_init_alone(lzma_stream *lzs, uint32_t preset, PyObject *filterspecs) +Compressor_init_alone(_lzma_state *state, lzma_stream *lzs, uint32_t preset, PyObject *filterspecs) { lzma_ret lzret; @@ -618,14 +680,14 @@ Compressor_init_alone(lzma_stream *lzs, uint32_t preset, PyObject *filterspecs) lzma_options_lzma options; if (lzma_lzma_preset(&options, preset)) { - PyErr_Format(Error, "Invalid compression preset: %u", preset); + PyErr_Format(state->error, "Invalid compression preset: %u", preset); return -1; } lzret = lzma_alone_encoder(lzs, &options); } else { lzma_filter filters[LZMA_FILTERS_MAX + 1]; - if (parse_filter_chain_spec(filters, filterspecs) == -1) + if (parse_filter_chain_spec(state, filters, filterspecs) == -1) return -1; if (filters[0].id == LZMA_FILTER_LZMA1 && filters[1].id == LZMA_VLI_UNKNOWN) { @@ -638,14 +700,16 @@ Compressor_init_alone(lzma_stream *lzs, uint32_t preset, PyObject *filterspecs) } free_filter_chain(filters); } - if (PyErr_Occurred() || catch_lzma_error(lzret)) + if (PyErr_Occurred() || catch_lzma_error(state, lzret)) { return -1; - else + } + else { return 0; + } } static int -Compressor_init_raw(lzma_stream *lzs, PyObject *filterspecs) +Compressor_init_raw(_lzma_state *state, lzma_stream *lzs, PyObject *filterspecs) { lzma_filter filters[LZMA_FILTERS_MAX + 1]; lzma_ret lzret; @@ -655,14 +719,17 @@ Compressor_init_raw(lzma_stream *lzs, PyObject *filterspecs) "Must specify filters for FORMAT_RAW"); return -1; } - if (parse_filter_chain_spec(filters, filterspecs) == -1) + if (parse_filter_chain_spec(state, filters, filterspecs) == -1) { return -1; + } lzret = lzma_raw_encoder(lzs, filters); free_filter_chain(filters); - if (catch_lzma_error(lzret)) + if (catch_lzma_error(state, lzret)) { return -1; - else + } + else { return 0; + } } /*[-clinic input] @@ -706,12 +773,14 @@ Compressor_init(Compressor *self, PyObject *args, PyObject *kwargs) uint32_t preset = LZMA_PRESET_DEFAULT; PyObject *preset_obj = Py_None; PyObject *filterspecs = Py_None; - + _lzma_state *state = PyType_GetModuleState(Py_TYPE(self)); + assert(state != NULL); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iiOO:LZMACompressor", arg_names, &format, &check, &preset_obj, - &filterspecs)) + &filterspecs)) { return -1; + } if (format != FORMAT_XZ && check != -1 && check != LZMA_CHECK_NONE) { PyErr_SetString(PyExc_ValueError, @@ -725,9 +794,11 @@ Compressor_init(Compressor *self, PyObject *args, PyObject *kwargs) return -1; } - if (preset_obj != Py_None) - if (!uint32_converter(preset_obj, &preset)) + if (preset_obj != Py_None) { + if (!uint32_converter(preset_obj, &preset)) { return -1; + } + } self->alloc.opaque = NULL; self->alloc.alloc = PyLzma_Malloc; @@ -743,20 +814,24 @@ Compressor_init(Compressor *self, PyObject *args, PyObject *kwargs) self->flushed = 0; switch (format) { case FORMAT_XZ: - if (check == -1) + if (check == -1) { check = LZMA_CHECK_CRC64; - if (Compressor_init_xz(&self->lzs, check, preset, filterspecs) != 0) + } + if (Compressor_init_xz(state, &self->lzs, check, preset, filterspecs) != 0) { break; + } return 0; case FORMAT_ALONE: - if (Compressor_init_alone(&self->lzs, preset, filterspecs) != 0) + if (Compressor_init_alone(state, &self->lzs, preset, filterspecs) != 0) { break; + } return 0; case FORMAT_RAW: - if (Compressor_init_raw(&self->lzs, filterspecs) != 0) + if (Compressor_init_raw(state, &self->lzs, filterspecs) != 0) { break; + } return 0; default: @@ -774,9 +849,12 @@ static void Compressor_dealloc(Compressor *self) { lzma_end(&self->lzs); - if (self->lock != NULL) + if (self->lock != NULL) { PyThread_free_lock(self->lock); - Py_TYPE(self)->tp_free((PyObject *)self); + } + PyTypeObject *tp = Py_TYPE(self); + tp->tp_free((PyObject *)self); + Py_DECREF(tp); } static PyMethodDef Compressor_methods[] = { @@ -785,6 +863,13 @@ static PyMethodDef Compressor_methods[] = { {NULL} }; +static int +Compressor_traverse(Compressor *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + return 0; +} + PyDoc_STRVAR(Compressor_doc, "LZMACompressor(format=FORMAT_XZ, check=-1, preset=None, filters=None)\n" "\n" @@ -813,47 +898,26 @@ PyDoc_STRVAR(Compressor_doc, "\n" "For one-shot compression, use the compress() function instead.\n"); -static PyTypeObject Compressor_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_lzma.LZMACompressor", /* tp_name */ - sizeof(Compressor), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)Compressor_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - Compressor_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - Compressor_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)Compressor_init, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ +static PyType_Slot lzma_compressor_type_slots[] = { + {Py_tp_dealloc, Compressor_dealloc}, + {Py_tp_methods, Compressor_methods}, + {Py_tp_init, Compressor_init}, + {Py_tp_new, PyType_GenericNew}, + {Py_tp_doc, (char *)Compressor_doc}, + {Py_tp_traverse, Compressor_traverse}, + {0, 0} }; +static PyType_Spec lzma_compressor_type_spec = { + .name = "_lzma.LZMACompressor", + .basicsize = sizeof(Compressor), + // Calling PyType_GetModuleState() on a subclass is not safe. + // lzma_compressor_type_spec does not have Py_TPFLAGS_BASETYPE flag + // which prevents to create a subclass. + // So calling PyType_GetModuleState() in this file is always safe. + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE), + .slots = lzma_compressor_type_slots, +}; /* LZMADecompressor class. */ @@ -864,34 +928,32 @@ static PyTypeObject Compressor_type = { static PyObject* decompress_buf(Decompressor *d, Py_ssize_t max_length) { - Py_ssize_t data_size = 0; PyObject *result; lzma_stream *lzs = &d->lzs; + _BlocksOutputBuffer buffer = {.list = NULL}; + _lzma_state *state = PyType_GetModuleState(Py_TYPE(d)); + assert(state != NULL); - if (max_length < 0 || max_length >= INITIAL_BUFFER_SIZE) - result = PyBytes_FromStringAndSize(NULL, INITIAL_BUFFER_SIZE); - else - result = PyBytes_FromStringAndSize(NULL, max_length); - if (result == NULL) - return NULL; - - lzs->next_out = (uint8_t *)PyBytes_AS_STRING(result); - lzs->avail_out = PyBytes_GET_SIZE(result); + if (OutputBuffer_InitAndGrow(&buffer, max_length, &lzs->next_out, &lzs->avail_out) < 0) { + goto error; + } for (;;) { lzma_ret lzret; Py_BEGIN_ALLOW_THREADS lzret = lzma_code(lzs, LZMA_RUN); - data_size = (char *)lzs->next_out - PyBytes_AS_STRING(result); - if (lzret == LZMA_BUF_ERROR && lzs->avail_in == 0 && lzs->avail_out > 0) - lzret = LZMA_OK; /* That wasn't a real error */ Py_END_ALLOW_THREADS - if (catch_lzma_error(lzret)) + if (lzret == LZMA_BUF_ERROR && lzs->avail_in == 0 && lzs->avail_out > 0) { + lzret = LZMA_OK; /* That wasn't a real error */ + } + if (catch_lzma_error(state, lzret)) { goto error; - if (lzret == LZMA_GET_CHECK || lzret == LZMA_NO_CHECK) + } + if (lzret == LZMA_GET_CHECK || lzret == LZMA_NO_CHECK) { d->check = lzma_get_check(&d->lzs); + } if (lzret == LZMA_STREAM_END) { d->eof = 1; break; @@ -900,24 +962,24 @@ decompress_buf(Decompressor *d, Py_ssize_t max_length) Maybe lzs's internal state still have a few bytes can be output, grow the output buffer and continue if max_lengh < 0. */ - if (data_size == max_length) + if (OutputBuffer_GetDataSize(&buffer, lzs->avail_out) == max_length) { break; - if (grow_buffer(&result, max_length) == -1) + } + if (OutputBuffer_Grow(&buffer, &lzs->next_out, &lzs->avail_out) < 0) { goto error; - lzs->next_out = (uint8_t *)PyBytes_AS_STRING(result) + data_size; - lzs->avail_out = PyBytes_GET_SIZE(result) - data_size; + } } else if (lzs->avail_in == 0) { break; } } - if (data_size != PyBytes_GET_SIZE(result)) - if (_PyBytes_Resize(&result, data_size) == -1) - goto error; - return result; + result = OutputBuffer_Finish(&buffer, lzs->avail_out); + if (result != NULL) { + return result; + } error: - Py_XDECREF(result); + OutputBuffer_OnError(&buffer); return NULL; } @@ -984,8 +1046,9 @@ decompress(Decompressor *d, uint8_t *data, size_t len, Py_ssize_t max_length) if (lzs->avail_in > 0) { Py_XSETREF(d->unused_data, PyBytes_FromStringAndSize((char *)lzs->next_in, lzs->avail_in)); - if (d->unused_data == NULL) + if (d->unused_data == NULL) { goto error; + } } } else if (lzs->avail_in == 0) { @@ -997,7 +1060,7 @@ decompress(Decompressor *d, uint8_t *data, size_t len, Py_ssize_t max_length) be output, try to output them next time. */ d->needs_input = 0; - /* if max_length < 0, lzs->avail_out always > 0 */ + /* If max_length < 0, lzs->avail_out always > 0 */ assert(max_length >= 0); } else { /* Input buffer exhausted, output buffer has space. */ @@ -1082,19 +1145,22 @@ _lzma_LZMADecompressor_decompress_impl(Decompressor *self, Py_buffer *data, } static int -Decompressor_init_raw(lzma_stream *lzs, PyObject *filterspecs) +Decompressor_init_raw(_lzma_state *state, lzma_stream *lzs, PyObject *filterspecs) { lzma_filter filters[LZMA_FILTERS_MAX + 1]; lzma_ret lzret; - if (parse_filter_chain_spec(filters, filterspecs) == -1) + if (parse_filter_chain_spec(state, filters, filterspecs) == -1) { return -1; + } lzret = lzma_raw_decoder(lzs, filters); free_filter_chain(filters); - if (catch_lzma_error(lzret)) + if (catch_lzma_error(state, lzret)) { return -1; - else + } + else { return 0; + } } /*[clinic input] @@ -1130,6 +1196,8 @@ _lzma_LZMADecompressor___init___impl(Decompressor *self, int format, const uint32_t decoder_flags = LZMA_TELL_ANY_CHECK | LZMA_TELL_NO_CHECK; uint64_t memlimit_ = UINT64_MAX; lzma_ret lzret; + _lzma_state *state = PyType_GetModuleState(Py_TYPE(self)); + assert(state != NULL); if (memlimit != Py_None) { if (format == FORMAT_RAW) { @@ -1138,8 +1206,9 @@ _lzma_LZMADecompressor___init___impl(Decompressor *self, int format, return -1; } memlimit_ = PyLong_AsUnsignedLongLong(memlimit); - if (PyErr_Occurred()) + if (PyErr_Occurred()) { return -1; + } } if (format == FORMAT_RAW && filters == Py_None) { @@ -1173,33 +1242,38 @@ _lzma_LZMADecompressor___init___impl(Decompressor *self, int format, self->input_buffer = NULL; self->input_buffer_size = 0; Py_XSETREF(self->unused_data, PyBytes_FromStringAndSize(NULL, 0)); - if (self->unused_data == NULL) + if (self->unused_data == NULL) { goto error; + } switch (format) { case FORMAT_AUTO: lzret = lzma_auto_decoder(&self->lzs, memlimit_, decoder_flags); - if (catch_lzma_error(lzret)) + if (catch_lzma_error(state, lzret)) { break; + } return 0; case FORMAT_XZ: lzret = lzma_stream_decoder(&self->lzs, memlimit_, decoder_flags); - if (catch_lzma_error(lzret)) + if (catch_lzma_error(state, lzret)) { break; + } return 0; case FORMAT_ALONE: self->check = LZMA_CHECK_NONE; lzret = lzma_alone_decoder(&self->lzs, memlimit_); - if (catch_lzma_error(lzret)) + if (catch_lzma_error(state, lzret)) { break; + } return 0; case FORMAT_RAW: self->check = LZMA_CHECK_NONE; - if (Decompressor_init_raw(&self->lzs, filters) == -1) + if (Decompressor_init_raw(state, &self->lzs, filters) == -1) { break; + } return 0; default: @@ -1223,9 +1297,19 @@ Decompressor_dealloc(Decompressor *self) lzma_end(&self->lzs); Py_CLEAR(self->unused_data); - if (self->lock != NULL) + if (self->lock != NULL) { PyThread_free_lock(self->lock); - Py_TYPE(self)->tp_free((PyObject *)self); + } + PyTypeObject *tp = Py_TYPE(self); + tp->tp_free((PyObject *)self); + Py_DECREF(tp); +} + +static int +Decompressor_traverse(Decompressor *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + return 0; } static PyMethodDef Decompressor_methods[] = { @@ -1257,45 +1341,26 @@ static PyMemberDef Decompressor_members[] = { {NULL} }; -static PyTypeObject Decompressor_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_lzma.LZMADecompressor", /* tp_name */ - sizeof(Decompressor), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)Decompressor_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - _lzma_LZMADecompressor___init____doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - Decompressor_methods, /* tp_methods */ - Decompressor_members, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - _lzma_LZMADecompressor___init__, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ +static PyType_Slot lzma_decompressor_type_slots[] = { + {Py_tp_dealloc, Decompressor_dealloc}, + {Py_tp_methods, Decompressor_methods}, + {Py_tp_init, _lzma_LZMADecompressor___init__}, + {Py_tp_new, PyType_GenericNew}, + {Py_tp_doc, (char *)_lzma_LZMADecompressor___init____doc__}, + {Py_tp_traverse, Decompressor_traverse}, + {Py_tp_members, Decompressor_members}, + {0, 0} +}; + +static PyType_Spec lzma_decompressor_type_spec = { + .name = "_lzma.LZMADecompressor", + .basicsize = sizeof(Decompressor), + // Calling PyType_GetModuleState() on a subclass is not safe. + // lzma_decompressor_type_spec does not have Py_TPFLAGS_BASETYPE flag + // which prevents to create a subclass. + // So calling PyType_GetModuleState() in this file is always safe. + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE), + .slots = lzma_decompressor_type_slots, }; @@ -1318,27 +1383,52 @@ _lzma_is_check_supported_impl(PyObject *module, int check_id) return PyBool_FromLong(lzma_check_is_supported(check_id)); } +PyDoc_STRVAR(_lzma__encode_filter_properties__doc__, +"_encode_filter_properties($module, filter, /)\n" +"--\n" +"\n" +"Return a bytes object encoding the options (properties) of the filter specified by *filter* (a dict).\n" +"\n" +"The result does not include the filter ID itself, only the options."); -/*[clinic input] -_lzma._encode_filter_properties - filter: lzma_filter(c_default="{LZMA_VLI_UNKNOWN, NULL}") - / +#define _LZMA__ENCODE_FILTER_PROPERTIES_METHODDEF \ + {"_encode_filter_properties", (PyCFunction)_lzma__encode_filter_properties, METH_O, _lzma__encode_filter_properties__doc__}, -Return a bytes object encoding the options (properties) of the filter specified by *filter* (a dict). +static PyObject * +_lzma__encode_filter_properties_impl(PyObject *module, lzma_filter filter); -The result does not include the filter ID itself, only the options. -[clinic start generated code]*/ +static PyObject * +_lzma__encode_filter_properties(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + lzma_filter filter = {LZMA_VLI_UNKNOWN, NULL}; + _lzma_state *state = get_lzma_state(module); + assert(state != NULL); + if (!lzma_filter_converter(state, arg, &filter)) { + goto exit; + } + return_value = _lzma__encode_filter_properties_impl(module, filter); + +exit: + /* Cleanup for filter */ + if (filter.id != LZMA_VLI_UNKNOWN) { + PyMem_Free(filter.options); + } + + return return_value; +} static PyObject * _lzma__encode_filter_properties_impl(PyObject *module, lzma_filter filter) -/*[clinic end generated code: output=5c93c8e14e7be5a8 input=d4c64f1b557c77d4]*/ { lzma_ret lzret; uint32_t encoded_size; PyObject *result = NULL; + _lzma_state *state = get_lzma_state(module); + assert(state != NULL); lzret = lzma_properties_size(&encoded_size, &filter); - if (catch_lzma_error(lzret)) + if (catch_lzma_error(state, lzret)) goto error; result = PyBytes_FromStringAndSize(NULL, encoded_size); @@ -1347,8 +1437,9 @@ _lzma__encode_filter_properties_impl(PyObject *module, lzma_filter filter) lzret = lzma_properties_encode( &filter, (uint8_t *)PyBytes_AS_STRING(result)); - if (catch_lzma_error(lzret)) + if (catch_lzma_error(state, lzret)) { goto error; + } return result; @@ -1378,11 +1469,14 @@ _lzma__decode_filter_properties_impl(PyObject *module, lzma_vli filter_id, lzma_ret lzret; PyObject *result = NULL; filter.id = filter_id; + _lzma_state *state = get_lzma_state(module); + assert(state != NULL); lzret = lzma_properties_decode( &filter, NULL, encoded_props->buf, encoded_props->len); - if (catch_lzma_error(lzret)) + if (catch_lzma_error(state, lzret)) { return NULL; + } result = build_filter_spec(&filter); @@ -1392,103 +1486,162 @@ _lzma__decode_filter_properties_impl(PyObject *module, lzma_vli filter_id, return result; } - -/* Module initialization. */ - -static PyMethodDef module_methods[] = { - _LZMA_IS_CHECK_SUPPORTED_METHODDEF - _LZMA__ENCODE_FILTER_PROPERTIES_METHODDEF - _LZMA__DECODE_FILTER_PROPERTIES_METHODDEF - {NULL} -}; - -static PyModuleDef _lzmamodule = { - PyModuleDef_HEAD_INIT, - "_lzma", - NULL, - -1, - module_methods, - NULL, - NULL, - NULL, - NULL, -}; - /* Some of our constants are more than 32 bits wide, so PyModule_AddIntConstant would not work correctly on platforms with 32-bit longs. */ static int module_add_int_constant(PyObject *m, const char *name, long long value) { PyObject *o = PyLong_FromLongLong(value); - if (o == NULL) + if (o == NULL) { return -1; - if (PyModule_AddObject(m, name, o) == 0) + } + if (PyModule_AddObject(m, name, o) == 0) { return 0; + } Py_DECREF(o); return -1; } -#define ADD_INT_PREFIX_MACRO(m, macro) \ - module_add_int_constant(m, #macro, LZMA_ ## macro) - -PyMODINIT_FUNC -PyInit__lzma(void) +static int +lzma_exec(PyObject *module) { - PyObject *m; +#define ADD_INT_PREFIX_MACRO(module, macro) \ + do { \ + if (module_add_int_constant(module, #macro, LZMA_ ## macro) < 0) { \ + return -1; \ + } \ + } while(0) + +#define ADD_INT_MACRO(module, macro) \ + do { \ + if (PyModule_AddIntMacro(module, macro) < 0) { \ + return -1; \ + } \ + } while (0) - empty_tuple = PyTuple_New(0); - if (empty_tuple == NULL) - return NULL; - m = PyModule_Create(&_lzmamodule); - if (m == NULL) - return NULL; + _lzma_state *state = get_lzma_state(module); - if (PyModule_AddIntMacro(m, FORMAT_AUTO) == -1 || - PyModule_AddIntMacro(m, FORMAT_XZ) == -1 || - PyModule_AddIntMacro(m, FORMAT_ALONE) == -1 || - PyModule_AddIntMacro(m, FORMAT_RAW) == -1 || - ADD_INT_PREFIX_MACRO(m, CHECK_NONE) == -1 || - ADD_INT_PREFIX_MACRO(m, CHECK_CRC32) == -1 || - ADD_INT_PREFIX_MACRO(m, CHECK_CRC64) == -1 || - ADD_INT_PREFIX_MACRO(m, CHECK_SHA256) == -1 || - ADD_INT_PREFIX_MACRO(m, CHECK_ID_MAX) == -1 || - ADD_INT_PREFIX_MACRO(m, CHECK_UNKNOWN) == -1 || - ADD_INT_PREFIX_MACRO(m, FILTER_LZMA1) == -1 || - ADD_INT_PREFIX_MACRO(m, FILTER_LZMA2) == -1 || - ADD_INT_PREFIX_MACRO(m, FILTER_DELTA) == -1 || - ADD_INT_PREFIX_MACRO(m, FILTER_X86) == -1 || - ADD_INT_PREFIX_MACRO(m, FILTER_IA64) == -1 || - ADD_INT_PREFIX_MACRO(m, FILTER_ARM) == -1 || - ADD_INT_PREFIX_MACRO(m, FILTER_ARMTHUMB) == -1 || - ADD_INT_PREFIX_MACRO(m, FILTER_SPARC) == -1 || - ADD_INT_PREFIX_MACRO(m, FILTER_POWERPC) == -1 || - ADD_INT_PREFIX_MACRO(m, MF_HC3) == -1 || - ADD_INT_PREFIX_MACRO(m, MF_HC4) == -1 || - ADD_INT_PREFIX_MACRO(m, MF_BT2) == -1 || - ADD_INT_PREFIX_MACRO(m, MF_BT3) == -1 || - ADD_INT_PREFIX_MACRO(m, MF_BT4) == -1 || - ADD_INT_PREFIX_MACRO(m, MODE_FAST) == -1 || - ADD_INT_PREFIX_MACRO(m, MODE_NORMAL) == -1 || - ADD_INT_PREFIX_MACRO(m, PRESET_DEFAULT) == -1 || - ADD_INT_PREFIX_MACRO(m, PRESET_EXTREME) == -1) - return NULL; + state->empty_tuple = PyTuple_New(0); + if (state->empty_tuple == NULL) { + return -1; + } - Error = PyErr_NewExceptionWithDoc( - "_lzma.LZMAError", "Call to liblzma failed.", NULL, NULL); - if (Error == NULL) - return NULL; - Py_INCREF(Error); - if (PyModule_AddObject(m, "LZMAError", Error) == -1) - return NULL; + ADD_INT_MACRO(module, FORMAT_AUTO); + ADD_INT_MACRO(module, FORMAT_XZ); + ADD_INT_MACRO(module, FORMAT_ALONE); + ADD_INT_MACRO(module, FORMAT_RAW); + ADD_INT_PREFIX_MACRO(module, CHECK_NONE); + ADD_INT_PREFIX_MACRO(module, CHECK_CRC32); + ADD_INT_PREFIX_MACRO(module, CHECK_CRC64); + ADD_INT_PREFIX_MACRO(module, CHECK_SHA256); + ADD_INT_PREFIX_MACRO(module, CHECK_ID_MAX); + ADD_INT_PREFIX_MACRO(module, CHECK_UNKNOWN); + ADD_INT_PREFIX_MACRO(module, FILTER_LZMA1); + ADD_INT_PREFIX_MACRO(module, FILTER_LZMA2); + ADD_INT_PREFIX_MACRO(module, FILTER_DELTA); + ADD_INT_PREFIX_MACRO(module, FILTER_X86); + ADD_INT_PREFIX_MACRO(module, FILTER_IA64); + ADD_INT_PREFIX_MACRO(module, FILTER_ARM); + ADD_INT_PREFIX_MACRO(module, FILTER_ARMTHUMB); + ADD_INT_PREFIX_MACRO(module, FILTER_SPARC); + ADD_INT_PREFIX_MACRO(module, FILTER_POWERPC); + ADD_INT_PREFIX_MACRO(module, MF_HC3); + ADD_INT_PREFIX_MACRO(module, MF_HC4); + ADD_INT_PREFIX_MACRO(module, MF_BT2); + ADD_INT_PREFIX_MACRO(module, MF_BT3); + ADD_INT_PREFIX_MACRO(module, MF_BT4); + ADD_INT_PREFIX_MACRO(module, MODE_FAST); + ADD_INT_PREFIX_MACRO(module, MODE_NORMAL); + ADD_INT_PREFIX_MACRO(module, PRESET_DEFAULT); + ADD_INT_PREFIX_MACRO(module, PRESET_EXTREME); + + state->error = PyErr_NewExceptionWithDoc("_lzma.LZMAError", "Call to liblzma failed.", NULL, NULL); + if (state->error == NULL) { + return -1; + } - if (PyModule_AddType(m, &Compressor_type) < 0) { - return NULL; + if (PyModule_AddType(module, (PyTypeObject *)state->error) < 0) { + return -1; } - if (PyModule_AddType(m, &Decompressor_type) < 0) { - return NULL; + + state->lzma_compressor_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, + &lzma_compressor_type_spec, NULL); + if (state->lzma_compressor_type == NULL) { + return -1; + } + + if (PyModule_AddType(module, state->lzma_compressor_type) < 0) { + return -1; + } + + state->lzma_decompressor_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, + &lzma_decompressor_type_spec, NULL); + if (state->lzma_decompressor_type == NULL) { + return -1; + } + + if (PyModule_AddType(module, state->lzma_decompressor_type) < 0) { + return -1; } - return m; + return 0; +} + +static PyMethodDef lzma_methods[] = { + _LZMA_IS_CHECK_SUPPORTED_METHODDEF + _LZMA__ENCODE_FILTER_PROPERTIES_METHODDEF + _LZMA__DECODE_FILTER_PROPERTIES_METHODDEF + {NULL} +}; + +static PyModuleDef_Slot lzma_slots[] = { + {Py_mod_exec, lzma_exec}, + {0, NULL} +}; + +static int +lzma_traverse(PyObject *module, visitproc visit, void *arg) +{ + _lzma_state *state = get_lzma_state(module); + Py_VISIT(state->lzma_compressor_type); + Py_VISIT(state->lzma_decompressor_type); + Py_VISIT(state->error); + Py_VISIT(state->empty_tuple); + return 0; +} + +static int +lzma_clear(PyObject *module) +{ + _lzma_state *state = get_lzma_state(module); + Py_CLEAR(state->lzma_compressor_type); + Py_CLEAR(state->lzma_decompressor_type); + Py_CLEAR(state->error); + Py_CLEAR(state->empty_tuple); + return 0; +} + +static void +lzma_free(void *module) +{ + lzma_clear((PyObject *)module); +} + +static PyModuleDef _lzmamodule = { + PyModuleDef_HEAD_INIT, + .m_name = "_lzma", + .m_size = sizeof(_lzma_state), + .m_methods = lzma_methods, + .m_slots = lzma_slots, + .m_traverse = lzma_traverse, + .m_clear = lzma_clear, + .m_free = lzma_free, +}; + +PyMODINIT_FUNC +PyInit__lzma(void) +{ + return PyModuleDef_Init(&_lzmamodule); } diff --git a/contrib/tools/python3/src/Modules/_multiprocessing/clinic/multiprocessing.c.h b/contrib/tools/python3/src/Modules/_multiprocessing/clinic/multiprocessing.c.h new file mode 100644 index 0000000000..7096442bd0 --- /dev/null +++ b/contrib/tools/python3/src/Modules/_multiprocessing/clinic/multiprocessing.c.h @@ -0,0 +1,151 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(_multiprocessing_closesocket__doc__, +"closesocket($module, handle, /)\n" +"--\n" +"\n"); + +#define _MULTIPROCESSING_CLOSESOCKET_METHODDEF \ + {"closesocket", (PyCFunction)_multiprocessing_closesocket, METH_O, _multiprocessing_closesocket__doc__}, + +static PyObject * +_multiprocessing_closesocket_impl(PyObject *module, HANDLE handle); + +static PyObject * +_multiprocessing_closesocket(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + HANDLE handle; + + if (!PyArg_Parse(arg, ""F_HANDLE":closesocket", &handle)) { + goto exit; + } + return_value = _multiprocessing_closesocket_impl(module, handle); + +exit: + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(_multiprocessing_recv__doc__, +"recv($module, handle, size, /)\n" +"--\n" +"\n"); + +#define _MULTIPROCESSING_RECV_METHODDEF \ + {"recv", (PyCFunction)(void(*)(void))_multiprocessing_recv, METH_FASTCALL, _multiprocessing_recv__doc__}, + +static PyObject * +_multiprocessing_recv_impl(PyObject *module, HANDLE handle, int size); + +static PyObject * +_multiprocessing_recv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + HANDLE handle; + int size; + + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"i:recv", + &handle, &size)) { + goto exit; + } + return_value = _multiprocessing_recv_impl(module, handle, size); + +exit: + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(_multiprocessing_send__doc__, +"send($module, handle, buf, /)\n" +"--\n" +"\n"); + +#define _MULTIPROCESSING_SEND_METHODDEF \ + {"send", (PyCFunction)(void(*)(void))_multiprocessing_send, METH_FASTCALL, _multiprocessing_send__doc__}, + +static PyObject * +_multiprocessing_send_impl(PyObject *module, HANDLE handle, Py_buffer *buf); + +static PyObject * +_multiprocessing_send(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + HANDLE handle; + Py_buffer buf = {NULL, NULL}; + + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"y*:send", + &handle, &buf)) { + goto exit; + } + return_value = _multiprocessing_send_impl(module, handle, &buf); + +exit: + /* Cleanup for buf */ + if (buf.obj) { + PyBuffer_Release(&buf); + } + + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +PyDoc_STRVAR(_multiprocessing_sem_unlink__doc__, +"sem_unlink($module, name, /)\n" +"--\n" +"\n"); + +#define _MULTIPROCESSING_SEM_UNLINK_METHODDEF \ + {"sem_unlink", (PyCFunction)_multiprocessing_sem_unlink, METH_O, _multiprocessing_sem_unlink__doc__}, + +static PyObject * +_multiprocessing_sem_unlink_impl(PyObject *module, const char *name); + +static PyObject * +_multiprocessing_sem_unlink(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *name; + + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("sem_unlink", "argument", "str", arg); + goto exit; + } + Py_ssize_t name_length; + name = PyUnicode_AsUTF8AndSize(arg, &name_length); + if (name == NULL) { + goto exit; + } + if (strlen(name) != (size_t)name_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + return_value = _multiprocessing_sem_unlink_impl(module, name); + +exit: + return return_value; +} + +#ifndef _MULTIPROCESSING_CLOSESOCKET_METHODDEF + #define _MULTIPROCESSING_CLOSESOCKET_METHODDEF +#endif /* !defined(_MULTIPROCESSING_CLOSESOCKET_METHODDEF) */ + +#ifndef _MULTIPROCESSING_RECV_METHODDEF + #define _MULTIPROCESSING_RECV_METHODDEF +#endif /* !defined(_MULTIPROCESSING_RECV_METHODDEF) */ + +#ifndef _MULTIPROCESSING_SEND_METHODDEF + #define _MULTIPROCESSING_SEND_METHODDEF +#endif /* !defined(_MULTIPROCESSING_SEND_METHODDEF) */ +/*[clinic end generated code: output=418191c446cd5751 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/_multiprocessing/clinic/posixshmem.c.h b/contrib/tools/python3/src/Modules/_multiprocessing/clinic/posixshmem.c.h index a99f0d2aae..3424b10a56 100644 --- a/contrib/tools/python3/src/Modules/_multiprocessing/clinic/posixshmem.c.h +++ b/contrib/tools/python3/src/Modules/_multiprocessing/clinic/posixshmem.c.h @@ -42,11 +42,6 @@ _posixshmem_shm_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, goto exit; } path = args[0]; - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } flags = _PyLong_AsInt(args[1]); if (flags == -1 && PyErr_Occurred()) { goto exit; @@ -54,11 +49,6 @@ _posixshmem_shm_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, if (!noptargs) { goto skip_optional_pos; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } mode = _PyLong_AsInt(args[2]); if (mode == -1 && PyErr_Occurred()) { goto exit; @@ -130,4 +120,4 @@ exit: #ifndef _POSIXSHMEM_SHM_UNLINK_METHODDEF #define _POSIXSHMEM_SHM_UNLINK_METHODDEF #endif /* !defined(_POSIXSHMEM_SHM_UNLINK_METHODDEF) */ -/*[clinic end generated code: output=9132861c61d8c2d8 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=bca8e78d0f43ef1a input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/_multiprocessing/clinic/semaphore.c.h b/contrib/tools/python3/src/Modules/_multiprocessing/clinic/semaphore.c.h new file mode 100644 index 0000000000..e1b9309e9f --- /dev/null +++ b/contrib/tools/python3/src/Modules/_multiprocessing/clinic/semaphore.c.h @@ -0,0 +1,402 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(_multiprocessing_SemLock_acquire__doc__, +"acquire($self, /, block=True, timeout=None)\n" +"--\n" +"\n" +"Acquire the semaphore/lock."); + +#define _MULTIPROCESSING_SEMLOCK_ACQUIRE_METHODDEF \ + {"acquire", (PyCFunction)(void(*)(void))_multiprocessing_SemLock_acquire, METH_FASTCALL|METH_KEYWORDS, _multiprocessing_SemLock_acquire__doc__}, + +static PyObject * +_multiprocessing_SemLock_acquire_impl(SemLockObject *self, int blocking, + PyObject *timeout_obj); + +static PyObject * +_multiprocessing_SemLock_acquire(SemLockObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"block", "timeout", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "acquire", 0}; + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + int blocking = 1; + PyObject *timeout_obj = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[0]) { + blocking = _PyLong_AsInt(args[0]); + if (blocking == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + timeout_obj = args[1]; +skip_optional_pos: + return_value = _multiprocessing_SemLock_acquire_impl(self, blocking, timeout_obj); + +exit: + return return_value; +} + +#endif /* defined(MS_WINDOWS) */ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(_multiprocessing_SemLock_release__doc__, +"release($self, /)\n" +"--\n" +"\n" +"Release the semaphore/lock."); + +#define _MULTIPROCESSING_SEMLOCK_RELEASE_METHODDEF \ + {"release", (PyCFunction)_multiprocessing_SemLock_release, METH_NOARGS, _multiprocessing_SemLock_release__doc__}, + +static PyObject * +_multiprocessing_SemLock_release_impl(SemLockObject *self); + +static PyObject * +_multiprocessing_SemLock_release(SemLockObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _multiprocessing_SemLock_release_impl(self); +} + +#endif /* defined(MS_WINDOWS) */ + +#if !defined(MS_WINDOWS) + +PyDoc_STRVAR(_multiprocessing_SemLock_acquire__doc__, +"acquire($self, /, block=True, timeout=None)\n" +"--\n" +"\n" +"Acquire the semaphore/lock."); + +#define _MULTIPROCESSING_SEMLOCK_ACQUIRE_METHODDEF \ + {"acquire", (PyCFunction)(void(*)(void))_multiprocessing_SemLock_acquire, METH_FASTCALL|METH_KEYWORDS, _multiprocessing_SemLock_acquire__doc__}, + +static PyObject * +_multiprocessing_SemLock_acquire_impl(SemLockObject *self, int blocking, + PyObject *timeout_obj); + +static PyObject * +_multiprocessing_SemLock_acquire(SemLockObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"block", "timeout", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "acquire", 0}; + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + int blocking = 1; + PyObject *timeout_obj = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[0]) { + blocking = _PyLong_AsInt(args[0]); + if (blocking == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + timeout_obj = args[1]; +skip_optional_pos: + return_value = _multiprocessing_SemLock_acquire_impl(self, blocking, timeout_obj); + +exit: + return return_value; +} + +#endif /* !defined(MS_WINDOWS) */ + +#if !defined(MS_WINDOWS) + +PyDoc_STRVAR(_multiprocessing_SemLock_release__doc__, +"release($self, /)\n" +"--\n" +"\n" +"Release the semaphore/lock."); + +#define _MULTIPROCESSING_SEMLOCK_RELEASE_METHODDEF \ + {"release", (PyCFunction)_multiprocessing_SemLock_release, METH_NOARGS, _multiprocessing_SemLock_release__doc__}, + +static PyObject * +_multiprocessing_SemLock_release_impl(SemLockObject *self); + +static PyObject * +_multiprocessing_SemLock_release(SemLockObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _multiprocessing_SemLock_release_impl(self); +} + +#endif /* !defined(MS_WINDOWS) */ + +static PyObject * +_multiprocessing_SemLock_impl(PyTypeObject *type, int kind, int value, + int maxvalue, const char *name, int unlink); + +static PyObject * +_multiprocessing_SemLock(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"kind", "value", "maxvalue", "name", "unlink", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "SemLock", 0}; + PyObject *argsbuf[5]; + PyObject * const *fastargs; + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + int kind; + int value; + int maxvalue; + const char *name; + int unlink; + + fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 5, 5, 0, argsbuf); + if (!fastargs) { + goto exit; + } + kind = _PyLong_AsInt(fastargs[0]); + if (kind == -1 && PyErr_Occurred()) { + goto exit; + } + value = _PyLong_AsInt(fastargs[1]); + if (value == -1 && PyErr_Occurred()) { + goto exit; + } + maxvalue = _PyLong_AsInt(fastargs[2]); + if (maxvalue == -1 && PyErr_Occurred()) { + goto exit; + } + if (!PyUnicode_Check(fastargs[3])) { + _PyArg_BadArgument("SemLock", "argument 'name'", "str", fastargs[3]); + goto exit; + } + Py_ssize_t name_length; + name = PyUnicode_AsUTF8AndSize(fastargs[3], &name_length); + if (name == NULL) { + goto exit; + } + if (strlen(name) != (size_t)name_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + unlink = _PyLong_AsInt(fastargs[4]); + if (unlink == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _multiprocessing_SemLock_impl(type, kind, value, maxvalue, name, unlink); + +exit: + return return_value; +} + +PyDoc_STRVAR(_multiprocessing_SemLock__rebuild__doc__, +"_rebuild($type, handle, kind, maxvalue, name, /)\n" +"--\n" +"\n"); + +#define _MULTIPROCESSING_SEMLOCK__REBUILD_METHODDEF \ + {"_rebuild", (PyCFunction)(void(*)(void))_multiprocessing_SemLock__rebuild, METH_FASTCALL|METH_CLASS, _multiprocessing_SemLock__rebuild__doc__}, + +static PyObject * +_multiprocessing_SemLock__rebuild_impl(PyTypeObject *type, SEM_HANDLE handle, + int kind, int maxvalue, + const char *name); + +static PyObject * +_multiprocessing_SemLock__rebuild(PyTypeObject *type, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + SEM_HANDLE handle; + int kind; + int maxvalue; + const char *name; + + if (!_PyArg_ParseStack(args, nargs, ""F_SEM_HANDLE"iiz:_rebuild", + &handle, &kind, &maxvalue, &name)) { + goto exit; + } + return_value = _multiprocessing_SemLock__rebuild_impl(type, handle, kind, maxvalue, name); + +exit: + return return_value; +} + +PyDoc_STRVAR(_multiprocessing_SemLock__count__doc__, +"_count($self, /)\n" +"--\n" +"\n" +"Num of `acquire()`s minus num of `release()`s for this process."); + +#define _MULTIPROCESSING_SEMLOCK__COUNT_METHODDEF \ + {"_count", (PyCFunction)_multiprocessing_SemLock__count, METH_NOARGS, _multiprocessing_SemLock__count__doc__}, + +static PyObject * +_multiprocessing_SemLock__count_impl(SemLockObject *self); + +static PyObject * +_multiprocessing_SemLock__count(SemLockObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _multiprocessing_SemLock__count_impl(self); +} + +PyDoc_STRVAR(_multiprocessing_SemLock__is_mine__doc__, +"_is_mine($self, /)\n" +"--\n" +"\n" +"Whether the lock is owned by this thread."); + +#define _MULTIPROCESSING_SEMLOCK__IS_MINE_METHODDEF \ + {"_is_mine", (PyCFunction)_multiprocessing_SemLock__is_mine, METH_NOARGS, _multiprocessing_SemLock__is_mine__doc__}, + +static PyObject * +_multiprocessing_SemLock__is_mine_impl(SemLockObject *self); + +static PyObject * +_multiprocessing_SemLock__is_mine(SemLockObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _multiprocessing_SemLock__is_mine_impl(self); +} + +PyDoc_STRVAR(_multiprocessing_SemLock__get_value__doc__, +"_get_value($self, /)\n" +"--\n" +"\n" +"Get the value of the semaphore."); + +#define _MULTIPROCESSING_SEMLOCK__GET_VALUE_METHODDEF \ + {"_get_value", (PyCFunction)_multiprocessing_SemLock__get_value, METH_NOARGS, _multiprocessing_SemLock__get_value__doc__}, + +static PyObject * +_multiprocessing_SemLock__get_value_impl(SemLockObject *self); + +static PyObject * +_multiprocessing_SemLock__get_value(SemLockObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _multiprocessing_SemLock__get_value_impl(self); +} + +PyDoc_STRVAR(_multiprocessing_SemLock__is_zero__doc__, +"_is_zero($self, /)\n" +"--\n" +"\n" +"Return whether semaphore has value zero."); + +#define _MULTIPROCESSING_SEMLOCK__IS_ZERO_METHODDEF \ + {"_is_zero", (PyCFunction)_multiprocessing_SemLock__is_zero, METH_NOARGS, _multiprocessing_SemLock__is_zero__doc__}, + +static PyObject * +_multiprocessing_SemLock__is_zero_impl(SemLockObject *self); + +static PyObject * +_multiprocessing_SemLock__is_zero(SemLockObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _multiprocessing_SemLock__is_zero_impl(self); +} + +PyDoc_STRVAR(_multiprocessing_SemLock__after_fork__doc__, +"_after_fork($self, /)\n" +"--\n" +"\n" +"Rezero the net acquisition count after fork()."); + +#define _MULTIPROCESSING_SEMLOCK__AFTER_FORK_METHODDEF \ + {"_after_fork", (PyCFunction)_multiprocessing_SemLock__after_fork, METH_NOARGS, _multiprocessing_SemLock__after_fork__doc__}, + +static PyObject * +_multiprocessing_SemLock__after_fork_impl(SemLockObject *self); + +static PyObject * +_multiprocessing_SemLock__after_fork(SemLockObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _multiprocessing_SemLock__after_fork_impl(self); +} + +PyDoc_STRVAR(_multiprocessing_SemLock___enter____doc__, +"__enter__($self, /)\n" +"--\n" +"\n" +"Enter the semaphore/lock."); + +#define _MULTIPROCESSING_SEMLOCK___ENTER___METHODDEF \ + {"__enter__", (PyCFunction)_multiprocessing_SemLock___enter__, METH_NOARGS, _multiprocessing_SemLock___enter____doc__}, + +static PyObject * +_multiprocessing_SemLock___enter___impl(SemLockObject *self); + +static PyObject * +_multiprocessing_SemLock___enter__(SemLockObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _multiprocessing_SemLock___enter___impl(self); +} + +PyDoc_STRVAR(_multiprocessing_SemLock___exit____doc__, +"__exit__($self, exc_type=None, exc_value=None, exc_tb=None, /)\n" +"--\n" +"\n" +"Exit the semaphore/lock."); + +#define _MULTIPROCESSING_SEMLOCK___EXIT___METHODDEF \ + {"__exit__", (PyCFunction)(void(*)(void))_multiprocessing_SemLock___exit__, METH_FASTCALL, _multiprocessing_SemLock___exit____doc__}, + +static PyObject * +_multiprocessing_SemLock___exit___impl(SemLockObject *self, + PyObject *exc_type, + PyObject *exc_value, PyObject *exc_tb); + +static PyObject * +_multiprocessing_SemLock___exit__(SemLockObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *exc_type = Py_None; + PyObject *exc_value = Py_None; + PyObject *exc_tb = Py_None; + + if (!_PyArg_CheckPositional("__exit__", nargs, 0, 3)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + exc_type = args[0]; + if (nargs < 2) { + goto skip_optional; + } + exc_value = args[1]; + if (nargs < 3) { + goto skip_optional; + } + exc_tb = args[2]; +skip_optional: + return_value = _multiprocessing_SemLock___exit___impl(self, exc_type, exc_value, exc_tb); + +exit: + return return_value; +} + +#ifndef _MULTIPROCESSING_SEMLOCK_ACQUIRE_METHODDEF + #define _MULTIPROCESSING_SEMLOCK_ACQUIRE_METHODDEF +#endif /* !defined(_MULTIPROCESSING_SEMLOCK_ACQUIRE_METHODDEF) */ + +#ifndef _MULTIPROCESSING_SEMLOCK_RELEASE_METHODDEF + #define _MULTIPROCESSING_SEMLOCK_RELEASE_METHODDEF +#endif /* !defined(_MULTIPROCESSING_SEMLOCK_RELEASE_METHODDEF) */ +/*[clinic end generated code: output=e7fd938150601fe5 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/_multiprocessing/multiprocessing.c b/contrib/tools/python3/src/Modules/_multiprocessing/multiprocessing.c index 806e638340..bec23517fc 100644 --- a/contrib/tools/python3/src/Modules/_multiprocessing/multiprocessing.c +++ b/contrib/tools/python3/src/Modules/_multiprocessing/multiprocessing.c @@ -9,6 +9,20 @@ #include "multiprocessing.h" +/*[python input] +class HANDLE_converter(CConverter): + type = "HANDLE" + format_unit = '"F_HANDLE"' + +[python start generated code]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=9fad6080b79ace91]*/ + +/*[clinic input] +module _multiprocessing +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=01e0745f380ac6e3]*/ + +#include "clinic/multiprocessing.c.h" /* * Function which raises exceptions based on error codes @@ -50,15 +64,20 @@ _PyMp_SetError(PyObject *Type, int num) } #ifdef MS_WINDOWS +/*[clinic input] +_multiprocessing.closesocket + + handle: HANDLE + / + +[clinic start generated code]*/ + static PyObject * -multiprocessing_closesocket(PyObject *self, PyObject *args) +_multiprocessing_closesocket_impl(PyObject *module, HANDLE handle) +/*[clinic end generated code: output=214f359f900966f4 input=8a20706dd386c6cc]*/ { - HANDLE handle; int ret; - if (!PyArg_ParseTuple(args, F_HANDLE ":closesocket" , &handle)) - return NULL; - Py_BEGIN_ALLOW_THREADS ret = closesocket((SOCKET) handle); Py_END_ALLOW_THREADS @@ -68,16 +87,22 @@ multiprocessing_closesocket(PyObject *self, PyObject *args) Py_RETURN_NONE; } +/*[clinic input] +_multiprocessing.recv + + handle: HANDLE + size: int + / + +[clinic start generated code]*/ + static PyObject * -multiprocessing_recv(PyObject *self, PyObject *args) +_multiprocessing_recv_impl(PyObject *module, HANDLE handle, int size) +/*[clinic end generated code: output=92322781ba9ff598 input=6a5b0834372cee5b]*/ { - HANDLE handle; - int size, nread; + int nread; PyObject *buf; - if (!PyArg_ParseTuple(args, F_HANDLE "i:recv" , &handle, &size)) - return NULL; - buf = PyBytes_FromStringAndSize(NULL, size); if (!buf) return NULL; @@ -94,23 +119,27 @@ multiprocessing_recv(PyObject *self, PyObject *args) return buf; } +/*[clinic input] +_multiprocessing.send + + handle: HANDLE + buf: Py_buffer + / + +[clinic start generated code]*/ + static PyObject * -multiprocessing_send(PyObject *self, PyObject *args) +_multiprocessing_send_impl(PyObject *module, HANDLE handle, Py_buffer *buf) +/*[clinic end generated code: output=52d7df0519c596cb input=41dce742f98d2210]*/ { - HANDLE handle; - Py_buffer buf; int ret, length; - if (!PyArg_ParseTuple(args, F_HANDLE "y*:send" , &handle, &buf)) - return NULL; - - length = (int)Py_MIN(buf.len, INT_MAX); + length = (int)Py_MIN(buf->len, INT_MAX); Py_BEGIN_ALLOW_THREADS - ret = send((SOCKET) handle, buf.buf, length, 0); + ret = send((SOCKET) handle, buf->buf, length, 0); Py_END_ALLOW_THREADS - PyBuffer_Release(&buf); if (ret < 0) return PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError()); return PyLong_FromLong(ret); @@ -118,18 +147,33 @@ multiprocessing_send(PyObject *self, PyObject *args) #endif +/*[clinic input] +_multiprocessing.sem_unlink + + name: str + / + +[clinic start generated code]*/ + +static PyObject * +_multiprocessing_sem_unlink_impl(PyObject *module, const char *name) +/*[clinic end generated code: output=fcbfeb1ed255e647 input=bf939aff9564f1d5]*/ +{ + return _PyMp_sem_unlink(name); +} + /* * Function table */ static PyMethodDef module_methods[] = { #ifdef MS_WINDOWS - {"closesocket", multiprocessing_closesocket, METH_VARARGS, ""}, - {"recv", multiprocessing_recv, METH_VARARGS, ""}, - {"send", multiprocessing_send, METH_VARARGS, ""}, + _MULTIPROCESSING_CLOSESOCKET_METHODDEF + _MULTIPROCESSING_RECV_METHODDEF + _MULTIPROCESSING_SEND_METHODDEF #endif #if !defined(POSIX_SEMAPHORES_NOT_ENABLED) && !defined(__ANDROID__) - {"sem_unlink", _PyMp_sem_unlink, METH_VARARGS, ""}, + _MULTIPROCESSING_SEM_UNLINK_METHODDEF #endif {NULL} }; @@ -139,35 +183,17 @@ static PyMethodDef module_methods[] = { * Initialize */ -static struct PyModuleDef multiprocessing_module = { - PyModuleDef_HEAD_INIT, - "_multiprocessing", - NULL, - -1, - module_methods, - NULL, - NULL, - NULL, - NULL -}; - - -PyMODINIT_FUNC -PyInit__multiprocessing(void) +static int +multiprocessing_exec(PyObject *module) { - PyObject *module, *temp, *value = NULL; - - /* Initialize module */ - module = PyModule_Create(&multiprocessing_module); - if (!module) - return NULL; - #if defined(MS_WINDOWS) || \ (defined(HAVE_SEM_OPEN) && !defined(POSIX_SEMAPHORES_NOT_ENABLED)) + /* Add _PyMp_SemLock type to module */ - if (PyType_Ready(&_PyMp_SemLockType) < 0) - return NULL; - Py_INCREF(&_PyMp_SemLockType); + if (PyModule_AddType(module, &_PyMp_SemLockType) < 0) { + return -1; + } + { PyObject *py_sem_value_max; /* Some systems define SEM_VALUE_MAX as an unsigned value that @@ -179,25 +205,40 @@ PyInit__multiprocessing(void) py_sem_value_max = PyLong_FromLong(INT_MAX); else py_sem_value_max = PyLong_FromLong(SEM_VALUE_MAX); - if (py_sem_value_max == NULL) - return NULL; - PyDict_SetItemString(_PyMp_SemLockType.tp_dict, "SEM_VALUE_MAX", - py_sem_value_max); + + if (py_sem_value_max == NULL) { + return -1; + } + if (PyDict_SetItemString(_PyMp_SemLockType.tp_dict, "SEM_VALUE_MAX", + py_sem_value_max) < 0) { + Py_DECREF(py_sem_value_max); + return -1; + } + Py_DECREF(py_sem_value_max); } - PyModule_AddObject(module, "SemLock", (PyObject*)&_PyMp_SemLockType); + #endif /* Add configuration macros */ - temp = PyDict_New(); - if (!temp) - return NULL; + PyObject *flags = PyDict_New(); + if (!flags) { + return -1; + } -#define ADD_FLAG(name) \ - value = Py_BuildValue("i", name); \ - if (value == NULL) { Py_DECREF(temp); return NULL; } \ - if (PyDict_SetItemString(temp, #name, value) < 0) { \ - Py_DECREF(temp); Py_DECREF(value); return NULL; } \ - Py_DECREF(value) +#define ADD_FLAG(name) \ + do { \ + PyObject *value = PyLong_FromLong(name); \ + if (value == NULL) { \ + Py_DECREF(flags); \ + return -1; \ + } \ + if (PyDict_SetItemString(flags, #name, value) < 0) { \ + Py_DECREF(flags); \ + Py_DECREF(value); \ + return -1; \ + } \ + Py_DECREF(value); \ + } while (0) #if defined(HAVE_SEM_OPEN) && !defined(POSIX_SEMAPHORES_NOT_ENABLED) ADD_FLAG(HAVE_SEM_OPEN); @@ -212,8 +253,28 @@ PyInit__multiprocessing(void) ADD_FLAG(HAVE_BROKEN_SEM_UNLINK); #endif - if (PyModule_AddObject(module, "flags", temp) < 0) - return NULL; + if (PyModule_AddObject(module, "flags", flags) < 0) { + Py_DECREF(flags); + return -1; + } + + return 0; +} + +static PyModuleDef_Slot multiprocessing_slots[] = { + {Py_mod_exec, multiprocessing_exec}, + {0, NULL} +}; - return module; +static struct PyModuleDef multiprocessing_module = { + PyModuleDef_HEAD_INIT, + .m_name = "_multiprocessing", + .m_methods = module_methods, + .m_slots = multiprocessing_slots, +}; + +PyMODINIT_FUNC +PyInit__multiprocessing(void) +{ + return PyModuleDef_Init(&multiprocessing_module); } diff --git a/contrib/tools/python3/src/Modules/_multiprocessing/multiprocessing.h b/contrib/tools/python3/src/Modules/_multiprocessing/multiprocessing.h index fe78135d46..277963bc15 100644 --- a/contrib/tools/python3/src/Modules/_multiprocessing/multiprocessing.h +++ b/contrib/tools/python3/src/Modules/_multiprocessing/multiprocessing.h @@ -88,6 +88,6 @@ PyObject *_PyMp_SetError(PyObject *Type, int num); */ extern PyTypeObject _PyMp_SemLockType; -extern PyObject *_PyMp_sem_unlink(PyObject *ignore, PyObject *args); +extern PyObject *_PyMp_sem_unlink(const char *name); #endif /* MULTIPROCESSING_H */ diff --git a/contrib/tools/python3/src/Modules/_multiprocessing/posixshmem.c b/contrib/tools/python3/src/Modules/_multiprocessing/posixshmem.c index 436ac6d6b3..d64ded4168 100644 --- a/contrib/tools/python3/src/Modules/_multiprocessing/posixshmem.c +++ b/contrib/tools/python3/src/Modules/_multiprocessing/posixshmem.c @@ -110,21 +110,17 @@ static PyMethodDef module_methods[ ] = { }; -static struct PyModuleDef this_module = { - PyModuleDef_HEAD_INIT, // m_base - "_posixshmem", // m_name - "POSIX shared memory module", // m_doc - -1, // m_size (space allocated for module globals) - module_methods, // m_methods +static struct PyModuleDef _posixshmemmodule = { + PyModuleDef_HEAD_INIT, + .m_name = "_posixshmem", + .m_doc = "POSIX shared memory module", + .m_size = 0, + .m_methods = module_methods, }; /* Module init function */ PyMODINIT_FUNC -PyInit__posixshmem(void) { - PyObject *module; - module = PyModule_Create(&this_module); - if (!module) { - return NULL; - } - return module; +PyInit__posixshmem(void) +{ + return PyModuleDef_Init(&_posixshmemmodule); } diff --git a/contrib/tools/python3/src/Modules/_multiprocessing/semaphore.c b/contrib/tools/python3/src/Modules/_multiprocessing/semaphore.c index ee490256d2..9a2d1f85c9 100644 --- a/contrib/tools/python3/src/Modules/_multiprocessing/semaphore.c +++ b/contrib/tools/python3/src/Modules/_multiprocessing/semaphore.c @@ -21,6 +21,22 @@ typedef struct { char *name; } SemLockObject; +/*[python input] +class SEM_HANDLE_converter(CConverter): + type = "SEM_HANDLE" + format_unit = '"F_SEM_HANDLE"' + +[python start generated code]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=3e0ad43e482d8716]*/ + +/*[clinic input] +module _multiprocessing +class _multiprocessing.SemLock "SemLockObject *" "&_PyMp_SemLockType" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=935fb41b7d032599]*/ + +#include "clinic/semaphore.c.h" + #define ISMINE(o) (o->count > 0 && PyThread_get_thread_ident() == o->last_tid) @@ -58,21 +74,24 @@ _GetSemaphoreValue(HANDLE handle, long *value) } } +/*[clinic input] +_multiprocessing.SemLock.acquire + + block as blocking: bool(accept={int}) = True + timeout as timeout_obj: object = None + +Acquire the semaphore/lock. +[clinic start generated code]*/ + static PyObject * -semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds) +_multiprocessing_SemLock_acquire_impl(SemLockObject *self, int blocking, + PyObject *timeout_obj) +/*[clinic end generated code: output=f9998f0b6b0b0872 input=86f05662cf753eb4]*/ { - int blocking = 1; double timeout; - PyObject *timeout_obj = Py_None; DWORD res, full_msecs, nhandles; HANDLE handles[2], sigint_event; - static char *kwlist[] = {"block", "timeout", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iO", kwlist, - &blocking, &timeout_obj)) - return NULL; - /* calculate timeout */ if (!blocking) { full_msecs = 0; @@ -146,8 +165,15 @@ semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds) } } +/*[clinic input] +_multiprocessing.SemLock.release + +Release the semaphore/lock. +[clinic start generated code]*/ + static PyObject * -semlock_release(SemLockObject *self, PyObject *args) +_multiprocessing_SemLock_release_impl(SemLockObject *self) +/*[clinic end generated code: output=b22f53ba96b0d1db input=ba7e63a961885d3d]*/ { if (self->kind == RECURSIVE_MUTEX) { if (!ISMINE(self)) { @@ -264,19 +290,23 @@ sem_timedwait_save(sem_t *sem, struct timespec *deadline, PyThreadState *_save) #endif /* !HAVE_SEM_TIMEDWAIT */ +/*[clinic input] +_multiprocessing.SemLock.acquire + + block as blocking: bool(accept={int}) = True + timeout as timeout_obj: object = None + +Acquire the semaphore/lock. +[clinic start generated code]*/ + static PyObject * -semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds) +_multiprocessing_SemLock_acquire_impl(SemLockObject *self, int blocking, + PyObject *timeout_obj) +/*[clinic end generated code: output=f9998f0b6b0b0872 input=86f05662cf753eb4]*/ { - int blocking = 1, res, err = 0; - PyObject *timeout_obj = Py_None; + int res, err = 0; struct timespec deadline = {0}; - static char *kwlist[] = {"block", "timeout", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iO", kwlist, - &blocking, &timeout_obj)) - return NULL; - if (self->kind == RECURSIVE_MUTEX && ISMINE(self)) { ++self->count; Py_RETURN_TRUE; @@ -345,8 +375,15 @@ semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds) Py_RETURN_TRUE; } +/*[clinic input] +_multiprocessing.SemLock.release + +Release the semaphore/lock. +[clinic start generated code]*/ + static PyObject * -semlock_release(SemLockObject *self, PyObject *args) +_multiprocessing_SemLock_release_impl(SemLockObject *self) +/*[clinic end generated code: output=b22f53ba96b0d1db input=ba7e63a961885d3d]*/ { if (self->kind == RECURSIVE_MUTEX) { if (!ISMINE(self)) { @@ -429,19 +466,26 @@ newsemlockobject(PyTypeObject *type, SEM_HANDLE handle, int kind, int maxvalue, return (PyObject*)self; } +/*[clinic input] +@classmethod +_multiprocessing.SemLock.__new__ + + kind: int + value: int + maxvalue: int + name: str + unlink: bool(accept={int}) + +[clinic start generated code]*/ + static PyObject * -semlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +_multiprocessing_SemLock_impl(PyTypeObject *type, int kind, int value, + int maxvalue, const char *name, int unlink) +/*[clinic end generated code: output=30727e38f5f7577a input=b378c3ee27d3a0fa]*/ { SEM_HANDLE handle = SEM_FAILED; - int kind, maxvalue, value, unlink; PyObject *result; - char *name, *name_copy = NULL; - static char *kwlist[] = {"kind", "value", "maxvalue", "name", "unlink", - NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "iiisi", kwlist, - &kind, &value, &maxvalue, &name, &unlink)) - return NULL; + char *name_copy = NULL; if (kind != RECURSIVE_MUTEX && kind != SEMAPHORE) { PyErr_SetString(PyExc_ValueError, "unrecognized kind"); @@ -481,16 +525,25 @@ semlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; } +/*[clinic input] +@classmethod +_multiprocessing.SemLock._rebuild + + handle: SEM_HANDLE + kind: int + maxvalue: int + name: str(accept={str, NoneType}) + / + +[clinic start generated code]*/ + static PyObject * -semlock_rebuild(PyTypeObject *type, PyObject *args) +_multiprocessing_SemLock__rebuild_impl(PyTypeObject *type, SEM_HANDLE handle, + int kind, int maxvalue, + const char *name) +/*[clinic end generated code: output=2aaee14f063f3bd9 input=f7040492ac6d9962]*/ { - SEM_HANDLE handle; - int kind, maxvalue; - char *name, *name_copy = NULL; - - if (!PyArg_ParseTuple(args, F_SEM_HANDLE "iiz", - &handle, &kind, &maxvalue, &name)) - return NULL; + char *name_copy = NULL; if (name != NULL) { name_copy = PyMem_Malloc(strlen(name) + 1); @@ -518,24 +571,45 @@ semlock_dealloc(SemLockObject* self) if (self->handle != SEM_FAILED) SEM_CLOSE(self->handle); PyMem_Free(self->name); - PyObject_Del(self); + PyObject_Free(self); } +/*[clinic input] +_multiprocessing.SemLock._count + +Num of `acquire()`s minus num of `release()`s for this process. +[clinic start generated code]*/ + static PyObject * -semlock_count(SemLockObject *self, PyObject *Py_UNUSED(ignored)) +_multiprocessing_SemLock__count_impl(SemLockObject *self) +/*[clinic end generated code: output=5ba8213900e517bb input=36fc59b1cd1025ab]*/ { return PyLong_FromLong((long)self->count); } +/*[clinic input] +_multiprocessing.SemLock._is_mine + +Whether the lock is owned by this thread. +[clinic start generated code]*/ + static PyObject * -semlock_ismine(SemLockObject *self, PyObject *Py_UNUSED(ignored)) +_multiprocessing_SemLock__is_mine_impl(SemLockObject *self) +/*[clinic end generated code: output=92dc98863f4303be input=a96664cb2f0093ba]*/ { /* only makes sense for a lock */ return PyBool_FromLong(ISMINE(self)); } +/*[clinic input] +_multiprocessing.SemLock._get_value + +Get the value of the semaphore. +[clinic start generated code]*/ + static PyObject * -semlock_getvalue(SemLockObject *self, PyObject *Py_UNUSED(ignored)) +_multiprocessing_SemLock__get_value_impl(SemLockObject *self) +/*[clinic end generated code: output=64bc1b89bda05e36 input=cb10f9a769836203]*/ { #ifdef HAVE_BROKEN_SEM_GETVALUE PyErr_SetNone(PyExc_NotImplementedError); @@ -552,8 +626,15 @@ semlock_getvalue(SemLockObject *self, PyObject *Py_UNUSED(ignored)) #endif } +/*[clinic input] +_multiprocessing.SemLock._is_zero + +Return whether semaphore has value zero. +[clinic start generated code]*/ + static PyObject * -semlock_iszero(SemLockObject *self, PyObject *Py_UNUSED(ignored)) +_multiprocessing_SemLock__is_zero_impl(SemLockObject *self) +/*[clinic end generated code: output=815d4c878c806ed7 input=294a446418d31347]*/ { #ifdef HAVE_BROKEN_SEM_GETVALUE if (sem_trywait(self->handle) < 0) { @@ -573,38 +654,68 @@ semlock_iszero(SemLockObject *self, PyObject *Py_UNUSED(ignored)) #endif } +/*[clinic input] +_multiprocessing.SemLock._after_fork + +Rezero the net acquisition count after fork(). +[clinic start generated code]*/ + static PyObject * -semlock_afterfork(SemLockObject *self, PyObject *Py_UNUSED(ignored)) +_multiprocessing_SemLock__after_fork_impl(SemLockObject *self) +/*[clinic end generated code: output=718bb27914c6a6c1 input=190991008a76621e]*/ { self->count = 0; Py_RETURN_NONE; } +/*[clinic input] +_multiprocessing.SemLock.__enter__ + +Enter the semaphore/lock. +[clinic start generated code]*/ + +static PyObject * +_multiprocessing_SemLock___enter___impl(SemLockObject *self) +/*[clinic end generated code: output=beeb2f07c858511f input=c5e27d594284690b]*/ +{ + return _multiprocessing_SemLock_acquire_impl(self, 1, Py_None); +} + +/*[clinic input] +_multiprocessing.SemLock.__exit__ + + exc_type: object = None + exc_value: object = None + exc_tb: object = None + / + +Exit the semaphore/lock. +[clinic start generated code]*/ + +static PyObject * +_multiprocessing_SemLock___exit___impl(SemLockObject *self, + PyObject *exc_type, + PyObject *exc_value, PyObject *exc_tb) +/*[clinic end generated code: output=3b37c1a9f8b91a03 input=7d644b64a89903f8]*/ +{ + return _multiprocessing_SemLock_release_impl(self); +} + /* * Semaphore methods */ static PyMethodDef semlock_methods[] = { - {"acquire", (PyCFunction)(void(*)(void))semlock_acquire, METH_VARARGS | METH_KEYWORDS, - "acquire the semaphore/lock"}, - {"release", (PyCFunction)semlock_release, METH_NOARGS, - "release the semaphore/lock"}, - {"__enter__", (PyCFunction)(void(*)(void))semlock_acquire, METH_VARARGS | METH_KEYWORDS, - "enter the semaphore/lock"}, - {"__exit__", (PyCFunction)semlock_release, METH_VARARGS, - "exit the semaphore/lock"}, - {"_count", (PyCFunction)semlock_count, METH_NOARGS, - "num of `acquire()`s minus num of `release()`s for this process"}, - {"_is_mine", (PyCFunction)semlock_ismine, METH_NOARGS, - "whether the lock is owned by this thread"}, - {"_get_value", (PyCFunction)semlock_getvalue, METH_NOARGS, - "get the value of the semaphore"}, - {"_is_zero", (PyCFunction)semlock_iszero, METH_NOARGS, - "returns whether semaphore has value zero"}, - {"_rebuild", (PyCFunction)semlock_rebuild, METH_VARARGS | METH_CLASS, - ""}, - {"_after_fork", (PyCFunction)semlock_afterfork, METH_NOARGS, - "rezero the net acquisition count after fork()"}, + _MULTIPROCESSING_SEMLOCK_ACQUIRE_METHODDEF + _MULTIPROCESSING_SEMLOCK_RELEASE_METHODDEF + _MULTIPROCESSING_SEMLOCK___ENTER___METHODDEF + _MULTIPROCESSING_SEMLOCK___EXIT___METHODDEF + _MULTIPROCESSING_SEMLOCK__COUNT_METHODDEF + _MULTIPROCESSING_SEMLOCK__IS_MINE_METHODDEF + _MULTIPROCESSING_SEMLOCK__GET_VALUE_METHODDEF + _MULTIPROCESSING_SEMLOCK__IS_ZERO_METHODDEF + _MULTIPROCESSING_SEMLOCK__REBUILD_METHODDEF + _MULTIPROCESSING_SEMLOCK__AFTER_FORK_METHODDEF {NULL} }; @@ -666,7 +777,7 @@ PyTypeObject _PyMp_SemLockType = { /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, - /* tp_new */ semlock_new, + /* tp_new */ _multiprocessing_SemLock, }; /* @@ -674,13 +785,8 @@ PyTypeObject _PyMp_SemLockType = { */ PyObject * -_PyMp_sem_unlink(PyObject *ignore, PyObject *args) +_PyMp_sem_unlink(const char *name) { - char *name; - - if (!PyArg_ParseTuple(args, "s", &name)) - return NULL; - if (SEM_UNLINK(name) < 0) { _PyMp_SetError(NULL, MP_STANDARD_ERROR); return NULL; diff --git a/contrib/tools/python3/src/Modules/_opcode.c b/contrib/tools/python3/src/Modules/_opcode.c index 42a8732694..d8de0762e7 100644 --- a/contrib/tools/python3/src/Modules/_opcode.c +++ b/contrib/tools/python3/src/Modules/_opcode.c @@ -36,8 +36,9 @@ _opcode_stack_effect_impl(PyObject *module, int opcode, PyObject *oparg, return -1; } oparg_int = (int)PyLong_AsLong(oparg); - if ((oparg_int == -1) && PyErr_Occurred()) + if ((oparg_int == -1) && PyErr_Occurred()) { return -1; + } } else if (oparg != Py_None) { PyErr_SetString(PyExc_ValueError, @@ -67,30 +68,22 @@ _opcode_stack_effect_impl(PyObject *module, int opcode, PyObject *oparg, return effect; } - - - static PyMethodDef opcode_functions[] = { _OPCODE_STACK_EFFECT_METHODDEF {NULL, NULL, 0, NULL} }; - static struct PyModuleDef opcodemodule = { PyModuleDef_HEAD_INIT, - "_opcode", - "Opcode support module.", - -1, - opcode_functions, - NULL, - NULL, - NULL, - NULL + .m_name = "_opcode", + .m_doc = "Opcode support module.", + .m_size = 0, + .m_methods = opcode_functions }; PyMODINIT_FUNC PyInit__opcode(void) { - return PyModule_Create(&opcodemodule); + return PyModuleDef_Init(&opcodemodule); } diff --git a/contrib/tools/python3/src/Modules/_operator.c b/contrib/tools/python3/src/Modules/_operator.c index 0136e380d2..f051513fc7 100644 --- a/contrib/tools/python3/src/Modules/_operator.c +++ b/contrib/tools/python3/src/Modules/_operator.c @@ -1,8 +1,21 @@ - #include "Python.h" - +#include "pycore_moduleobject.h" // _PyModule_GetState() #include "clinic/_operator.c.h" +typedef struct { + PyObject *itemgetter_type; + PyObject *attrgetter_type; + PyObject *methodcaller_type; +} _operator_state; + +static inline _operator_state* +get_operator_state(PyObject *module) +{ + void *state = _PyModule_GetState(module); + assert(state != NULL); + return (_operator_state *)state; +} + /*[clinic input] module _operator [clinic start generated code]*/ @@ -942,8 +955,6 @@ typedef struct { Py_ssize_t index; // -1 unless *item* is a single non-negative integer index } itemgetterobject; -static PyTypeObject itemgetter_type; - /* AC 3.5: treats first argument as an iterable, otherwise uses *args */ static PyObject * itemgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) @@ -960,13 +971,15 @@ itemgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (nitems <= 1) { if (!PyArg_UnpackTuple(args, "itemgetter", 1, 1, &item)) return NULL; - } else + } else { item = args; - + } + _operator_state *state = PyType_GetModuleState(type); /* create itemgetterobject structure */ - ig = PyObject_GC_New(itemgetterobject, &itemgetter_type); - if (ig == NULL) + ig = PyObject_GC_New(itemgetterobject, (PyTypeObject *) state->itemgetter_type); + if (ig == NULL) { return NULL; + } Py_INCREF(item); ig->item = item; @@ -991,17 +1004,27 @@ itemgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return (PyObject *)ig; } +static int +itemgetter_clear(itemgetterobject *ig) +{ + Py_CLEAR(ig->item); + return 0; +} + static void itemgetter_dealloc(itemgetterobject *ig) { + PyTypeObject *tp = Py_TYPE(ig); PyObject_GC_UnTrack(ig); - Py_XDECREF(ig->item); - PyObject_GC_Del(ig); + (void)itemgetter_clear(ig); + tp->tp_free(ig); + Py_DECREF(tp); } static int itemgetter_traverse(itemgetterobject *ig, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(ig)); Py_VISIT(ig->item); return 0; } @@ -1093,49 +1116,27 @@ Return a callable object that fetches the given item(s) from its operand.\n\ After f = itemgetter(2), the call f(r) returns r[2].\n\ After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3])"); -static PyTypeObject itemgetter_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "operator.itemgetter", /* tp_name */ - sizeof(itemgetterobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)itemgetter_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)itemgetter_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - (ternaryfunc)itemgetter_call, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ - itemgetter_doc, /* tp_doc */ - (traverseproc)itemgetter_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - itemgetter_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itemgetter_new, /* tp_new */ - 0, /* tp_free */ +static PyType_Slot itemgetter_type_slots[] = { + {Py_tp_doc, (void *)itemgetter_doc}, + {Py_tp_dealloc, itemgetter_dealloc}, + {Py_tp_call, itemgetter_call}, + {Py_tp_traverse, itemgetter_traverse}, + {Py_tp_clear, itemgetter_clear}, + {Py_tp_methods, itemgetter_methods}, + {Py_tp_new, itemgetter_new}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_repr, itemgetter_repr}, + {0, 0} }; +static PyType_Spec itemgetter_type_spec = { + .name = "operator.itemgetter", + .basicsize = sizeof(itemgetterobject), + .itemsize = 0, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = itemgetter_type_slots, +}; /* attrgetter object **********************************************************/ @@ -1145,8 +1146,6 @@ typedef struct { PyObject *attr; } attrgetterobject; -static PyTypeObject attrgetter_type; - /* AC 3.5: treats first argument as an iterable, otherwise uses *args */ static PyObject * attrgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) @@ -1246,8 +1245,9 @@ attrgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) } } + _operator_state *state = PyType_GetModuleState(type); /* create attrgetterobject structure */ - ag = PyObject_GC_New(attrgetterobject, &attrgetter_type); + ag = PyObject_GC_New(attrgetterobject, (PyTypeObject *)state->attrgetter_type); if (ag == NULL) { Py_DECREF(attr); return NULL; @@ -1260,18 +1260,28 @@ attrgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return (PyObject *)ag; } +static int +attrgetter_clear(attrgetterobject *ag) +{ + Py_CLEAR(ag->attr); + return 0; +} + static void attrgetter_dealloc(attrgetterobject *ag) { + PyTypeObject *tp = Py_TYPE(ag); PyObject_GC_UnTrack(ag); - Py_XDECREF(ag->attr); - PyObject_GC_Del(ag); + (void)attrgetter_clear(ag); + tp->tp_free(ag); + Py_DECREF(tp); } static int attrgetter_traverse(attrgetterobject *ag, visitproc visit, void *arg) { Py_VISIT(ag->attr); + Py_VISIT(Py_TYPE(ag)); return 0; } @@ -1438,47 +1448,26 @@ After g = attrgetter('name', 'date'), the call g(r) returns (r.name, r.date).\n\ After h = attrgetter('name.first', 'name.last'), the call h(r) returns\n\ (r.name.first, r.name.last)."); -static PyTypeObject attrgetter_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "operator.attrgetter", /* tp_name */ - sizeof(attrgetterobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)attrgetter_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)attrgetter_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - (ternaryfunc)attrgetter_call, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ - attrgetter_doc, /* tp_doc */ - (traverseproc)attrgetter_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - attrgetter_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - attrgetter_new, /* tp_new */ - 0, /* tp_free */ +static PyType_Slot attrgetter_type_slots[] = { + {Py_tp_doc, (void *)attrgetter_doc}, + {Py_tp_dealloc, attrgetter_dealloc}, + {Py_tp_call, attrgetter_call}, + {Py_tp_traverse, attrgetter_traverse}, + {Py_tp_clear, attrgetter_clear}, + {Py_tp_methods, attrgetter_methods}, + {Py_tp_new, attrgetter_new}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_repr, attrgetter_repr}, + {0, 0} +}; + +static PyType_Spec attrgetter_type_spec = { + .name = "operator.attrgetter", + .basicsize = sizeof(attrgetterobject), + .itemsize = 0, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = attrgetter_type_slots, }; @@ -1491,8 +1480,6 @@ typedef struct { PyObject *kwds; } methodcallerobject; -static PyTypeObject methodcaller_type; - /* AC 3.5: variable number of arguments, not currently support by AC */ static PyObject * methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds) @@ -1513,10 +1500,12 @@ methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; } + _operator_state *state = PyType_GetModuleState(type); /* create methodcallerobject structure */ - mc = PyObject_GC_New(methodcallerobject, &methodcaller_type); - if (mc == NULL) + mc = PyObject_GC_New(methodcallerobject, (PyTypeObject *)state->methodcaller_type); + if (mc == NULL) { return NULL; + } name = PyTuple_GET_ITEM(args, 0); Py_INCREF(name); @@ -1536,21 +1525,32 @@ methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return (PyObject *)mc; } +static int +methodcaller_clear(methodcallerobject *mc) +{ + Py_CLEAR(mc->name); + Py_CLEAR(mc->args); + Py_CLEAR(mc->kwds); + return 0; +} + static void methodcaller_dealloc(methodcallerobject *mc) { + PyTypeObject *tp = Py_TYPE(mc); PyObject_GC_UnTrack(mc); - Py_XDECREF(mc->name); - Py_XDECREF(mc->args); - Py_XDECREF(mc->kwds); - PyObject_GC_Del(mc); + (void)methodcaller_clear(mc); + tp->tp_free(mc); + Py_DECREF(tp); } static int methodcaller_traverse(methodcallerobject *mc, visitproc visit, void *arg) { + Py_VISIT(mc->name); Py_VISIT(mc->args); Py_VISIT(mc->kwds); + Py_VISIT(Py_TYPE(mc)); return 0; } @@ -1704,63 +1704,54 @@ After f = methodcaller('name'), the call f(r) returns r.name().\n\ After g = methodcaller('name', 'date', foo=1), the call g(r) returns\n\ r.name('date', foo=1)."); -static PyTypeObject methodcaller_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "operator.methodcaller", /* tp_name */ - sizeof(methodcallerobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)methodcaller_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)methodcaller_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - (ternaryfunc)methodcaller_call, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ - methodcaller_doc, /* tp_doc */ - (traverseproc)methodcaller_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - methodcaller_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - methodcaller_new, /* tp_new */ - 0, /* tp_free */ +static PyType_Slot methodcaller_type_slots[] = { + {Py_tp_doc, (void *)methodcaller_doc}, + {Py_tp_dealloc, methodcaller_dealloc}, + {Py_tp_call, methodcaller_call}, + {Py_tp_traverse, methodcaller_traverse}, + {Py_tp_clear, methodcaller_clear}, + {Py_tp_methods, methodcaller_methods}, + {Py_tp_new, methodcaller_new}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_repr, methodcaller_repr}, + {0, 0} }; +static PyType_Spec methodcaller_type_spec = { + .name = "operator.methodcaller", + .basicsize = sizeof(methodcallerobject), + .itemsize = 0, + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = methodcaller_type_slots, +}; static int operator_exec(PyObject *module) { - PyTypeObject *types[] = { - &itemgetter_type, - &attrgetter_type, - &methodcaller_type - }; + _operator_state *state = get_operator_state(module); + state->attrgetter_type = PyType_FromModuleAndSpec(module, &attrgetter_type_spec, NULL); + if (state->attrgetter_type == NULL) { + return -1; + } + if (PyModule_AddType(module, (PyTypeObject *)state->attrgetter_type) < 0) { + return -1; + } - for (size_t i = 0; i < Py_ARRAY_LENGTH(types); i++) { - if (PyModule_AddType(module, types[i]) < 0) { - return -1; - } + state->itemgetter_type = PyType_FromModuleAndSpec(module, &itemgetter_type_spec, NULL); + if (state->itemgetter_type == NULL) { + return -1; + } + if (PyModule_AddType(module, (PyTypeObject *)state->itemgetter_type) < 0) { + return -1; + } + + state->methodcaller_type = PyType_FromModuleAndSpec(module, &methodcaller_type_spec, NULL); + if (state->methodcaller_type == NULL) { + return -1; + } + if (PyModule_AddType(module, (PyTypeObject *)state->methodcaller_type) < 0) { + return -1; } return 0; @@ -1772,17 +1763,42 @@ static struct PyModuleDef_Slot operator_slots[] = { {0, NULL} }; +static int +operator_traverse(PyObject *module, visitproc visit, void *arg) +{ + _operator_state *state = get_operator_state(module); + Py_VISIT(state->attrgetter_type); + Py_VISIT(state->itemgetter_type); + Py_VISIT(state->methodcaller_type); + return 0; +} + +static int +operator_clear(PyObject *module) +{ + _operator_state *state = get_operator_state(module); + Py_CLEAR(state->attrgetter_type); + Py_CLEAR(state->itemgetter_type); + Py_CLEAR(state->methodcaller_type); + return 0; +} + +static void +operator_free(void *module) +{ + operator_clear((PyObject *)module); +} static struct PyModuleDef operatormodule = { PyModuleDef_HEAD_INIT, - "_operator", - operator_doc, - 0, - operator_methods, - operator_slots, - NULL, - NULL, - NULL + .m_name = "_operator", + .m_doc = operator_doc, + .m_size = sizeof(_operator_state), + .m_methods = operator_methods, + .m_slots = operator_slots, + .m_traverse = operator_traverse, + .m_clear = operator_clear, + .m_free = operator_free, }; PyMODINIT_FUNC diff --git a/contrib/tools/python3/src/Modules/_peg_parser.c b/contrib/tools/python3/src/Modules/_peg_parser.c deleted file mode 100644 index ca2a3cf7b5..0000000000 --- a/contrib/tools/python3/src/Modules/_peg_parser.c +++ /dev/null @@ -1,153 +0,0 @@ -#include <Python.h> -#include "pegen_interface.h" - -static int -_mode_str_to_int(char *mode_str) -{ - int mode; - if (strcmp(mode_str, "exec") == 0) { - mode = Py_file_input; - } - else if (strcmp(mode_str, "eval") == 0) { - mode = Py_eval_input; - } - else if (strcmp(mode_str, "single") == 0) { - mode = Py_single_input; - } - else { - mode = -1; - } - return mode; -} - -static mod_ty -_run_parser(char *str, char *filename, int mode, PyCompilerFlags *flags, PyArena *arena, int oldparser) -{ - mod_ty mod; - if (!oldparser) { - mod = PyPegen_ASTFromString(str, filename, mode, flags, arena); - } - else { - mod = PyParser_ASTFromString(str, filename, mode, flags, arena); - } - return mod; -} - -PyObject * -_Py_compile_string(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *keywords[] = {"string", "filename", "mode", "oldparser", NULL}; - char *the_string; - char *filename = "<string>"; - char *mode_str = "exec"; - int oldparser = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|ssp", keywords, - &the_string, &filename, &mode_str, &oldparser)) { - return NULL; - } - - int mode = _mode_str_to_int(mode_str); - if (mode == -1) { - return PyErr_Format(PyExc_ValueError, "mode must be either 'exec' or 'eval' or 'single'"); - } - - PyCompilerFlags flags = _PyCompilerFlags_INIT; - flags.cf_flags = PyCF_IGNORE_COOKIE; - - PyArena *arena = PyArena_New(); - if (arena == NULL) { - return NULL; - } - - mod_ty mod = _run_parser(the_string, filename, mode, &flags, arena, oldparser); - if (mod == NULL) { - PyArena_Free(arena); - return NULL; - } - - PyObject *filename_ob = PyUnicode_DecodeFSDefault(filename); - if (filename_ob == NULL) { - PyArena_Free(arena); - return NULL; - } - PyCodeObject *result = PyAST_CompileObject(mod, filename_ob, &flags, -1, arena); - Py_XDECREF(filename_ob); - PyArena_Free(arena); - return (PyObject *)result; -} - -PyObject * -_Py_parse_string(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *keywords[] = {"string", "filename", "mode", "oldparser", "ast", NULL}; - char *the_string; - char *filename = "<string>"; - char *mode_str = "exec"; - int oldparser = 0; - int ast = 1; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|sspp", keywords, - &the_string, &filename, &mode_str, &oldparser, &ast)) { - return NULL; - } - - int mode = _mode_str_to_int(mode_str); - if (mode == -1) { - return PyErr_Format(PyExc_ValueError, "mode must be either 'exec' or 'eval' or 'single'"); - } - - PyCompilerFlags flags = _PyCompilerFlags_INIT; - flags.cf_flags = PyCF_IGNORE_COOKIE; - - PyArena *arena = PyArena_New(); - if (arena == NULL) { - return NULL; - } - - mod_ty mod = _run_parser(the_string, filename, mode, &flags, arena, oldparser); - if (mod == NULL) { - PyArena_Free(arena); - return NULL; - } - - PyObject *result; - if (ast) { - result = PyAST_mod2obj(mod); - } - else { - Py_INCREF(Py_None); - result = Py_None; - } - PyArena_Free(arena); - return result; -} - -static PyMethodDef ParseMethods[] = { - { - "parse_string", - (PyCFunction)(void (*)(void))_Py_parse_string, - METH_VARARGS|METH_KEYWORDS, - "Parse a string, return an AST." - }, - { - "compile_string", - (PyCFunction)(void (*)(void))_Py_compile_string, - METH_VARARGS|METH_KEYWORDS, - "Compile a string, return a code object." - }, - {NULL, NULL, 0, NULL} /* Sentinel */ -}; - -static struct PyModuleDef parsemodule = { - PyModuleDef_HEAD_INIT, - .m_name = "peg_parser", - .m_doc = "A parser.", - .m_methods = ParseMethods, -}; - -PyMODINIT_FUNC -PyInit__peg_parser(void) -{ - return PyModule_Create(&parsemodule); -} diff --git a/contrib/tools/python3/src/Modules/_pickle.c b/contrib/tools/python3/src/Modules/_pickle.c index 30bb5c0d75..8a4f0e64fb 100644 --- a/contrib/tools/python3/src/Modules/_pickle.c +++ b/contrib/tools/python3/src/Modules/_pickle.c @@ -9,6 +9,7 @@ #endif #include "Python.h" +#include "pycore_moduleobject.h" // _PyModule_GetState() #include "structmember.h" // PyMemberDef PyDoc_STRVAR(pickle_module_doc, @@ -182,7 +183,7 @@ static struct PyModuleDef _picklemodule; static PickleState * _Pickle_GetState(PyObject *module) { - return (PickleState *)PyModule_GetState(module); + return (PickleState *)_PyModule_GetState(module); } /* Find the module instance imported in the currently running sub-interpreter @@ -442,8 +443,8 @@ Pdata_dealloc(Pdata *self) while (--i >= 0) { Py_DECREF(self->data[i]); } - PyMem_FREE(self->data); - PyObject_Del(self); + PyMem_Free(self->data); + PyObject_Free(self); } static PyTypeObject Pdata_Type = { @@ -465,7 +466,7 @@ Pdata_New(void) self->mark_set = 0; self->fence = 0; self->allocated = 8; - self->data = PyMem_MALLOC(self->allocated * sizeof(PyObject *)); + self->data = PyMem_Malloc(self->allocated * sizeof(PyObject *)); if (self->data) return (PyObject *)self; Py_DECREF(self); @@ -726,7 +727,7 @@ static PyTypeObject Unpickler_Type; static PyMemoTable * PyMemoTable_New(void) { - PyMemoTable *memo = PyMem_MALLOC(sizeof(PyMemoTable)); + PyMemoTable *memo = PyMem_Malloc(sizeof(PyMemoTable)); if (memo == NULL) { PyErr_NoMemory(); return NULL; @@ -735,9 +736,9 @@ PyMemoTable_New(void) memo->mt_used = 0; memo->mt_allocated = MT_MINSIZE; memo->mt_mask = MT_MINSIZE - 1; - memo->mt_table = PyMem_MALLOC(MT_MINSIZE * sizeof(PyMemoEntry)); + memo->mt_table = PyMem_Malloc(MT_MINSIZE * sizeof(PyMemoEntry)); if (memo->mt_table == NULL) { - PyMem_FREE(memo); + PyMem_Free(memo); PyErr_NoMemory(); return NULL; } @@ -758,10 +759,10 @@ PyMemoTable_Copy(PyMemoTable *self) new->mt_mask = self->mt_mask; /* The table we get from _New() is probably smaller than we wanted. Free it and allocate one that's the right size. */ - PyMem_FREE(new->mt_table); + PyMem_Free(new->mt_table); new->mt_table = PyMem_NEW(PyMemoEntry, self->mt_allocated); if (new->mt_table == NULL) { - PyMem_FREE(new); + PyMem_Free(new); PyErr_NoMemory(); return NULL; } @@ -800,8 +801,8 @@ PyMemoTable_Del(PyMemoTable *self) return; PyMemoTable_Clear(self); - PyMem_FREE(self->mt_table); - PyMem_FREE(self); + PyMem_Free(self->mt_table); + PyMem_Free(self); } /* Since entries cannot be deleted from this hashtable, _PyMemoTable_Lookup() @@ -880,7 +881,7 @@ _PyMemoTable_ResizeTable(PyMemoTable *self, size_t min_size) } /* Deallocate the old table. */ - PyMem_FREE(oldtable); + PyMem_Free(oldtable); return 0; } @@ -1582,7 +1583,7 @@ _Unpickler_MemoCleanup(UnpicklerObject *self) while (--i >= 0) { Py_XDECREF(memo[i]); } - PyMem_FREE(memo); + PyMem_Free(memo); } static UnpicklerObject * @@ -1715,7 +1716,7 @@ memo_get(PicklerObject *self, PyObject *key) if (!self->bin) { pdata[0] = GET; PyOS_snprintf(pdata + 1, sizeof(pdata) - 1, - "%" PY_FORMAT_SIZE_T "d\n", *value); + "%zd\n", *value); len = strlen(pdata); } else { @@ -1772,7 +1773,7 @@ memo_put(PicklerObject *self, PyObject *obj) else if (!self->bin) { pdata[0] = PUT; PyOS_snprintf(pdata + 1, sizeof(pdata) - 1, - "%" PY_FORMAT_SIZE_T "d\n", idx); + "%zd\n", idx); len = strlen(pdata); } else { @@ -2004,26 +2005,21 @@ fast_save_enter(PicklerObject *self, PyObject *obj) self->fast_nesting = -1; return 0; } - if (PyDict_GetItemWithError(self->fast_memo, key)) { - Py_DECREF(key); + int r = PyDict_Contains(self->fast_memo, key); + if (r > 0) { PyErr_Format(PyExc_ValueError, "fast mode: can't pickle cyclic objects " "including object type %.200s at %p", Py_TYPE(obj)->tp_name, obj); - self->fast_nesting = -1; - return 0; } - if (PyErr_Occurred()) { - Py_DECREF(key); - self->fast_nesting = -1; - return 0; + else if (r == 0) { + r = PyDict_SetItem(self->fast_memo, key, Py_None); } - if (PyDict_SetItem(self->fast_memo, key, Py_None) < 0) { - Py_DECREF(key); + Py_DECREF(key); + if (r != 0) { self->fast_nesting = -1; return 0; } - Py_DECREF(key); } return 1; } @@ -5912,118 +5908,75 @@ load_inst(UnpicklerObject *self) return 0; } -static int -load_newobj(UnpicklerObject *self) +static void +newobj_unpickling_error(const char * msg, int use_kwargs, PyObject *arg) { - PyObject *args = NULL; - PyObject *clsraw = NULL; - PyTypeObject *cls; /* clsraw cast to its true type */ - PyObject *obj; PickleState *st = _Pickle_GetGlobalState(); - - /* Stack is ... cls argtuple, and we want to call - * cls.__new__(cls, *argtuple). - */ - PDATA_POP(self->stack, args); - if (args == NULL) - goto error; - if (!PyTuple_Check(args)) { - PyErr_SetString(st->UnpicklingError, - "NEWOBJ expected an arg " "tuple."); - goto error; - } - - PDATA_POP(self->stack, clsraw); - cls = (PyTypeObject *)clsraw; - if (cls == NULL) - goto error; - if (!PyType_Check(cls)) { - PyErr_SetString(st->UnpicklingError, "NEWOBJ class argument " - "isn't a type object"); - goto error; - } - if (cls->tp_new == NULL) { - PyErr_SetString(st->UnpicklingError, "NEWOBJ class argument " - "has NULL tp_new"); - goto error; - } - - /* Call __new__. */ - obj = cls->tp_new(cls, args, NULL); - if (obj == NULL) - goto error; - - Py_DECREF(args); - Py_DECREF(clsraw); - PDATA_PUSH(self->stack, obj, -1); - return 0; - - error: - Py_XDECREF(args); - Py_XDECREF(clsraw); - return -1; + PyErr_Format(st->UnpicklingError, msg, + use_kwargs ? "NEWOBJ_EX" : "NEWOBJ", + Py_TYPE(arg)->tp_name); } static int -load_newobj_ex(UnpicklerObject *self) +load_newobj(UnpicklerObject *self, int use_kwargs) { - PyObject *cls, *args, *kwargs; + PyObject *cls, *args, *kwargs = NULL; PyObject *obj; - PickleState *st = _Pickle_GetGlobalState(); - PDATA_POP(self->stack, kwargs); - if (kwargs == NULL) { - return -1; + /* Stack is ... cls args [kwargs], and we want to call + * cls.__new__(cls, *args, **kwargs). + */ + if (use_kwargs) { + PDATA_POP(self->stack, kwargs); + if (kwargs == NULL) { + return -1; + } } PDATA_POP(self->stack, args); if (args == NULL) { - Py_DECREF(kwargs); + Py_XDECREF(kwargs); return -1; } PDATA_POP(self->stack, cls); if (cls == NULL) { - Py_DECREF(kwargs); + Py_XDECREF(kwargs); Py_DECREF(args); return -1; } if (!PyType_Check(cls)) { - PyErr_Format(st->UnpicklingError, - "NEWOBJ_EX class argument must be a type, not %.200s", - Py_TYPE(cls)->tp_name); + newobj_unpickling_error("%s class argument must be a type, not %.200s", + use_kwargs, cls); goto error; } - if (((PyTypeObject *)cls)->tp_new == NULL) { - PyErr_SetString(st->UnpicklingError, - "NEWOBJ_EX class argument doesn't have __new__"); + newobj_unpickling_error("%s class argument '%.200s' doesn't have __new__", + use_kwargs, cls); goto error; } if (!PyTuple_Check(args)) { - PyErr_Format(st->UnpicklingError, - "NEWOBJ_EX args argument must be a tuple, not %.200s", - Py_TYPE(args)->tp_name); + newobj_unpickling_error("%s args argument must be a tuple, not %.200s", + use_kwargs, args); goto error; } - if (!PyDict_Check(kwargs)) { - PyErr_Format(st->UnpicklingError, - "NEWOBJ_EX kwargs argument must be a dict, not %.200s", - Py_TYPE(kwargs)->tp_name); + if (use_kwargs && !PyDict_Check(kwargs)) { + newobj_unpickling_error("%s kwargs argument must be a dict, not %.200s", + use_kwargs, kwargs); goto error; } obj = ((PyTypeObject *)cls)->tp_new((PyTypeObject *)cls, args, kwargs); - Py_DECREF(kwargs); - Py_DECREF(args); - Py_DECREF(cls); if (obj == NULL) { - return -1; + goto error; } + Py_XDECREF(kwargs); + Py_DECREF(args); + Py_DECREF(cls); PDATA_PUSH(self->stack, obj, -1); return 0; error: - Py_DECREF(kwargs); + Py_XDECREF(kwargs); Py_DECREF(args); Py_DECREF(cls); return -1; @@ -6956,8 +6909,8 @@ load(UnpicklerObject *self) OP(FROZENSET, load_frozenset) OP(OBJ, load_obj) OP(INST, load_inst) - OP(NEWOBJ, load_newobj) - OP(NEWOBJ_EX, load_newobj_ex) + OP_ARG(NEWOBJ, load_newobj, 0) + OP_ARG(NEWOBJ_EX, load_newobj, 1) OP(GLOBAL, load_global) OP(STACK_GLOBAL, load_stack_global) OP(APPEND, load_append) @@ -7592,7 +7545,7 @@ Unpickler_set_memo(UnpicklerObject *self, PyObject *obj, void *Py_UNUSED(ignored for (size_t i = new_memo_size - 1; i != SIZE_MAX; i--) { Py_XDECREF(new_memo[i]); } - PyMem_FREE(new_memo); + PyMem_Free(new_memo); } return -1; } diff --git a/contrib/tools/python3/src/Modules/_posixsubprocess.c b/contrib/tools/python3/src/Modules/_posixsubprocess.c index d64e0a1cfa..a58159a277 100644 --- a/contrib/tools/python3/src/Modules/_posixsubprocess.c +++ b/contrib/tools/python3/src/Modules/_posixsubprocess.c @@ -1,5 +1,6 @@ /* Authors: Gregory P. Smith & Jeffrey Yasskin */ #include "Python.h" +#include "pycore_fileutils.h" #if defined(HAVE_PIPE2) && !defined(_GNU_SOURCE) # define _GNU_SOURCE #endif @@ -35,6 +36,14 @@ # define SYS_getdents64 __NR_getdents64 #endif +#if defined(__linux__) && defined(HAVE_VFORK) && defined(HAVE_SIGNAL_H) && \ + defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK) +/* If this is ever expanded to non-Linux platforms, verify what calls are + * allowed after vfork(). Ex: setsid() may be disallowed on macOS? */ +# include <signal.h> +# define VFORK_USABLE 1 +#endif + #if defined(__sun) && defined(__SVR4) /* readdir64 is used to work around Solaris 9 bug 6395699. */ # define readdir readdir64 @@ -60,47 +69,8 @@ #define POSIX_CALL(call) do { if ((call) == -1) goto error; } while (0) -typedef struct { - PyObject* disable; - PyObject* enable; - PyObject* isenabled; -} _posixsubprocessstate; - static struct PyModuleDef _posixsubprocessmodule; -static inline _posixsubprocessstate* -get_posixsubprocess_state(PyObject *module) -{ - void *state = PyModule_GetState(module); - assert(state != NULL); - return (_posixsubprocessstate *)state; -} - -#define _posixsubprocessstate_global get_posixsubprocess_state(PyState_FindModule(&_posixsubprocessmodule)) - -/* If gc was disabled, call gc.enable(). Return 0 on success. */ -static int -_enable_gc(int need_to_reenable_gc, PyObject *gc_module) -{ - PyObject *result; - PyObject *exctype, *val, *tb; - - if (need_to_reenable_gc) { - PyErr_Fetch(&exctype, &val, &tb); - result = PyObject_CallMethodNoArgs( - gc_module, _posixsubprocessstate_global->enable); - if (exctype != NULL) { - PyErr_Restore(exctype, val, tb); - } - if (result == NULL) { - return 1; - } - Py_DECREF(result); - } - return 0; -} - - /* Convert ASCII to a positive int, no libc call. no overflow. -1 on error. */ static int _pos_int_from_ascii(const char *name) @@ -250,7 +220,6 @@ _close_fds_by_brute_force(long start_fd, PyObject *py_fds_to_keep) long end_fd = safe_get_max_fd(); Py_ssize_t num_fds_to_keep = PyTuple_GET_SIZE(py_fds_to_keep); Py_ssize_t keep_seq_idx; - int fd_num; /* As py_fds_to_keep is sorted we can loop through the list closing * fds in between any in the keep list falling within our range. */ for (keep_seq_idx = 0; keep_seq_idx < num_fds_to_keep; ++keep_seq_idx) { @@ -258,21 +227,11 @@ _close_fds_by_brute_force(long start_fd, PyObject *py_fds_to_keep) int keep_fd = PyLong_AsLong(py_keep_fd); if (keep_fd < start_fd) continue; - for (fd_num = start_fd; fd_num < keep_fd; ++fd_num) { - close(fd_num); - } + _Py_closerange(start_fd, keep_fd - 1); start_fd = keep_fd + 1; } if (start_fd <= end_fd) { -#if defined(__FreeBSD__) - /* Any errors encountered while closing file descriptors are ignored */ - closefrom(start_fd); -#else - for (fd_num = start_fd; fd_num < end_fd; ++fd_num) { - /* Ignore errors */ - (void)close(fd_num); - } -#endif + _Py_closerange(start_fd, end_fd); } } @@ -417,9 +376,53 @@ _close_open_fds_maybe_unsafe(long start_fd, PyObject* py_fds_to_keep) #endif /* else NOT (defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)) */ +#ifdef VFORK_USABLE +/* Reset dispositions for all signals to SIG_DFL except for ignored + * signals. This way we ensure that no signal handlers can run + * after we unblock signals in a child created by vfork(). + */ +static void +reset_signal_handlers(const sigset_t *child_sigmask) +{ + struct sigaction sa_dfl = {.sa_handler = SIG_DFL}; + for (int sig = 1; sig < _NSIG; sig++) { + /* Dispositions for SIGKILL and SIGSTOP can't be changed. */ + if (sig == SIGKILL || sig == SIGSTOP) { + continue; + } + + /* There is no need to reset the disposition of signals that will + * remain blocked across execve() since the kernel will do it. */ + if (sigismember(child_sigmask, sig) == 1) { + continue; + } + + struct sigaction sa; + /* C libraries usually return EINVAL for signals used + * internally (e.g. for thread cancellation), so simply + * skip errors here. */ + if (sigaction(sig, NULL, &sa) == -1) { + continue; + } + + /* void *h works as these fields are both pointer types already. */ + void *h = (sa.sa_flags & SA_SIGINFO ? (void *)sa.sa_sigaction : + (void *)sa.sa_handler); + if (h == SIG_IGN || h == SIG_DFL) { + continue; + } + + /* This call can't reasonably fail, but if it does, terminating + * the child seems to be too harsh, so ignore errors. */ + (void) sigaction(sig, &sa_dfl, NULL); + } +} +#endif /* VFORK_USABLE */ + + /* - * This function is code executed in the child process immediately after fork - * to set things up and call exec(). + * This function is code executed in the child process immediately after + * (v)fork to set things up and call exec(). * * All of the code in this function must only use async-signal-safe functions, * listed at `man 7 signal` or @@ -427,8 +430,28 @@ _close_open_fds_maybe_unsafe(long start_fd, PyObject* py_fds_to_keep) * * This restriction is documented at * http://www.opengroup.org/onlinepubs/009695399/functions/fork.html. + * + * If this function is called after vfork(), even more care must be taken. + * The lack of preparations that C libraries normally take on fork(), + * as well as sharing the address space with the parent, might make even + * async-signal-safe functions vfork-unsafe. In particular, on Linux, + * set*id() and setgroups() library functions must not be called, since + * they have to interact with the library-level thread list and send + * library-internal signals to implement per-process credentials semantics + * required by POSIX but not supported natively on Linux. Another reason to + * avoid this family of functions is that sharing an address space between + * processes running with different privileges is inherently insecure. + * See bpo-35823 for further discussion and references. + * + * In some C libraries, setrlimit() has the same thread list/signalling + * behavior since resource limits were per-thread attributes before + * Linux 2.6.10. Musl, as of 1.2.1, is known to have this issue + * (https://www.openwall.com/lists/musl/2020/10/15/6). + * + * If vfork-unsafe functionality is desired after vfork(), consider using + * syscall() to obtain it. */ -static void +_Py_NO_INLINE static void child_exec(char *const exec_array[], char *const argv[], char *const envp[], @@ -442,6 +465,7 @@ child_exec(char *const exec_array[], int call_setgid, gid_t gid, int call_setgroups, size_t groups_size, const gid_t *groups, int call_setuid, uid_t uid, int child_umask, + const void *child_sigmask, PyObject *py_fds_to_keep, PyObject *preexec_fn, PyObject *preexec_fn_args_tuple) @@ -517,6 +541,15 @@ child_exec(char *const exec_array[], if (restore_signals) _Py_RestoreSignals(); +#ifdef VFORK_USABLE + if (child_sigmask) { + reset_signal_handlers(child_sigmask); + if ((errno = pthread_sigmask(SIG_SETMASK, child_sigmask, NULL))) { + goto error; + } + } +#endif + #ifdef HAVE_SETSID if (call_setsid) POSIX_CALL(setsid()); @@ -609,8 +642,82 @@ error: } +/* The main purpose of this wrapper function is to isolate vfork() from both + * subprocess_fork_exec() and child_exec(). A child process created via + * vfork() executes on the same stack as the parent process while the latter is + * suspended, so this function should not be inlined to avoid compiler bugs + * that might clobber data needed by the parent later. Additionally, + * child_exec() should not be inlined to avoid spurious -Wclobber warnings from + * GCC (see bpo-35823). + */ +_Py_NO_INLINE static pid_t +do_fork_exec(char *const exec_array[], + char *const argv[], + char *const envp[], + const char *cwd, + int p2cread, int p2cwrite, + int c2pread, int c2pwrite, + int errread, int errwrite, + int errpipe_read, int errpipe_write, + int close_fds, int restore_signals, + int call_setsid, + int call_setgid, gid_t gid, + int call_setgroups, size_t groups_size, const gid_t *groups, + int call_setuid, uid_t uid, int child_umask, + const void *child_sigmask, + PyObject *py_fds_to_keep, + PyObject *preexec_fn, + PyObject *preexec_fn_args_tuple) +{ + + pid_t pid; + +#ifdef VFORK_USABLE + if (child_sigmask) { + /* These are checked by our caller; verify them in debug builds. */ + assert(!call_setuid); + assert(!call_setgid); + assert(!call_setgroups); + assert(preexec_fn == Py_None); + + pid = vfork(); + } else +#endif + { + pid = fork(); + } + + if (pid != 0) { + return pid; + } + + /* Child process. + * See the comment above child_exec() for restrictions imposed on + * the code below. + */ + + if (preexec_fn != Py_None) { + /* We'll be calling back into Python later so we need to do this. + * This call may not be async-signal-safe but neither is calling + * back into Python. The user asked us to use hope as a strategy + * to avoid deadlock... */ + PyOS_AfterFork_Child(); + } + + child_exec(exec_array, argv, envp, cwd, + p2cread, p2cwrite, c2pread, c2pwrite, + errread, errwrite, errpipe_read, errpipe_write, + close_fds, restore_signals, call_setsid, + call_setgid, gid, call_setgroups, groups_size, groups, + call_setuid, uid, child_umask, child_sigmask, + py_fds_to_keep, preexec_fn, preexec_fn_args_tuple); + _exit(255); + return 0; /* Dead code to avoid a potential compiler warning. */ +} + + static PyObject * -subprocess_fork_exec(PyObject* self, PyObject *args) +subprocess_fork_exec(PyObject *module, PyObject *args) { PyObject *gc_module = NULL; PyObject *executable_list, *py_fds_to_keep; @@ -628,7 +735,7 @@ subprocess_fork_exec(PyObject* self, PyObject *args) int child_umask; PyObject *cwd_obj, *cwd_obj2 = NULL; const char *cwd; - pid_t pid; + pid_t pid = -1; int need_to_reenable_gc = 0; char *const *exec_array, *const *argv = NULL, *const *envp = NULL; Py_ssize_t arg_num, num_groups = 0; @@ -673,30 +780,7 @@ subprocess_fork_exec(PyObject* self, PyObject *args) /* We need to call gc.disable() when we'll be calling preexec_fn */ if (preexec_fn != Py_None) { - PyObject *result; - - gc_module = PyImport_ImportModule("gc"); - if (gc_module == NULL) - return NULL; - result = PyObject_CallMethodNoArgs( - gc_module, _posixsubprocessstate_global->isenabled); - if (result == NULL) { - Py_DECREF(gc_module); - return NULL; - } - need_to_reenable_gc = PyObject_IsTrue(result); - Py_DECREF(result); - if (need_to_reenable_gc == -1) { - Py_DECREF(gc_module); - return NULL; - } - result = PyObject_CallMethodNoArgs( - gc_module, _posixsubprocessstate_global->disable); - if (result == NULL) { - Py_DECREF(gc_module); - return NULL; - } - Py_DECREF(result); + need_to_reenable_gc = PyGC_Disable(); } exec_array = _PySequence_BytesToCharpArray(executable_list); @@ -841,83 +925,92 @@ subprocess_fork_exec(PyObject* self, PyObject *args) need_after_fork = 1; } - pid = fork(); - if (pid == 0) { - /* Child process */ - /* - * Code from here to _exit() must only use async-signal-safe functions, - * listed at `man 7 signal` or - * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html. + /* NOTE: When old_sigmask is non-NULL, do_fork_exec() may use vfork(). */ + const void *old_sigmask = NULL; +#ifdef VFORK_USABLE + /* Use vfork() only if it's safe. See the comment above child_exec(). */ + sigset_t old_sigs; + if (preexec_fn == Py_None && + !call_setuid && !call_setgid && !call_setgroups) { + /* Block all signals to ensure that no signal handlers are run in the + * child process while it shares memory with us. Note that signals + * used internally by C libraries won't be blocked by + * pthread_sigmask(), but signal handlers installed by C libraries + * normally service only signals originating from *within the process*, + * so it should be sufficient to consider any library function that + * might send such a signal to be vfork-unsafe and do not call it in + * the child. */ - - if (preexec_fn != Py_None) { - /* We'll be calling back into Python later so we need to do this. - * This call may not be async-signal-safe but neither is calling - * back into Python. The user asked us to use hope as a strategy - * to avoid deadlock... */ - PyOS_AfterFork_Child(); + sigset_t all_sigs; + sigfillset(&all_sigs); + if ((saved_errno = pthread_sigmask(SIG_BLOCK, &all_sigs, &old_sigs))) { + goto cleanup; } - - child_exec(exec_array, argv, envp, cwd, - p2cread, p2cwrite, c2pread, c2pwrite, - errread, errwrite, errpipe_read, errpipe_write, - close_fds, restore_signals, call_setsid, - call_setgid, gid, call_setgroups, num_groups, groups, - call_setuid, uid, child_umask, - py_fds_to_keep, preexec_fn, preexec_fn_args_tuple); - _exit(255); - return NULL; /* Dead code to avoid a potential compiler warning. */ + old_sigmask = &old_sigs; } +#endif + + pid = do_fork_exec(exec_array, argv, envp, cwd, + p2cread, p2cwrite, c2pread, c2pwrite, + errread, errwrite, errpipe_read, errpipe_write, + close_fds, restore_signals, call_setsid, + call_setgid, gid, call_setgroups, num_groups, groups, + call_setuid, uid, child_umask, old_sigmask, + py_fds_to_keep, preexec_fn, preexec_fn_args_tuple); + /* Parent (original) process */ if (pid == -1) { /* Capture errno for the exception. */ saved_errno = errno; } - Py_XDECREF(cwd_obj2); +#ifdef VFORK_USABLE + if (old_sigmask) { + /* vfork() semantics guarantees that the parent is blocked + * until the child performs _exit() or execve(), so it is safe + * to unblock signals once we're here. + * Note that in environments where vfork() is implemented as fork(), + * such as QEMU user-mode emulation, the parent won't be blocked, + * but it won't share the address space with the child, + * so it's still safe to unblock the signals. + * + * We don't handle errors here because this call can't fail + * if valid arguments are given, and because there is no good + * way for the caller to deal with a failure to restore + * the thread signal mask. */ + (void) pthread_sigmask(SIG_SETMASK, old_sigmask, NULL); + } +#endif if (need_after_fork) PyOS_AfterFork_Parent(); - if (envp) - _Py_FreeCharPArray(envp); - if (argv) - _Py_FreeCharPArray(argv); - _Py_FreeCharPArray(exec_array); - - /* Reenable gc in the parent process (or if fork failed). */ - if (_enable_gc(need_to_reenable_gc, gc_module)) { - pid = -1; - } - PyMem_RawFree(groups); - Py_XDECREF(preexec_fn_args_tuple); - Py_XDECREF(gc_module); - if (pid == -1) { +cleanup: + if (saved_errno != 0) { errno = saved_errno; /* We can't call this above as PyOS_AfterFork_Parent() calls back * into Python code which would see the unreturned error. */ PyErr_SetFromErrno(PyExc_OSError); - return NULL; /* fork() failed. */ } - return PyLong_FromPid(pid); - -cleanup: + Py_XDECREF(preexec_fn_args_tuple); + PyMem_RawFree(groups); Py_XDECREF(cwd_obj2); if (envp) _Py_FreeCharPArray(envp); + Py_XDECREF(converted_args); + Py_XDECREF(fast_args); if (argv) _Py_FreeCharPArray(argv); if (exec_array) _Py_FreeCharPArray(exec_array); - PyMem_RawFree(groups); - Py_XDECREF(converted_args); - Py_XDECREF(fast_args); - Py_XDECREF(preexec_fn_args_tuple); - _enable_gc(need_to_reenable_gc, gc_module); + if (need_to_reenable_gc) { + PyGC_Enable(); + } Py_XDECREF(gc_module); - return NULL; + + return pid == -1 ? NULL : PyLong_FromPid(pid); } @@ -954,63 +1047,26 @@ Raises: Only on an error in the parent process.\n\ PyDoc_STRVAR(module_doc, "A POSIX helper for the subprocess module."); - static PyMethodDef module_methods[] = { {"fork_exec", subprocess_fork_exec, METH_VARARGS, subprocess_fork_exec_doc}, {NULL, NULL} /* sentinel */ }; - -static int _posixsubprocess_traverse(PyObject *m, visitproc visit, void *arg) { - Py_VISIT(get_posixsubprocess_state(m)->disable); - Py_VISIT(get_posixsubprocess_state(m)->enable); - Py_VISIT(get_posixsubprocess_state(m)->isenabled); - return 0; -} - -static int _posixsubprocess_clear(PyObject *m) { - Py_CLEAR(get_posixsubprocess_state(m)->disable); - Py_CLEAR(get_posixsubprocess_state(m)->enable); - Py_CLEAR(get_posixsubprocess_state(m)->isenabled); - return 0; -} - -static void _posixsubprocess_free(void *m) { - _posixsubprocess_clear((PyObject *)m); -} +static PyModuleDef_Slot _posixsubprocess_slots[] = { + {0, NULL} +}; static struct PyModuleDef _posixsubprocessmodule = { PyModuleDef_HEAD_INIT, - "_posixsubprocess", - module_doc, - sizeof(_posixsubprocessstate), - module_methods, - NULL, - _posixsubprocess_traverse, - _posixsubprocess_clear, - _posixsubprocess_free, + .m_name = "_posixsubprocess", + .m_doc = module_doc, + .m_size = 0, + .m_methods = module_methods, + .m_slots = _posixsubprocess_slots, }; PyMODINIT_FUNC PyInit__posixsubprocess(void) { - PyObject* m; - - m = PyState_FindModule(&_posixsubprocessmodule); - if (m != NULL) { - Py_INCREF(m); - return m; - } - - m = PyModule_Create(&_posixsubprocessmodule); - if (m == NULL) { - return NULL; - } - - get_posixsubprocess_state(m)->disable = PyUnicode_InternFromString("disable"); - get_posixsubprocess_state(m)->enable = PyUnicode_InternFromString("enable"); - get_posixsubprocess_state(m)->isenabled = PyUnicode_InternFromString("isenabled"); - - PyState_AddModule(m, &_posixsubprocessmodule); - return m; + return PyModuleDef_Init(&_posixsubprocessmodule); } diff --git a/contrib/tools/python3/src/Modules/_queuemodule.c b/contrib/tools/python3/src/Modules/_queuemodule.c index b155ea9423..a124255a72 100644 --- a/contrib/tools/python3/src/Modules/_queuemodule.c +++ b/contrib/tools/python3/src/Modules/_queuemodule.c @@ -1,16 +1,23 @@ #include "Python.h" +#include "pycore_moduleobject.h" // _PyModule_GetState() +#include "structmember.h" // PyMemberDef #include <stddef.h> // offsetof() -/*[clinic input] -module _queue -class _queue.SimpleQueue "simplequeueobject *" "&PySimpleQueueType" -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=cf49af81bcbbbea6]*/ - -static PyTypeObject PySimpleQueueType; /* forward decl */ - -static PyObject *EmptyError; +typedef struct { + PyTypeObject *SimpleQueueType; + PyObject *EmptyError; +} simplequeue_state; +static simplequeue_state * +simplequeue_get_state(PyObject *module) +{ + simplequeue_state *state = _PyModule_GetState(module); + assert(state); + return state; +} +static struct PyModuleDef queuemodule; +#define simplequeue_get_state_by_type(type) \ + (simplequeue_get_state(_PyType_GetModuleByDef(type, &queuemodule))) typedef struct { PyObject_HEAD @@ -21,10 +28,24 @@ typedef struct { PyObject *weakreflist; } simplequeueobject; +/*[clinic input] +module _queue +class _queue.SimpleQueue "simplequeueobject *" "simplequeue_get_state_by_type(type)->SimpleQueueType" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=0a4023fe4d198c8d]*/ + +static int +simplequeue_clear(simplequeueobject *self) +{ + Py_CLEAR(self->lst); + return 0; +} static void simplequeue_dealloc(simplequeueobject *self) { + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); if (self->lock != NULL) { /* Unlock the lock so it's safe to free it */ @@ -32,16 +53,18 @@ simplequeue_dealloc(simplequeueobject *self) PyThread_release_lock(self->lock); PyThread_free_lock(self->lock); } - Py_XDECREF(self->lst); + (void)simplequeue_clear(self); if (self->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) self); Py_TYPE(self)->tp_free(self); + Py_DECREF(tp); } static int simplequeue_traverse(simplequeueobject *self, visitproc visit, void *arg) { Py_VISIT(self->lst); + Py_VISIT(Py_TYPE(self)); return 0; } @@ -155,6 +178,9 @@ simplequeue_pop_item(simplequeueobject *self) /*[clinic input] _queue.SimpleQueue.get + + cls: defining_class + / block: bool = True timeout: object = None @@ -171,9 +197,9 @@ in that case). [clinic start generated code]*/ static PyObject * -_queue_SimpleQueue_get_impl(simplequeueobject *self, int block, - PyObject *timeout) -/*[clinic end generated code: output=ec82a7157dcccd1a input=4bf691f9f01fa297]*/ +_queue_SimpleQueue_get_impl(simplequeueobject *self, PyTypeObject *cls, + int block, PyObject *timeout) +/*[clinic end generated code: output=1969aefa7db63666 input=5fc4d56b9a54757e]*/ { _PyTime_t endtime = 0; _PyTime_t timeout_val; @@ -225,8 +251,10 @@ _queue_SimpleQueue_get_impl(simplequeueobject *self, int block, return NULL; } if (r == PY_LOCK_FAILURE) { + PyObject *module = PyType_GetModule(cls); + simplequeue_state *state = simplequeue_get_state(module); /* Timed out */ - PyErr_SetNone(EmptyError); + PyErr_SetNone(state->EmptyError); return NULL; } self->locked = 1; @@ -251,6 +279,9 @@ _queue_SimpleQueue_get_impl(simplequeueobject *self, int block, /*[clinic input] _queue.SimpleQueue.get_nowait + cls: defining_class + / + Remove and return an item from the queue without blocking. Only get an item if one is immediately available. Otherwise @@ -258,10 +289,11 @@ raise the Empty exception. [clinic start generated code]*/ static PyObject * -_queue_SimpleQueue_get_nowait_impl(simplequeueobject *self) -/*[clinic end generated code: output=a89731a75dbe4937 input=6fe5102db540a1b9]*/ +_queue_SimpleQueue_get_nowait_impl(simplequeueobject *self, + PyTypeObject *cls) +/*[clinic end generated code: output=620c58e2750f8b8a input=842f732bf04216d3]*/ { - return _queue_SimpleQueue_get_impl(self, 0, Py_None); + return _queue_SimpleQueue_get_impl(self, cls, 0, Py_None); } /*[clinic input] @@ -290,6 +322,29 @@ _queue_SimpleQueue_qsize_impl(simplequeueobject *self) return PyList_GET_SIZE(self->lst) - self->lst_pos; } +static int +queue_traverse(PyObject *m, visitproc visit, void *arg) +{ + simplequeue_state *state = simplequeue_get_state(m); + Py_VISIT(state->SimpleQueueType); + Py_VISIT(state->EmptyError); + return 0; +} + +static int +queue_clear(PyObject *m) +{ + simplequeue_state *state = simplequeue_get_state(m); + Py_CLEAR(state->SimpleQueueType); + Py_CLEAR(state->EmptyError); + return 0; +} + +static void +queue_free(void *m) +{ + queue_clear((PyObject *)m); +} #include "clinic/_queuemodule.c.h" @@ -306,48 +361,28 @@ static PyMethodDef simplequeue_methods[] = { {NULL, NULL} /* sentinel */ }; +static struct PyMemberDef simplequeue_members[] = { + {"__weaklistoffset__", T_PYSSIZET, offsetof(simplequeueobject, weakreflist), READONLY}, + {NULL}, +}; + +static PyType_Slot simplequeue_slots[] = { + {Py_tp_dealloc, simplequeue_dealloc}, + {Py_tp_doc, (void *)simplequeue_new__doc__}, + {Py_tp_traverse, simplequeue_traverse}, + {Py_tp_clear, simplequeue_clear}, + {Py_tp_members, simplequeue_members}, + {Py_tp_methods, simplequeue_methods}, + {Py_tp_new, simplequeue_new}, + {0, NULL}, +}; -static PyTypeObject PySimpleQueueType = { - PyVarObject_HEAD_INIT(NULL, 0) - "_queue.SimpleQueue", /*tp_name*/ - sizeof(simplequeueobject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)simplequeue_dealloc, /*tp_dealloc*/ - 0, /*tp_vectorcall_offset*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_as_async*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE - | Py_TPFLAGS_HAVE_GC, /* tp_flags */ - simplequeue_new__doc__, /*tp_doc*/ - (traverseproc)simplequeue_traverse, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - offsetof(simplequeueobject, weakreflist), /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - simplequeue_methods, /*tp_methods*/ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - simplequeue_new /* tp_new */ +static PyType_Spec simplequeue_spec = { + .name = "_queue.SimpleQueue", + .basicsize = sizeof(simplequeueobject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = simplequeue_slots, }; @@ -357,43 +392,54 @@ PyDoc_STRVAR(queue_module_doc, "C implementation of the Python queue module.\n\ This module is an implementation detail, please do not use it directly."); -static struct PyModuleDef queuemodule = { - PyModuleDef_HEAD_INIT, - "_queue", - queue_module_doc, - -1, - NULL, - NULL, - NULL, - NULL, - NULL -}; - - -PyMODINIT_FUNC -PyInit__queue(void) +static int +queuemodule_exec(PyObject *module) { - PyObject *m; - - /* Create the module */ - m = PyModule_Create(&queuemodule); - if (m == NULL) - return NULL; + simplequeue_state *state = simplequeue_get_state(module); - EmptyError = PyErr_NewExceptionWithDoc( + state->EmptyError = PyErr_NewExceptionWithDoc( "_queue.Empty", "Exception raised by Queue.get(block=0)/get_nowait().", NULL, NULL); - if (EmptyError == NULL) - return NULL; - - Py_INCREF(EmptyError); - if (PyModule_AddObject(m, "Empty", EmptyError) < 0) - return NULL; + if (state->EmptyError == NULL) { + return -1; + } + if (PyModule_AddObjectRef(module, "Empty", state->EmptyError) < 0) { + return -1; + } - if (PyModule_AddType(m, &PySimpleQueueType) < 0) { - return NULL; + state->SimpleQueueType = (PyTypeObject *)PyType_FromModuleAndSpec( + module, &simplequeue_spec, NULL); + if (state->SimpleQueueType == NULL) { + return -1; } + if (PyModule_AddType(module, state->SimpleQueueType) < 0) { + return -1; + } + + return 0; +} + +static PyModuleDef_Slot queuemodule_slots[] = { + {Py_mod_exec, queuemodule_exec}, + {0, NULL} +}; - return m; + +static struct PyModuleDef queuemodule = { + .m_base = PyModuleDef_HEAD_INIT, + .m_name = "_queue", + .m_doc = queue_module_doc, + .m_size = sizeof(simplequeue_state), + .m_slots = queuemodule_slots, + .m_traverse = queue_traverse, + .m_clear = queue_clear, + .m_free = queue_free, +}; + + +PyMODINIT_FUNC +PyInit__queue(void) +{ + return PyModuleDef_Init(&queuemodule); } diff --git a/contrib/tools/python3/src/Modules/_randommodule.c b/contrib/tools/python3/src/Modules/_randommodule.c index a402b937f7..0137e34da6 100644 --- a/contrib/tools/python3/src/Modules/_randommodule.c +++ b/contrib/tools/python3/src/Modules/_randommodule.c @@ -67,7 +67,7 @@ /* ---------------------------------------------------------------*/ #include "Python.h" -#include "pycore_byteswap.h" // _Py_bswap32() +#include "pycore_moduleobject.h" // _PyModule_GetState() #ifdef HAVE_PROCESS_H # include <process.h> // getpid() #endif @@ -87,14 +87,15 @@ typedef struct { static inline _randomstate* get_random_state(PyObject *module) { - void *state = PyModule_GetState(module); + void *state = _PyModule_GetState(module); assert(state != NULL); return (_randomstate *)state; } static struct PyModuleDef _randommodule; -#define _randomstate_global get_random_state(PyState_FindModule(&_randommodule)) +#define _randomstate_type(type) \ + (get_random_state(_PyType_GetModuleByDef(type, &_randommodule))) typedef struct { PyObject_HEAD @@ -107,9 +108,9 @@ typedef struct { /*[clinic input] module _random -class _random.Random "RandomObject *" "&Random_Type" +class _random.Random "RandomObject *" "_randomstate_type(type)->Random_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f79898ae7847c321]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=70a2c99619474983]*/ /* Random methods */ @@ -291,7 +292,8 @@ random_seed(RandomObject *self, PyObject *arg) } else if (PyLong_Check(arg)) { /* Calling int.__abs__() prevents calling arg.__abs__(), which might return an invalid value. See issue #31478. */ - n = PyObject_CallOneArg(_randomstate_global->Long___abs__, arg); + _randomstate *state = _randomstate_type(Py_TYPE(self)); + n = PyObject_CallOneArg(state->Long___abs__, arg); } else { Py_hash_t hash = PyObject_Hash(arg); @@ -518,8 +520,10 @@ random_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { RandomObject *self; PyObject *tmp; + PyObject *arg = NULL; + _randomstate *state = _randomstate_type(type); - if (type == (PyTypeObject*)_randomstate_global->Random_Type && + if (type == (PyTypeObject*)state->Random_Type && !_PyArg_NoKeywords("Random()", kwds)) { return NULL; } @@ -527,12 +531,22 @@ random_new(PyTypeObject *type, PyObject *args, PyObject *kwds) self = (RandomObject *)PyType_GenericAlloc(type, 0); if (self == NULL) return NULL; - tmp = random_seed(self, args); + + if (PyTuple_GET_SIZE(args) > 1) { + PyErr_SetString(PyExc_TypeError, "Random() requires 0 or 1 argument"); + return NULL; + } + + if (PyTuple_GET_SIZE(args) == 1) + arg = PyTuple_GET_ITEM(args, 0); + + tmp = random_seed(self, arg); if (tmp == NULL) { Py_DECREF(self); return NULL; } Py_DECREF(tmp); + return (PyObject *)self; } @@ -569,6 +583,45 @@ PyDoc_STRVAR(module_doc, "Module implements the Mersenne Twister random number generator."); static int +_random_exec(PyObject *module) +{ + _randomstate *state = get_random_state(module); + + state->Random_Type = PyType_FromModuleAndSpec( + module, &Random_Type_spec, NULL); + if (state->Random_Type == NULL) { + return -1; + } + if (PyModule_AddType(module, (PyTypeObject *)state->Random_Type) < 0) { + return -1; + } + + /* Look up and save int.__abs__, which is needed in random_seed(). */ + PyObject *longval = PyLong_FromLong(0); + if (longval == NULL) { + return -1; + } + + PyObject *longtype = PyObject_Type(longval); + Py_DECREF(longval); + if (longtype == NULL) { + return -1; + } + + state->Long___abs__ = PyObject_GetAttrString(longtype, "__abs__"); + Py_DECREF(longtype); + if (state->Long___abs__ == NULL) { + return -1; + } + return 0; +} + +static PyModuleDef_Slot _random_slots[] = { + {Py_mod_exec, _random_exec}, + {0, NULL} +}; + +static int _random_traverse(PyObject *module, visitproc visit, void *arg) { Py_VISIT(get_random_state(module)->Random_Type); @@ -595,7 +648,7 @@ static struct PyModuleDef _randommodule = { module_doc, sizeof(_randomstate), NULL, - NULL, + _random_slots, _random_traverse, _random_clear, _random_free, @@ -604,43 +657,5 @@ static struct PyModuleDef _randommodule = { PyMODINIT_FUNC PyInit__random(void) { - PyObject *m; - - PyObject *Random_Type = PyType_FromSpec(&Random_Type_spec); - if (Random_Type == NULL) { - return NULL; - } - - m = PyModule_Create(&_randommodule); - if (m == NULL) { - Py_DECREF(Random_Type); - return NULL; - } - get_random_state(m)->Random_Type = Random_Type; - - Py_INCREF(Random_Type); - PyModule_AddObject(m, "Random", Random_Type); - - /* Look up and save int.__abs__, which is needed in random_seed(). */ - PyObject *longval = NULL, *longtype = NULL; - longval = PyLong_FromLong(0); - if (longval == NULL) goto fail; - - longtype = PyObject_Type(longval); - if (longtype == NULL) goto fail; - - PyObject *abs = PyObject_GetAttrString(longtype, "__abs__"); - if (abs == NULL) goto fail; - - Py_DECREF(longtype); - Py_DECREF(longval); - get_random_state(m)->Long___abs__ = abs; - - return m; - -fail: - Py_XDECREF(longtype); - Py_XDECREF(longval); - Py_DECREF(m); - return NULL; + return PyModuleDef_Init(&_randommodule); } diff --git a/contrib/tools/python3/src/Modules/_scproxy.c b/contrib/tools/python3/src/Modules/_scproxy.c index dbee3f7367..4c1f1aa300 100644 --- a/contrib/tools/python3/src/Modules/_scproxy.c +++ b/contrib/tools/python3/src/Modules/_scproxy.c @@ -231,21 +231,18 @@ static PyMethodDef mod_methods[] = { { 0, 0, 0, 0 } }; +static PyModuleDef_Slot _scproxy_slots[] = { + {0, NULL} +}; - -static struct PyModuleDef mod_module = { +static struct PyModuleDef _scproxy_module = { PyModuleDef_HEAD_INIT, - "_scproxy", - NULL, - -1, - mod_methods, - NULL, - NULL, - NULL, - NULL + .m_name = "_scproxy", + .m_size = 0, + .m_methods = mod_methods, + .m_slots = _scproxy_slots, }; - #ifdef __cplusplus extern "C" { #endif @@ -253,10 +250,9 @@ extern "C" { PyMODINIT_FUNC PyInit__scproxy(void) { - return PyModule_Create(&mod_module); + return PyModuleDef_Init(&_scproxy_module); } #ifdef __cplusplus } #endif - diff --git a/contrib/tools/python3/src/Modules/_sha3/sha3module.c b/contrib/tools/python3/src/Modules/_sha3/sha3module.c index b6a7130dd8..3974e0b6b4 100644 --- a/contrib/tools/python3/src/Modules/_sha3/sha3module.c +++ b/contrib/tools/python3/src/Modules/_sha3/sha3module.c @@ -127,6 +127,28 @@ #define SHA3_squeeze Keccak_HashSqueeze #define SHA3_copystate(dest, src) memcpy(&(dest), &(src), sizeof(SHA3_state)) +typedef struct { + PyTypeObject *sha3_224_type; + PyTypeObject *sha3_256_type; + PyTypeObject *sha3_384_type; + PyTypeObject *sha3_512_type; +#ifdef PY_WITH_KECCAK + PyTypeObject *keccak_224_type; + PyTypeObject *keccak_256_type; + PyTypeObject *keccak_384_type; + PyTypeObject *keccak_512_type; +#endif + PyTypeObject *shake_128_type; + PyTypeObject *shake_256_type; +} SHA3State; + +static inline SHA3State* +sha3_get_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (SHA3State *)state; +} /*[clinic input] module _sha3 @@ -147,19 +169,6 @@ typedef struct { PyThread_type_lock lock; } SHA3object; -static PyTypeObject SHA3_224type; -static PyTypeObject SHA3_256type; -static PyTypeObject SHA3_384type; -static PyTypeObject SHA3_512type; -#ifdef PY_WITH_KECCAK -static PyTypeObject Keccak_224type; -static PyTypeObject Keccak_256type; -static PyTypeObject Keccak_384type; -static PyTypeObject Keccak_512type; -#endif -static PyTypeObject SHAKE128type; -static PyTypeObject SHAKE256type; - #include "clinic/sha3module.c.h" static SHA3object * @@ -189,42 +198,49 @@ static PyObject * py_sha3_new_impl(PyTypeObject *type, PyObject *data, int usedforsecurity) /*[clinic end generated code: output=90409addc5d5e8b0 input=bcfcdf2e4368347a]*/ { - SHA3object *self = NULL; - Py_buffer buf = {NULL, NULL}; HashReturn res; - - self = newSHA3object(type); + Py_buffer buf = {NULL, NULL}; + SHA3State *state = PyType_GetModuleState(type); + SHA3object *self = newSHA3object(type); if (self == NULL) { goto error; } - if (type == &SHA3_224type) { + assert(state != NULL); + + if (type == state->sha3_224_type) { res = Keccak_HashInitialize_SHA3_224(&self->hash_state); - } else if (type == &SHA3_256type) { + } else if (type == state->sha3_256_type) { res = Keccak_HashInitialize_SHA3_256(&self->hash_state); - } else if (type == &SHA3_384type) { + } else if (type == state->sha3_384_type) { res = Keccak_HashInitialize_SHA3_384(&self->hash_state); - } else if (type == &SHA3_512type) { + } else if (type == state->sha3_512_type) { res = Keccak_HashInitialize_SHA3_512(&self->hash_state); #ifdef PY_WITH_KECCAK - } else if (type == &Keccak_224type) { + } else if (type == state->keccak_224_type) { res = Keccak_HashInitialize(&self->hash_state, 1152, 448, 224, 0x01); - } else if (type == &Keccak_256type) { + } else if (type == state->keccak_256_type) { res = Keccak_HashInitialize(&self->hash_state, 1088, 512, 256, 0x01); - } else if (type == &Keccak_384type) { + } else if (type == state->keccak_384_type) { res = Keccak_HashInitialize(&self->hash_state, 832, 768, 384, 0x01); - } else if (type == &Keccak_512type) { + } else if (type == state->keccak_512_type) { res = Keccak_HashInitialize(&self->hash_state, 576, 1024, 512, 0x01); #endif - } else if (type == &SHAKE128type) { + } else if (type == state->shake_128_type) { res = Keccak_HashInitialize_SHAKE128(&self->hash_state); - } else if (type == &SHAKE256type) { + } else if (type == state->shake_256_type) { res = Keccak_HashInitialize_SHAKE256(&self->hash_state); } else { PyErr_BadInternalCall(); goto error; } + if (res != SUCCESS) { + PyErr_SetString(PyExc_RuntimeError, + "internal error in SHA3 initialize()"); + goto error; + } + if (data) { GET_BUFFER_VIEW_OR_ERROR(data, &buf, goto error); if (buf.len >= HASHLIB_GIL_MINSIZE) { @@ -267,7 +283,10 @@ SHA3_dealloc(SHA3object *self) if (self->lock) { PyThread_free_lock(self->lock); } - PyObject_Del(self); + + PyTypeObject *tp = Py_TYPE(self); + PyObject_Free(self); + Py_DECREF(tp); } @@ -421,27 +440,31 @@ static PyObject * SHA3_get_name(SHA3object *self, void *closure) { PyTypeObject *type = Py_TYPE(self); - if (type == &SHA3_224type) { + + SHA3State *state = PyType_GetModuleState(type); + assert(state != NULL); + + if (type == state->sha3_224_type) { return PyUnicode_FromString("sha3_224"); - } else if (type == &SHA3_256type) { + } else if (type == state->sha3_256_type) { return PyUnicode_FromString("sha3_256"); - } else if (type == &SHA3_384type) { + } else if (type == state->sha3_384_type) { return PyUnicode_FromString("sha3_384"); - } else if (type == &SHA3_512type) { + } else if (type == state->sha3_512_type) { return PyUnicode_FromString("sha3_512"); #ifdef PY_WITH_KECCAK - } else if (type == &Keccak_224type) { + } else if (type == state->keccak_224_type) { return PyUnicode_FromString("keccak_224"); - } else if (type == &Keccak_256type) { + } else if (type == state->keccak_256_type) { return PyUnicode_FromString("keccak_256"); - } else if (type == &Keccak_384type) { + } else if (type == state->keccak_384_type) { return PyUnicode_FromString("keccak_384"); - } else if (type == &Keccak_512type) { + } else if (type == state->keccak_512_type) { return PyUnicode_FromString("keccak_512"); #endif - } else if (type == &SHAKE128type) { + } else if (type == state->shake_128_type) { return PyUnicode_FromString("shake_128"); - } else if (type == &SHAKE256type) { + } else if (type == state->shake_256_type) { return PyUnicode_FromString("shake_256"); } else { PyErr_BadInternalCall(); @@ -481,7 +504,6 @@ SHA3_get_suffix(SHA3object *self, void *closure) return PyBytes_FromStringAndSize((const char *)suffix, 1); } - static PyGetSetDef SHA3_getseters[] = { {"block_size", (getter)SHA3_get_block_size, NULL, NULL, NULL}, {"name", (getter)SHA3_get_name, NULL, NULL, NULL}, @@ -492,48 +514,24 @@ static PyGetSetDef SHA3_getseters[] = { {NULL} /* Sentinel */ }; +#define SHA3_TYPE_SLOTS(type_slots_obj, type_doc, type_methods) \ + static PyType_Slot type_slots_obj[] = { \ + {Py_tp_dealloc, SHA3_dealloc}, \ + {Py_tp_doc, (char*)type_doc}, \ + {Py_tp_methods, type_methods}, \ + {Py_tp_getset, SHA3_getseters}, \ + {Py_tp_new, py_sha3_new}, \ + {0,0} \ + } -#define SHA3_TYPE(type_obj, type_name, type_doc, type_methods) \ - static PyTypeObject type_obj = { \ - PyVarObject_HEAD_INIT(NULL, 0) \ - type_name, /* tp_name */ \ - sizeof(SHA3object), /* tp_basicsize */ \ - 0, /* tp_itemsize */ \ - /* methods */ \ - (destructor)SHA3_dealloc, /* tp_dealloc */ \ - 0, /* tp_vectorcall_offset */ \ - 0, /* tp_getattr */ \ - 0, /* tp_setattr */ \ - 0, /* tp_as_async */ \ - 0, /* tp_repr */ \ - 0, /* tp_as_number */ \ - 0, /* tp_as_sequence */ \ - 0, /* tp_as_mapping */ \ - 0, /* tp_hash */ \ - 0, /* tp_call */ \ - 0, /* tp_str */ \ - 0, /* tp_getattro */ \ - 0, /* tp_setattro */ \ - 0, /* tp_as_buffer */ \ - Py_TPFLAGS_DEFAULT, /* tp_flags */ \ - type_doc, /* tp_doc */ \ - 0, /* tp_traverse */ \ - 0, /* tp_clear */ \ - 0, /* tp_richcompare */ \ - 0, /* tp_weaklistoffset */ \ - 0, /* tp_iter */ \ - 0, /* tp_iternext */ \ - type_methods, /* tp_methods */ \ - NULL, /* tp_members */ \ - SHA3_getseters, /* tp_getset */ \ - 0, /* tp_base */ \ - 0, /* tp_dict */ \ - 0, /* tp_descr_get */ \ - 0, /* tp_descr_set */ \ - 0, /* tp_dictoffset */ \ - 0, /* tp_init */ \ - 0, /* tp_alloc */ \ - py_sha3_new, /* tp_new */ \ +// Using PyType_GetModuleState() on these types is safe since they +// cannot be subclassed: it does not have the Py_TPFLAGS_BASETYPE flag. +#define SHA3_TYPE_SPEC(type_spec_obj, type_name, type_slots) \ + static PyType_Spec type_spec_obj = { \ + .name = "_sha3." type_name, \ + .basicsize = sizeof(SHA3object), \ + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE, \ + .slots = type_slots \ } PyDoc_STRVAR(sha3_224__doc__, @@ -556,11 +554,6 @@ PyDoc_STRVAR(sha3_512__doc__, \n\ Return a new SHA3 hash object with a hashbit length of 64 bytes."); -SHA3_TYPE(SHA3_224type, "_sha3.sha3_224", sha3_224__doc__, SHA3_methods); -SHA3_TYPE(SHA3_256type, "_sha3.sha3_256", sha3_256__doc__, SHA3_methods); -SHA3_TYPE(SHA3_384type, "_sha3.sha3_384", sha3_384__doc__, SHA3_methods); -SHA3_TYPE(SHA3_512type, "_sha3.sha3_512", sha3_512__doc__, SHA3_methods); - #ifdef PY_WITH_KECCAK PyDoc_STRVAR(keccak_224__doc__, "keccak_224([data], *, usedforsecurity=True) -> Keccak object\n\ @@ -582,10 +575,32 @@ PyDoc_STRVAR(keccak_512__doc__, \n\ Return a new Keccak hash object with a hashbit length of 64 bytes."); -SHA3_TYPE(Keccak_224type, "_sha3.keccak_224", keccak_224__doc__, SHA3_methods); -SHA3_TYPE(Keccak_256type, "_sha3.keccak_256", keccak_256__doc__, SHA3_methods); -SHA3_TYPE(Keccak_384type, "_sha3.keccak_384", keccak_384__doc__, SHA3_methods); -SHA3_TYPE(Keccak_512type, "_sha3.keccak_512", keccak_512__doc__, SHA3_methods); +#endif + +SHA3_TYPE_SLOTS(sha3_224_slots, sha3_224__doc__, SHA3_methods); +SHA3_TYPE_SPEC(sha3_224_spec, "sha3_224", sha3_224_slots); + +SHA3_TYPE_SLOTS(sha3_256_slots, sha3_256__doc__, SHA3_methods); +SHA3_TYPE_SPEC(sha3_256_spec, "sha3_256", sha3_256_slots); + +SHA3_TYPE_SLOTS(sha3_384_slots, sha3_384__doc__, SHA3_methods); +SHA3_TYPE_SPEC(sha3_384_spec, "sha3_384", sha3_384_slots); + +SHA3_TYPE_SLOTS(sha3_512_slots, sha3_512__doc__, SHA3_methods); +SHA3_TYPE_SPEC(sha3_512_spec, "sha3_512", sha3_512_slots); + +#ifdef PY_WITH_KECCAK +SHA3_TYPE_SLOTS(Keccak_224_slots, keccak_224__doc__, SHA3_methods); +SHA3_TYPE_SPEC(Keccak_224_spec, "keccak_224", Keccak_224_slots); + +SHA3_TYPE_SLOTS(Keccak_256_slots, keccak_256__doc__, SHA3_methods); +SHA3_TYPE_SPEC(Keccak_256_spec, "keccak_256", Keccak_256_slots); + +SHA3_TYPE_SLOTS(Keccak_384_slots, keccak_384__doc__, SHA3_methods); +SHA3_TYPE_SPEC(Keccak_384_spec, "keccak_384", Keccak_384_slots); + +SHA3_TYPE_SLOTS(Keccak_512_slots, keccak_512__doc__, SHA3_methods); +SHA3_TYPE_SPEC(Keccak_512_spec, "keccak_512", Keccak_512_slots); #endif @@ -689,70 +704,118 @@ PyDoc_STRVAR(shake_256__doc__, \n\ Return a new SHAKE hash object."); -SHA3_TYPE(SHAKE128type, "_sha3.shake_128", shake_128__doc__, SHAKE_methods); -SHA3_TYPE(SHAKE256type, "_sha3.shake_256", shake_256__doc__, SHAKE_methods); +SHA3_TYPE_SLOTS(SHAKE128slots, shake_128__doc__, SHAKE_methods); +SHA3_TYPE_SPEC(SHAKE128_spec, "shake_128", SHAKE128slots); +SHA3_TYPE_SLOTS(SHAKE256slots, shake_256__doc__, SHAKE_methods); +SHA3_TYPE_SPEC(SHAKE256_spec, "shake_256", SHAKE256slots); -/* Initialize this module. */ -static struct PyModuleDef _SHA3module = { - PyModuleDef_HEAD_INIT, - "_sha3", - NULL, - -1, - NULL, - NULL, - NULL, - NULL, - NULL -}; +static int +_sha3_traverse(PyObject *module, visitproc visit, void *arg) +{ + SHA3State *state = sha3_get_state(module); + Py_VISIT(state->sha3_224_type); + Py_VISIT(state->sha3_256_type); + Py_VISIT(state->sha3_384_type); + Py_VISIT(state->sha3_512_type); +#ifdef PY_WITH_KECCAK + Py_VISIT(state->keccak_224_type); + Py_VISIT(state->keccak_256_type); + Py_VISIT(state->keccak_384_type); + Py_VISIT(state->keccak_512_type); +#endif + Py_VISIT(state->shake_128_type); + Py_VISIT(state->shake_256_type); + return 0; +} -PyMODINIT_FUNC -PyInit__sha3(void) +static int +_sha3_clear(PyObject *module) { - PyObject *m = NULL; + SHA3State *state = sha3_get_state(module); + Py_CLEAR(state->sha3_224_type); + Py_CLEAR(state->sha3_256_type); + Py_CLEAR(state->sha3_384_type); + Py_CLEAR(state->sha3_512_type); +#ifdef PY_WITH_KECCAK + Py_CLEAR(state->keccak_224_type); + Py_CLEAR(state->keccak_256_type); + Py_CLEAR(state->keccak_384_type); + Py_CLEAR(state->keccak_512_type); +#endif + Py_CLEAR(state->shake_128_type); + Py_CLEAR(state->shake_256_type); + return 0; +} - if ((m = PyModule_Create(&_SHA3module)) == NULL) { - return NULL; - } +static void +_sha3_free(void *module) +{ + _sha3_clear((PyObject *)module); +} -#define init_sha3type(name, type) \ - do { \ - Py_SET_TYPE(type, &PyType_Type); \ - if (PyType_Ready(type) < 0) { \ - goto error; \ - } \ - Py_INCREF((PyObject *)type); \ - if (PyModule_AddObject(m, name, (PyObject *)type) < 0) { \ - goto error; \ - } \ +static int +_sha3_exec(PyObject *m) +{ + SHA3State *st = sha3_get_state(m); + +#define init_sha3type(type, typespec) \ + do { \ + st->type = (PyTypeObject *)PyType_FromModuleAndSpec( \ + m, &typespec, NULL); \ + if (st->type == NULL) { \ + return -1; \ + } \ + if (PyModule_AddType(m, st->type) < 0) { \ + return -1; \ + } \ } while(0) - init_sha3type("sha3_224", &SHA3_224type); - init_sha3type("sha3_256", &SHA3_256type); - init_sha3type("sha3_384", &SHA3_384type); - init_sha3type("sha3_512", &SHA3_512type); + init_sha3type(sha3_224_type, sha3_224_spec); + init_sha3type(sha3_256_type, sha3_256_spec); + init_sha3type(sha3_384_type, sha3_384_spec); + init_sha3type(sha3_512_type, sha3_512_spec); #ifdef PY_WITH_KECCAK - init_sha3type("keccak_224", &Keccak_224type); - init_sha3type("keccak_256", &Keccak_256type); - init_sha3type("keccak_384", &Keccak_384type); - init_sha3type("keccak_512", &Keccak_512type); + init_sha3type(keccak_224_type, Keccak_224_spec); + init_sha3type(keccak_256_type, Keccak_256_spec); + init_sha3type(keccak_384_type, Keccak_384_spec); + init_sha3type(keccak_512_type, Keccak_512_spec); #endif - init_sha3type("shake_128", &SHAKE128type); - init_sha3type("shake_256", &SHAKE256type); - + init_sha3type(shake_128_type, SHAKE128_spec); + init_sha3type(shake_256_type, SHAKE256_spec); #undef init_sha3type if (PyModule_AddIntConstant(m, "keccakopt", KeccakOpt) < 0) { - goto error; + return -1; } if (PyModule_AddStringConstant(m, "implementation", KeccakP1600_implementation) < 0) { - goto error; + return -1; } - return m; - error: - Py_DECREF(m); - return NULL; + return 0; +} + +static PyModuleDef_Slot _sha3_slots[] = { + {Py_mod_exec, _sha3_exec}, + {0, NULL} +}; + +/* Initialize this module. */ +static struct PyModuleDef _sha3module = { + PyModuleDef_HEAD_INIT, + .m_name = "_sha3", + .m_size = sizeof(SHA3State), + .m_slots = _sha3_slots, + .m_traverse = _sha3_traverse, + .m_clear = _sha3_clear, + .m_free = _sha3_free, +}; + + +PyMODINIT_FUNC +PyInit__sha3(void) +{ + return PyModuleDef_Init(&_sha3module); } diff --git a/contrib/tools/python3/src/Modules/_sqlite/cache.c b/contrib/tools/python3/src/Modules/_sqlite/cache.c index 758fc022f7..fd4e619f6a 100644 --- a/contrib/tools/python3/src/Modules/_sqlite/cache.c +++ b/contrib/tools/python3/src/Modules/_sqlite/cache.c @@ -25,20 +25,18 @@ #include <limits.h> /* only used internally */ -pysqlite_Node* pysqlite_new_node(PyObject* key, PyObject* data) +static pysqlite_Node * +pysqlite_new_node(PyObject *key, PyObject *data) { pysqlite_Node* node; - node = (pysqlite_Node*) (pysqlite_NodeType.tp_alloc(&pysqlite_NodeType, 0)); + node = (pysqlite_Node*) (pysqlite_NodeType->tp_alloc(pysqlite_NodeType, 0)); if (!node) { return NULL; } - Py_INCREF(key); - node->key = key; - - Py_INCREF(data); - node->data = data; + node->key = Py_NewRef(key); + node->data = Py_NewRef(data); node->prev = NULL; node->next = NULL; @@ -46,15 +44,35 @@ pysqlite_Node* pysqlite_new_node(PyObject* key, PyObject* data) return node; } -void pysqlite_node_dealloc(pysqlite_Node* self) +static int +node_traverse(pysqlite_Node *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + Py_VISIT(self->key); + Py_VISIT(self->data); + return 0; +} + +static int +node_clear(pysqlite_Node *self) { - Py_DECREF(self->key); - Py_DECREF(self->data); + Py_CLEAR(self->key); + Py_CLEAR(self->data); + return 0; +} - Py_TYPE(self)->tp_free((PyObject*)self); +static void +pysqlite_node_dealloc(pysqlite_Node *self) +{ + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); + tp->tp_clear((PyObject *)self); + tp->tp_free(self); + Py_DECREF(tp); } -int pysqlite_cache_init(pysqlite_Cache* self, PyObject* args, PyObject* kwargs) +static int +pysqlite_cache_init(pysqlite_Cache *self, PyObject *args, PyObject *kwargs) { PyObject* factory; int size = 10; @@ -78,38 +96,62 @@ int pysqlite_cache_init(pysqlite_Cache* self, PyObject* args, PyObject* kwargs) return -1; } - Py_INCREF(factory); - self->factory = factory; + self->factory = Py_NewRef(factory); self->decref_factory = 1; return 0; } -void pysqlite_cache_dealloc(pysqlite_Cache* self) +static int +cache_traverse(pysqlite_Cache *self, visitproc visit, void *arg) { - pysqlite_Node* node; - pysqlite_Node* delete_node; + Py_VISIT(Py_TYPE(self)); + Py_VISIT(self->mapping); + if (self->decref_factory) { + Py_VISIT(self->factory); + } - if (!self->factory) { - /* constructor failed, just get out of here */ - return; + pysqlite_Node *node = self->first; + while (node) { + Py_VISIT(node); + node = node->next; + } + return 0; +} + +static int +cache_clear(pysqlite_Cache *self) +{ + Py_CLEAR(self->mapping); + if (self->decref_factory) { + Py_CLEAR(self->factory); } /* iterate over all nodes and deallocate them */ - node = self->first; + pysqlite_Node *node = self->first; + self->first = NULL; while (node) { - delete_node = node; + pysqlite_Node *delete_node = node; node = node->next; - Py_DECREF(delete_node); + Py_CLEAR(delete_node); } + return 0; +} - if (self->decref_factory) { - Py_DECREF(self->factory); +static void +pysqlite_cache_dealloc(pysqlite_Cache *self) +{ + if (!self->factory) { + /* constructor failed, just get out of here */ + return; } - Py_DECREF(self->mapping); - Py_TYPE(self)->tp_free((PyObject*)self); + PyObject_GC_UnTrack(self); + PyTypeObject *tp = Py_TYPE(self); + tp->tp_clear((PyObject *)self); + tp->tp_free(self); + Py_DECREF(tp); } PyObject* pysqlite_cache_get(pysqlite_Cache* self, PyObject* key) @@ -213,11 +255,11 @@ PyObject* pysqlite_cache_get(pysqlite_Cache* self, PyObject* key) self->last = node; } - Py_INCREF(node->data); - return node->data; + return Py_NewRef(node->data); } -PyObject* pysqlite_cache_display(pysqlite_Cache* self, PyObject* args) +static PyObject * +pysqlite_cache_display(pysqlite_Cache *self, PyObject *args) { pysqlite_Node* ptr; PyObject* prevkey; @@ -253,6 +295,21 @@ PyObject* pysqlite_cache_display(pysqlite_Cache* self, PyObject* args) Py_RETURN_NONE; } +static PyType_Slot node_slots[] = { + {Py_tp_dealloc, pysqlite_node_dealloc}, + {Py_tp_traverse, node_traverse}, + {Py_tp_clear, node_clear}, + {0, NULL}, +}; + +static PyType_Spec node_spec = { + .name = MODULE_NAME ".Node", + .basicsize = sizeof(pysqlite_Node), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + .slots = node_slots, +}; +PyTypeObject *pysqlite_NodeType = NULL; + static PyMethodDef cache_methods[] = { {"get", (PyCFunction)pysqlite_cache_get, METH_O, PyDoc_STR("Gets an entry from the cache or calls the factory function to produce one.")}, @@ -261,102 +318,34 @@ static PyMethodDef cache_methods[] = { {NULL, NULL} }; -PyTypeObject pysqlite_NodeType = { - PyVarObject_HEAD_INIT(NULL, 0) - MODULE_NAME "Node", /* tp_name */ - sizeof(pysqlite_Node), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)pysqlite_node_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0 /* tp_free */ +static PyType_Slot cache_slots[] = { + {Py_tp_dealloc, pysqlite_cache_dealloc}, + {Py_tp_methods, cache_methods}, + {Py_tp_init, pysqlite_cache_init}, + {Py_tp_traverse, cache_traverse}, + {Py_tp_clear, cache_clear}, + {0, NULL}, }; -PyTypeObject pysqlite_CacheType = { - PyVarObject_HEAD_INIT(NULL, 0) - MODULE_NAME ".Cache", /* tp_name */ - sizeof(pysqlite_Cache), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)pysqlite_cache_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - cache_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)pysqlite_cache_init, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0 /* tp_free */ +static PyType_Spec cache_spec = { + .name = MODULE_NAME ".Cache", + .basicsize = sizeof(pysqlite_Cache), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + .slots = cache_slots, }; +PyTypeObject *pysqlite_CacheType = NULL; -extern int pysqlite_cache_setup_types(void) +int +pysqlite_cache_setup_types(PyObject *mod) { - int rc; - - pysqlite_NodeType.tp_new = PyType_GenericNew; - pysqlite_CacheType.tp_new = PyType_GenericNew; - - rc = PyType_Ready(&pysqlite_NodeType); - if (rc < 0) { - return rc; + pysqlite_NodeType = (PyTypeObject *)PyType_FromModuleAndSpec(mod, &node_spec, NULL); + if (pysqlite_NodeType == NULL) { + return -1; } - rc = PyType_Ready(&pysqlite_CacheType); - return rc; + pysqlite_CacheType = (PyTypeObject *)PyType_FromModuleAndSpec(mod, &cache_spec, NULL); + if (pysqlite_CacheType == NULL) { + return -1; + } + return 0; } diff --git a/contrib/tools/python3/src/Modules/_sqlite/cache.h b/contrib/tools/python3/src/Modules/_sqlite/cache.h index 529010967c..083356f93f 100644 --- a/contrib/tools/python3/src/Modules/_sqlite/cache.h +++ b/contrib/tools/python3/src/Modules/_sqlite/cache.h @@ -23,8 +23,7 @@ #ifndef PYSQLITE_CACHE_H #define PYSQLITE_CACHE_H -#define PY_SSIZE_T_CLEAN -#include "Python.h" +#include "module.h" /* The LRU cache is implemented as a combination of a doubly-linked with a * dictionary. The list items are of type 'Node' and the dictionary has the @@ -59,16 +58,11 @@ typedef struct int decref_factory; } pysqlite_Cache; -extern PyTypeObject pysqlite_NodeType; -extern PyTypeObject pysqlite_CacheType; +extern PyTypeObject *pysqlite_NodeType; +extern PyTypeObject *pysqlite_CacheType; -int pysqlite_node_init(pysqlite_Node* self, PyObject* args, PyObject* kwargs); -void pysqlite_node_dealloc(pysqlite_Node* self); - -int pysqlite_cache_init(pysqlite_Cache* self, PyObject* args, PyObject* kwargs); -void pysqlite_cache_dealloc(pysqlite_Cache* self); PyObject* pysqlite_cache_get(pysqlite_Cache* self, PyObject* args); -int pysqlite_cache_setup_types(void); +int pysqlite_cache_setup_types(PyObject *module); #endif diff --git a/contrib/tools/python3/src/Modules/_sqlite/clinic/connection.c.h b/contrib/tools/python3/src/Modules/_sqlite/clinic/connection.c.h new file mode 100644 index 0000000000..9ddce41e90 --- /dev/null +++ b/contrib/tools/python3/src/Modules/_sqlite/clinic/connection.c.h @@ -0,0 +1,709 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(pysqlite_connection_cursor__doc__, +"cursor($self, /, factory=<unrepresentable>)\n" +"--\n" +"\n" +"Return a cursor for the connection."); + +#define PYSQLITE_CONNECTION_CURSOR_METHODDEF \ + {"cursor", (PyCFunction)(void(*)(void))pysqlite_connection_cursor, METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_cursor__doc__}, + +static PyObject * +pysqlite_connection_cursor_impl(pysqlite_Connection *self, PyObject *factory); + +static PyObject * +pysqlite_connection_cursor(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"factory", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "cursor", 0}; + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + PyObject *factory = NULL; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + factory = args[0]; +skip_optional_pos: + return_value = pysqlite_connection_cursor_impl(self, factory); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_connection_close__doc__, +"close($self, /)\n" +"--\n" +"\n" +"Closes the connection."); + +#define PYSQLITE_CONNECTION_CLOSE_METHODDEF \ + {"close", (PyCFunction)pysqlite_connection_close, METH_NOARGS, pysqlite_connection_close__doc__}, + +static PyObject * +pysqlite_connection_close_impl(pysqlite_Connection *self); + +static PyObject * +pysqlite_connection_close(pysqlite_Connection *self, PyObject *Py_UNUSED(ignored)) +{ + return pysqlite_connection_close_impl(self); +} + +PyDoc_STRVAR(pysqlite_connection_commit__doc__, +"commit($self, /)\n" +"--\n" +"\n" +"Commit the current transaction."); + +#define PYSQLITE_CONNECTION_COMMIT_METHODDEF \ + {"commit", (PyCFunction)pysqlite_connection_commit, METH_NOARGS, pysqlite_connection_commit__doc__}, + +static PyObject * +pysqlite_connection_commit_impl(pysqlite_Connection *self); + +static PyObject * +pysqlite_connection_commit(pysqlite_Connection *self, PyObject *Py_UNUSED(ignored)) +{ + return pysqlite_connection_commit_impl(self); +} + +PyDoc_STRVAR(pysqlite_connection_rollback__doc__, +"rollback($self, /)\n" +"--\n" +"\n" +"Roll back the current transaction."); + +#define PYSQLITE_CONNECTION_ROLLBACK_METHODDEF \ + {"rollback", (PyCFunction)pysqlite_connection_rollback, METH_NOARGS, pysqlite_connection_rollback__doc__}, + +static PyObject * +pysqlite_connection_rollback_impl(pysqlite_Connection *self); + +static PyObject * +pysqlite_connection_rollback(pysqlite_Connection *self, PyObject *Py_UNUSED(ignored)) +{ + return pysqlite_connection_rollback_impl(self); +} + +PyDoc_STRVAR(pysqlite_connection_create_function__doc__, +"create_function($self, /, name, narg, func, *, deterministic=False)\n" +"--\n" +"\n" +"Creates a new function."); + +#define PYSQLITE_CONNECTION_CREATE_FUNCTION_METHODDEF \ + {"create_function", (PyCFunction)(void(*)(void))pysqlite_connection_create_function, METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_create_function__doc__}, + +static PyObject * +pysqlite_connection_create_function_impl(pysqlite_Connection *self, + const char *name, int narg, + PyObject *func, int deterministic); + +static PyObject * +pysqlite_connection_create_function(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"name", "narg", "func", "deterministic", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "create_function", 0}; + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; + const char *name; + int narg; + PyObject *func; + int deterministic = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("create_function", "argument 'name'", "str", args[0]); + goto exit; + } + Py_ssize_t name_length; + name = PyUnicode_AsUTF8AndSize(args[0], &name_length); + if (name == NULL) { + goto exit; + } + if (strlen(name) != (size_t)name_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + narg = _PyLong_AsInt(args[1]); + if (narg == -1 && PyErr_Occurred()) { + goto exit; + } + func = args[2]; + if (!noptargs) { + goto skip_optional_kwonly; + } + deterministic = PyObject_IsTrue(args[3]); + if (deterministic < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = pysqlite_connection_create_function_impl(self, name, narg, func, deterministic); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_connection_create_aggregate__doc__, +"create_aggregate($self, /, name, n_arg, aggregate_class)\n" +"--\n" +"\n" +"Creates a new aggregate."); + +#define PYSQLITE_CONNECTION_CREATE_AGGREGATE_METHODDEF \ + {"create_aggregate", (PyCFunction)(void(*)(void))pysqlite_connection_create_aggregate, METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_create_aggregate__doc__}, + +static PyObject * +pysqlite_connection_create_aggregate_impl(pysqlite_Connection *self, + const char *name, int n_arg, + PyObject *aggregate_class); + +static PyObject * +pysqlite_connection_create_aggregate(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"name", "n_arg", "aggregate_class", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "create_aggregate", 0}; + PyObject *argsbuf[3]; + const char *name; + int n_arg; + PyObject *aggregate_class; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); + if (!args) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("create_aggregate", "argument 'name'", "str", args[0]); + goto exit; + } + Py_ssize_t name_length; + name = PyUnicode_AsUTF8AndSize(args[0], &name_length); + if (name == NULL) { + goto exit; + } + if (strlen(name) != (size_t)name_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + n_arg = _PyLong_AsInt(args[1]); + if (n_arg == -1 && PyErr_Occurred()) { + goto exit; + } + aggregate_class = args[2]; + return_value = pysqlite_connection_create_aggregate_impl(self, name, n_arg, aggregate_class); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_connection_set_authorizer__doc__, +"set_authorizer($self, /, authorizer_callback)\n" +"--\n" +"\n" +"Sets authorizer callback."); + +#define PYSQLITE_CONNECTION_SET_AUTHORIZER_METHODDEF \ + {"set_authorizer", (PyCFunction)(void(*)(void))pysqlite_connection_set_authorizer, METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_set_authorizer__doc__}, + +static PyObject * +pysqlite_connection_set_authorizer_impl(pysqlite_Connection *self, + PyObject *authorizer_cb); + +static PyObject * +pysqlite_connection_set_authorizer(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"authorizer_callback", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "set_authorizer", 0}; + PyObject *argsbuf[1]; + PyObject *authorizer_cb; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + authorizer_cb = args[0]; + return_value = pysqlite_connection_set_authorizer_impl(self, authorizer_cb); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_connection_set_progress_handler__doc__, +"set_progress_handler($self, /, progress_handler, n)\n" +"--\n" +"\n" +"Sets progress handler callback."); + +#define PYSQLITE_CONNECTION_SET_PROGRESS_HANDLER_METHODDEF \ + {"set_progress_handler", (PyCFunction)(void(*)(void))pysqlite_connection_set_progress_handler, METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_set_progress_handler__doc__}, + +static PyObject * +pysqlite_connection_set_progress_handler_impl(pysqlite_Connection *self, + PyObject *progress_handler, + int n); + +static PyObject * +pysqlite_connection_set_progress_handler(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"progress_handler", "n", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "set_progress_handler", 0}; + PyObject *argsbuf[2]; + PyObject *progress_handler; + int n; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + progress_handler = args[0]; + n = _PyLong_AsInt(args[1]); + if (n == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = pysqlite_connection_set_progress_handler_impl(self, progress_handler, n); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_connection_set_trace_callback__doc__, +"set_trace_callback($self, /, trace_callback)\n" +"--\n" +"\n" +"Sets a trace callback called for each SQL statement (passed as unicode)."); + +#define PYSQLITE_CONNECTION_SET_TRACE_CALLBACK_METHODDEF \ + {"set_trace_callback", (PyCFunction)(void(*)(void))pysqlite_connection_set_trace_callback, METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_set_trace_callback__doc__}, + +static PyObject * +pysqlite_connection_set_trace_callback_impl(pysqlite_Connection *self, + PyObject *trace_callback); + +static PyObject * +pysqlite_connection_set_trace_callback(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"trace_callback", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "set_trace_callback", 0}; + PyObject *argsbuf[1]; + PyObject *trace_callback; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + trace_callback = args[0]; + return_value = pysqlite_connection_set_trace_callback_impl(self, trace_callback); + +exit: + return return_value; +} + +#if !defined(SQLITE_OMIT_LOAD_EXTENSION) + +PyDoc_STRVAR(pysqlite_connection_enable_load_extension__doc__, +"enable_load_extension($self, enable, /)\n" +"--\n" +"\n" +"Enable dynamic loading of SQLite extension modules."); + +#define PYSQLITE_CONNECTION_ENABLE_LOAD_EXTENSION_METHODDEF \ + {"enable_load_extension", (PyCFunction)pysqlite_connection_enable_load_extension, METH_O, pysqlite_connection_enable_load_extension__doc__}, + +static PyObject * +pysqlite_connection_enable_load_extension_impl(pysqlite_Connection *self, + int onoff); + +static PyObject * +pysqlite_connection_enable_load_extension(pysqlite_Connection *self, PyObject *arg) +{ + PyObject *return_value = NULL; + int onoff; + + onoff = _PyLong_AsInt(arg); + if (onoff == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = pysqlite_connection_enable_load_extension_impl(self, onoff); + +exit: + return return_value; +} + +#endif /* !defined(SQLITE_OMIT_LOAD_EXTENSION) */ + +#if !defined(SQLITE_OMIT_LOAD_EXTENSION) + +PyDoc_STRVAR(pysqlite_connection_load_extension__doc__, +"load_extension($self, name, /)\n" +"--\n" +"\n" +"Load SQLite extension module."); + +#define PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF \ + {"load_extension", (PyCFunction)pysqlite_connection_load_extension, METH_O, pysqlite_connection_load_extension__doc__}, + +static PyObject * +pysqlite_connection_load_extension_impl(pysqlite_Connection *self, + const char *extension_name); + +static PyObject * +pysqlite_connection_load_extension(pysqlite_Connection *self, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *extension_name; + + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("load_extension", "argument", "str", arg); + goto exit; + } + Py_ssize_t extension_name_length; + extension_name = PyUnicode_AsUTF8AndSize(arg, &extension_name_length); + if (extension_name == NULL) { + goto exit; + } + if (strlen(extension_name) != (size_t)extension_name_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + return_value = pysqlite_connection_load_extension_impl(self, extension_name); + +exit: + return return_value; +} + +#endif /* !defined(SQLITE_OMIT_LOAD_EXTENSION) */ + +PyDoc_STRVAR(pysqlite_connection_execute__doc__, +"execute($self, sql, parameters=<unrepresentable>, /)\n" +"--\n" +"\n" +"Executes an SQL statement."); + +#define PYSQLITE_CONNECTION_EXECUTE_METHODDEF \ + {"execute", (PyCFunction)(void(*)(void))pysqlite_connection_execute, METH_FASTCALL, pysqlite_connection_execute__doc__}, + +static PyObject * +pysqlite_connection_execute_impl(pysqlite_Connection *self, PyObject *sql, + PyObject *parameters); + +static PyObject * +pysqlite_connection_execute(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *sql; + PyObject *parameters = NULL; + + if (!_PyArg_CheckPositional("execute", nargs, 1, 2)) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("execute", "argument 1", "str", args[0]); + goto exit; + } + if (PyUnicode_READY(args[0]) == -1) { + goto exit; + } + sql = args[0]; + if (nargs < 2) { + goto skip_optional; + } + parameters = args[1]; +skip_optional: + return_value = pysqlite_connection_execute_impl(self, sql, parameters); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_connection_executemany__doc__, +"executemany($self, sql, parameters, /)\n" +"--\n" +"\n" +"Repeatedly executes an SQL statement."); + +#define PYSQLITE_CONNECTION_EXECUTEMANY_METHODDEF \ + {"executemany", (PyCFunction)(void(*)(void))pysqlite_connection_executemany, METH_FASTCALL, pysqlite_connection_executemany__doc__}, + +static PyObject * +pysqlite_connection_executemany_impl(pysqlite_Connection *self, + PyObject *sql, PyObject *parameters); + +static PyObject * +pysqlite_connection_executemany(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *sql; + PyObject *parameters; + + if (!_PyArg_CheckPositional("executemany", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("executemany", "argument 1", "str", args[0]); + goto exit; + } + if (PyUnicode_READY(args[0]) == -1) { + goto exit; + } + sql = args[0]; + parameters = args[1]; + return_value = pysqlite_connection_executemany_impl(self, sql, parameters); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_connection_executescript__doc__, +"executescript($self, sql_script, /)\n" +"--\n" +"\n" +"Executes multiple SQL statements at once."); + +#define PYSQLITE_CONNECTION_EXECUTESCRIPT_METHODDEF \ + {"executescript", (PyCFunction)pysqlite_connection_executescript, METH_O, pysqlite_connection_executescript__doc__}, + +PyDoc_STRVAR(pysqlite_connection_interrupt__doc__, +"interrupt($self, /)\n" +"--\n" +"\n" +"Abort any pending database operation."); + +#define PYSQLITE_CONNECTION_INTERRUPT_METHODDEF \ + {"interrupt", (PyCFunction)pysqlite_connection_interrupt, METH_NOARGS, pysqlite_connection_interrupt__doc__}, + +static PyObject * +pysqlite_connection_interrupt_impl(pysqlite_Connection *self); + +static PyObject * +pysqlite_connection_interrupt(pysqlite_Connection *self, PyObject *Py_UNUSED(ignored)) +{ + return pysqlite_connection_interrupt_impl(self); +} + +PyDoc_STRVAR(pysqlite_connection_iterdump__doc__, +"iterdump($self, /)\n" +"--\n" +"\n" +"Returns iterator to the dump of the database in an SQL text format."); + +#define PYSQLITE_CONNECTION_ITERDUMP_METHODDEF \ + {"iterdump", (PyCFunction)pysqlite_connection_iterdump, METH_NOARGS, pysqlite_connection_iterdump__doc__}, + +static PyObject * +pysqlite_connection_iterdump_impl(pysqlite_Connection *self); + +static PyObject * +pysqlite_connection_iterdump(pysqlite_Connection *self, PyObject *Py_UNUSED(ignored)) +{ + return pysqlite_connection_iterdump_impl(self); +} + +PyDoc_STRVAR(pysqlite_connection_backup__doc__, +"backup($self, /, target, *, pages=-1, progress=None, name=\'main\',\n" +" sleep=0.25)\n" +"--\n" +"\n" +"Makes a backup of the database."); + +#define PYSQLITE_CONNECTION_BACKUP_METHODDEF \ + {"backup", (PyCFunction)(void(*)(void))pysqlite_connection_backup, METH_FASTCALL|METH_KEYWORDS, pysqlite_connection_backup__doc__}, + +static PyObject * +pysqlite_connection_backup_impl(pysqlite_Connection *self, + pysqlite_Connection *target, int pages, + PyObject *progress, const char *name, + double sleep); + +static PyObject * +pysqlite_connection_backup(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"target", "pages", "progress", "name", "sleep", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "backup", 0}; + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + pysqlite_Connection *target; + int pages = -1; + PyObject *progress = Py_None; + const char *name = "main"; + double sleep = 0.25; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!PyObject_TypeCheck(args[0], pysqlite_ConnectionType)) { + _PyArg_BadArgument("backup", "argument 'target'", (pysqlite_ConnectionType)->tp_name, args[0]); + goto exit; + } + target = (pysqlite_Connection *)args[0]; + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[1]) { + pages = _PyLong_AsInt(args[1]); + if (pages == -1 && PyErr_Occurred()) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[2]) { + progress = args[2]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (args[3]) { + if (!PyUnicode_Check(args[3])) { + _PyArg_BadArgument("backup", "argument 'name'", "str", args[3]); + goto exit; + } + Py_ssize_t name_length; + name = PyUnicode_AsUTF8AndSize(args[3], &name_length); + if (name == NULL) { + goto exit; + } + if (strlen(name) != (size_t)name_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (PyFloat_CheckExact(args[4])) { + sleep = PyFloat_AS_DOUBLE(args[4]); + } + else + { + sleep = PyFloat_AsDouble(args[4]); + if (sleep == -1.0 && PyErr_Occurred()) { + goto exit; + } + } +skip_optional_kwonly: + return_value = pysqlite_connection_backup_impl(self, target, pages, progress, name, sleep); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_connection_create_collation__doc__, +"create_collation($self, name, callback, /)\n" +"--\n" +"\n" +"Creates a collation function."); + +#define PYSQLITE_CONNECTION_CREATE_COLLATION_METHODDEF \ + {"create_collation", (PyCFunction)(void(*)(void))pysqlite_connection_create_collation, METH_FASTCALL, pysqlite_connection_create_collation__doc__}, + +static PyObject * +pysqlite_connection_create_collation_impl(pysqlite_Connection *self, + PyObject *name, PyObject *callable); + +static PyObject * +pysqlite_connection_create_collation(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *name; + PyObject *callable; + + if (!_PyArg_CheckPositional("create_collation", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("create_collation", "argument 1", "str", args[0]); + goto exit; + } + if (PyUnicode_READY(args[0]) == -1) { + goto exit; + } + name = args[0]; + callable = args[1]; + return_value = pysqlite_connection_create_collation_impl(self, name, callable); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_connection_enter__doc__, +"__enter__($self, /)\n" +"--\n" +"\n" +"Called when the connection is used as a context manager.\n" +"\n" +"Returns itself as a convenience to the caller."); + +#define PYSQLITE_CONNECTION_ENTER_METHODDEF \ + {"__enter__", (PyCFunction)pysqlite_connection_enter, METH_NOARGS, pysqlite_connection_enter__doc__}, + +static PyObject * +pysqlite_connection_enter_impl(pysqlite_Connection *self); + +static PyObject * +pysqlite_connection_enter(pysqlite_Connection *self, PyObject *Py_UNUSED(ignored)) +{ + return pysqlite_connection_enter_impl(self); +} + +PyDoc_STRVAR(pysqlite_connection_exit__doc__, +"__exit__($self, type, value, traceback, /)\n" +"--\n" +"\n" +"Called when the connection is used as a context manager.\n" +"\n" +"If there was any exception, a rollback takes place; otherwise we commit."); + +#define PYSQLITE_CONNECTION_EXIT_METHODDEF \ + {"__exit__", (PyCFunction)(void(*)(void))pysqlite_connection_exit, METH_FASTCALL, pysqlite_connection_exit__doc__}, + +static PyObject * +pysqlite_connection_exit_impl(pysqlite_Connection *self, PyObject *exc_type, + PyObject *exc_value, PyObject *exc_tb); + +static PyObject * +pysqlite_connection_exit(pysqlite_Connection *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *exc_type; + PyObject *exc_value; + PyObject *exc_tb; + + if (!_PyArg_CheckPositional("__exit__", nargs, 3, 3)) { + goto exit; + } + exc_type = args[0]; + exc_value = args[1]; + exc_tb = args[2]; + return_value = pysqlite_connection_exit_impl(self, exc_type, exc_value, exc_tb); + +exit: + return return_value; +} + +#ifndef PYSQLITE_CONNECTION_ENABLE_LOAD_EXTENSION_METHODDEF + #define PYSQLITE_CONNECTION_ENABLE_LOAD_EXTENSION_METHODDEF +#endif /* !defined(PYSQLITE_CONNECTION_ENABLE_LOAD_EXTENSION_METHODDEF) */ + +#ifndef PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF + #define PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF +#endif /* !defined(PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF) */ +/*[clinic end generated code: output=2f3f3406ba6b4d2e input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/_sqlite/clinic/cursor.c.h b/contrib/tools/python3/src/Modules/_sqlite/clinic/cursor.c.h new file mode 100644 index 0000000000..c6e35a23d6 --- /dev/null +++ b/contrib/tools/python3/src/Modules/_sqlite/clinic/cursor.c.h @@ -0,0 +1,262 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +static int +pysqlite_cursor_init_impl(pysqlite_Cursor *self, + pysqlite_Connection *connection); + +static int +pysqlite_cursor_init(PyObject *self, PyObject *args, PyObject *kwargs) +{ + int return_value = -1; + pysqlite_Connection *connection; + + if (Py_IS_TYPE(self, pysqlite_CursorType) && + !_PyArg_NoKeywords("Cursor", kwargs)) { + goto exit; + } + if (!_PyArg_CheckPositional("Cursor", PyTuple_GET_SIZE(args), 1, 1)) { + goto exit; + } + if (!PyObject_TypeCheck(PyTuple_GET_ITEM(args, 0), pysqlite_ConnectionType)) { + _PyArg_BadArgument("Cursor", "argument 1", (pysqlite_ConnectionType)->tp_name, PyTuple_GET_ITEM(args, 0)); + goto exit; + } + connection = (pysqlite_Connection *)PyTuple_GET_ITEM(args, 0); + return_value = pysqlite_cursor_init_impl((pysqlite_Cursor *)self, connection); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_cursor_execute__doc__, +"execute($self, sql, parameters=(), /)\n" +"--\n" +"\n" +"Executes an SQL statement."); + +#define PYSQLITE_CURSOR_EXECUTE_METHODDEF \ + {"execute", (PyCFunction)(void(*)(void))pysqlite_cursor_execute, METH_FASTCALL, pysqlite_cursor_execute__doc__}, + +static PyObject * +pysqlite_cursor_execute_impl(pysqlite_Cursor *self, PyObject *sql, + PyObject *parameters); + +static PyObject * +pysqlite_cursor_execute(pysqlite_Cursor *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *sql; + PyObject *parameters = NULL; + + if (!_PyArg_CheckPositional("execute", nargs, 1, 2)) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("execute", "argument 1", "str", args[0]); + goto exit; + } + if (PyUnicode_READY(args[0]) == -1) { + goto exit; + } + sql = args[0]; + if (nargs < 2) { + goto skip_optional; + } + parameters = args[1]; +skip_optional: + return_value = pysqlite_cursor_execute_impl(self, sql, parameters); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_cursor_executemany__doc__, +"executemany($self, sql, seq_of_parameters, /)\n" +"--\n" +"\n" +"Repeatedly executes an SQL statement."); + +#define PYSQLITE_CURSOR_EXECUTEMANY_METHODDEF \ + {"executemany", (PyCFunction)(void(*)(void))pysqlite_cursor_executemany, METH_FASTCALL, pysqlite_cursor_executemany__doc__}, + +static PyObject * +pysqlite_cursor_executemany_impl(pysqlite_Cursor *self, PyObject *sql, + PyObject *seq_of_parameters); + +static PyObject * +pysqlite_cursor_executemany(pysqlite_Cursor *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *sql; + PyObject *seq_of_parameters; + + if (!_PyArg_CheckPositional("executemany", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("executemany", "argument 1", "str", args[0]); + goto exit; + } + if (PyUnicode_READY(args[0]) == -1) { + goto exit; + } + sql = args[0]; + seq_of_parameters = args[1]; + return_value = pysqlite_cursor_executemany_impl(self, sql, seq_of_parameters); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_cursor_executescript__doc__, +"executescript($self, sql_script, /)\n" +"--\n" +"\n" +"Executes multiple SQL statements at once."); + +#define PYSQLITE_CURSOR_EXECUTESCRIPT_METHODDEF \ + {"executescript", (PyCFunction)pysqlite_cursor_executescript, METH_O, pysqlite_cursor_executescript__doc__}, + +PyDoc_STRVAR(pysqlite_cursor_fetchone__doc__, +"fetchone($self, /)\n" +"--\n" +"\n" +"Fetches one row from the resultset."); + +#define PYSQLITE_CURSOR_FETCHONE_METHODDEF \ + {"fetchone", (PyCFunction)pysqlite_cursor_fetchone, METH_NOARGS, pysqlite_cursor_fetchone__doc__}, + +static PyObject * +pysqlite_cursor_fetchone_impl(pysqlite_Cursor *self); + +static PyObject * +pysqlite_cursor_fetchone(pysqlite_Cursor *self, PyObject *Py_UNUSED(ignored)) +{ + return pysqlite_cursor_fetchone_impl(self); +} + +PyDoc_STRVAR(pysqlite_cursor_fetchmany__doc__, +"fetchmany($self, /, size=1)\n" +"--\n" +"\n" +"Fetches several rows from the resultset.\n" +"\n" +" size\n" +" The default value is set by the Cursor.arraysize attribute."); + +#define PYSQLITE_CURSOR_FETCHMANY_METHODDEF \ + {"fetchmany", (PyCFunction)(void(*)(void))pysqlite_cursor_fetchmany, METH_FASTCALL|METH_KEYWORDS, pysqlite_cursor_fetchmany__doc__}, + +static PyObject * +pysqlite_cursor_fetchmany_impl(pysqlite_Cursor *self, int maxrows); + +static PyObject * +pysqlite_cursor_fetchmany(pysqlite_Cursor *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"size", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "fetchmany", 0}; + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + int maxrows = self->arraysize; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + maxrows = _PyLong_AsInt(args[0]); + if (maxrows == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_pos: + return_value = pysqlite_cursor_fetchmany_impl(self, maxrows); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_cursor_fetchall__doc__, +"fetchall($self, /)\n" +"--\n" +"\n" +"Fetches all rows from the resultset."); + +#define PYSQLITE_CURSOR_FETCHALL_METHODDEF \ + {"fetchall", (PyCFunction)pysqlite_cursor_fetchall, METH_NOARGS, pysqlite_cursor_fetchall__doc__}, + +static PyObject * +pysqlite_cursor_fetchall_impl(pysqlite_Cursor *self); + +static PyObject * +pysqlite_cursor_fetchall(pysqlite_Cursor *self, PyObject *Py_UNUSED(ignored)) +{ + return pysqlite_cursor_fetchall_impl(self); +} + +PyDoc_STRVAR(pysqlite_cursor_setinputsizes__doc__, +"setinputsizes($self, sizes, /)\n" +"--\n" +"\n" +"Required by DB-API. Does nothing in sqlite3."); + +#define PYSQLITE_CURSOR_SETINPUTSIZES_METHODDEF \ + {"setinputsizes", (PyCFunction)pysqlite_cursor_setinputsizes, METH_O, pysqlite_cursor_setinputsizes__doc__}, + +PyDoc_STRVAR(pysqlite_cursor_setoutputsize__doc__, +"setoutputsize($self, size, column=None, /)\n" +"--\n" +"\n" +"Required by DB-API. Does nothing in sqlite3."); + +#define PYSQLITE_CURSOR_SETOUTPUTSIZE_METHODDEF \ + {"setoutputsize", (PyCFunction)(void(*)(void))pysqlite_cursor_setoutputsize, METH_FASTCALL, pysqlite_cursor_setoutputsize__doc__}, + +static PyObject * +pysqlite_cursor_setoutputsize_impl(pysqlite_Cursor *self, PyObject *size, + PyObject *column); + +static PyObject * +pysqlite_cursor_setoutputsize(pysqlite_Cursor *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *size; + PyObject *column = Py_None; + + if (!_PyArg_CheckPositional("setoutputsize", nargs, 1, 2)) { + goto exit; + } + size = args[0]; + if (nargs < 2) { + goto skip_optional; + } + column = args[1]; +skip_optional: + return_value = pysqlite_cursor_setoutputsize_impl(self, size, column); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_cursor_close__doc__, +"close($self, /)\n" +"--\n" +"\n" +"Closes the cursor."); + +#define PYSQLITE_CURSOR_CLOSE_METHODDEF \ + {"close", (PyCFunction)pysqlite_cursor_close, METH_NOARGS, pysqlite_cursor_close__doc__}, + +static PyObject * +pysqlite_cursor_close_impl(pysqlite_Cursor *self); + +static PyObject * +pysqlite_cursor_close(pysqlite_Cursor *self, PyObject *Py_UNUSED(ignored)) +{ + return pysqlite_cursor_close_impl(self); +} +/*[clinic end generated code: output=9879e3a5d4ee3847 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/_sqlite/clinic/module.c.h b/contrib/tools/python3/src/Modules/_sqlite/clinic/module.c.h new file mode 100644 index 0000000000..2118cb7c42 --- /dev/null +++ b/contrib/tools/python3/src/Modules/_sqlite/clinic/module.c.h @@ -0,0 +1,225 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(pysqlite_complete_statement__doc__, +"complete_statement($module, /, statement)\n" +"--\n" +"\n" +"Checks if a string contains a complete SQL statement."); + +#define PYSQLITE_COMPLETE_STATEMENT_METHODDEF \ + {"complete_statement", (PyCFunction)(void(*)(void))pysqlite_complete_statement, METH_FASTCALL|METH_KEYWORDS, pysqlite_complete_statement__doc__}, + +static PyObject * +pysqlite_complete_statement_impl(PyObject *module, const char *statement); + +static PyObject * +pysqlite_complete_statement(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"statement", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "complete_statement", 0}; + PyObject *argsbuf[1]; + const char *statement; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("complete_statement", "argument 'statement'", "str", args[0]); + goto exit; + } + Py_ssize_t statement_length; + statement = PyUnicode_AsUTF8AndSize(args[0], &statement_length); + if (statement == NULL) { + goto exit; + } + if (strlen(statement) != (size_t)statement_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + return_value = pysqlite_complete_statement_impl(module, statement); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_enable_shared_cache__doc__, +"enable_shared_cache($module, /, do_enable)\n" +"--\n" +"\n" +"Enable or disable shared cache mode for the calling thread.\n" +"\n" +"This method is deprecated and will be removed in Python 3.12.\n" +"Shared cache is strongly discouraged by the SQLite 3 documentation.\n" +"If shared cache must be used, open the database in URI mode using\n" +"the cache=shared query parameter."); + +#define PYSQLITE_ENABLE_SHARED_CACHE_METHODDEF \ + {"enable_shared_cache", (PyCFunction)(void(*)(void))pysqlite_enable_shared_cache, METH_FASTCALL|METH_KEYWORDS, pysqlite_enable_shared_cache__doc__}, + +static PyObject * +pysqlite_enable_shared_cache_impl(PyObject *module, int do_enable); + +static PyObject * +pysqlite_enable_shared_cache(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"do_enable", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "enable_shared_cache", 0}; + PyObject *argsbuf[1]; + int do_enable; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + do_enable = _PyLong_AsInt(args[0]); + if (do_enable == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = pysqlite_enable_shared_cache_impl(module, do_enable); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_register_adapter__doc__, +"register_adapter($module, type, caster, /)\n" +"--\n" +"\n" +"Registers an adapter with sqlite3\'s adapter registry."); + +#define PYSQLITE_REGISTER_ADAPTER_METHODDEF \ + {"register_adapter", (PyCFunction)(void(*)(void))pysqlite_register_adapter, METH_FASTCALL, pysqlite_register_adapter__doc__}, + +static PyObject * +pysqlite_register_adapter_impl(PyObject *module, PyTypeObject *type, + PyObject *caster); + +static PyObject * +pysqlite_register_adapter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyTypeObject *type; + PyObject *caster; + + if (!_PyArg_CheckPositional("register_adapter", nargs, 2, 2)) { + goto exit; + } + type = (PyTypeObject *)args[0]; + caster = args[1]; + return_value = pysqlite_register_adapter_impl(module, type, caster); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_register_converter__doc__, +"register_converter($module, name, converter, /)\n" +"--\n" +"\n" +"Registers a converter with sqlite3."); + +#define PYSQLITE_REGISTER_CONVERTER_METHODDEF \ + {"register_converter", (PyCFunction)(void(*)(void))pysqlite_register_converter, METH_FASTCALL, pysqlite_register_converter__doc__}, + +static PyObject * +pysqlite_register_converter_impl(PyObject *module, PyObject *orig_name, + PyObject *callable); + +static PyObject * +pysqlite_register_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *orig_name; + PyObject *callable; + + if (!_PyArg_CheckPositional("register_converter", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("register_converter", "argument 1", "str", args[0]); + goto exit; + } + if (PyUnicode_READY(args[0]) == -1) { + goto exit; + } + orig_name = args[0]; + callable = args[1]; + return_value = pysqlite_register_converter_impl(module, orig_name, callable); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_enable_callback_trace__doc__, +"enable_callback_tracebacks($module, enable, /)\n" +"--\n" +"\n" +"Enable or disable callback functions throwing errors to stderr."); + +#define PYSQLITE_ENABLE_CALLBACK_TRACE_METHODDEF \ + {"enable_callback_tracebacks", (PyCFunction)pysqlite_enable_callback_trace, METH_O, pysqlite_enable_callback_trace__doc__}, + +static PyObject * +pysqlite_enable_callback_trace_impl(PyObject *module, int enable); + +static PyObject * +pysqlite_enable_callback_trace(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int enable; + + enable = _PyLong_AsInt(arg); + if (enable == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = pysqlite_enable_callback_trace_impl(module, enable); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_adapt__doc__, +"adapt($module, obj, proto=PrepareProtocolType, alt=<unrepresentable>, /)\n" +"--\n" +"\n" +"Adapt given object to given protocol."); + +#define PYSQLITE_ADAPT_METHODDEF \ + {"adapt", (PyCFunction)(void(*)(void))pysqlite_adapt, METH_FASTCALL, pysqlite_adapt__doc__}, + +static PyObject * +pysqlite_adapt_impl(PyObject *module, PyObject *obj, PyObject *proto, + PyObject *alt); + +static PyObject * +pysqlite_adapt(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *obj; + PyObject *proto = (PyObject*)pysqlite_PrepareProtocolType; + PyObject *alt = NULL; + + if (!_PyArg_CheckPositional("adapt", nargs, 1, 3)) { + goto exit; + } + obj = args[0]; + if (nargs < 2) { + goto skip_optional; + } + proto = args[1]; + if (nargs < 3) { + goto skip_optional; + } + alt = args[2]; +skip_optional: + return_value = pysqlite_adapt_impl(module, obj, proto, alt); + +exit: + return return_value; +} +/*[clinic end generated code: output=6939849a4371122d input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/_sqlite/clinic/row.c.h b/contrib/tools/python3/src/Modules/_sqlite/clinic/row.c.h new file mode 100644 index 0000000000..7ff110940d --- /dev/null +++ b/contrib/tools/python3/src/Modules/_sqlite/clinic/row.c.h @@ -0,0 +1,56 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +static PyObject * +pysqlite_row_new_impl(PyTypeObject *type, pysqlite_Cursor *cursor, + PyObject *data); + +static PyObject * +pysqlite_row_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + pysqlite_Cursor *cursor; + PyObject *data; + + if ((type == pysqlite_RowType) && + !_PyArg_NoKeywords("Row", kwargs)) { + goto exit; + } + if (!_PyArg_CheckPositional("Row", PyTuple_GET_SIZE(args), 2, 2)) { + goto exit; + } + if (!PyObject_TypeCheck(PyTuple_GET_ITEM(args, 0), pysqlite_CursorType)) { + _PyArg_BadArgument("Row", "argument 1", (pysqlite_CursorType)->tp_name, PyTuple_GET_ITEM(args, 0)); + goto exit; + } + cursor = (pysqlite_Cursor *)PyTuple_GET_ITEM(args, 0); + if (!PyTuple_Check(PyTuple_GET_ITEM(args, 1))) { + _PyArg_BadArgument("Row", "argument 2", "tuple", PyTuple_GET_ITEM(args, 1)); + goto exit; + } + data = PyTuple_GET_ITEM(args, 1); + return_value = pysqlite_row_new_impl(type, cursor, data); + +exit: + return return_value; +} + +PyDoc_STRVAR(pysqlite_row_keys__doc__, +"keys($self, /)\n" +"--\n" +"\n" +"Returns the keys of the row."); + +#define PYSQLITE_ROW_KEYS_METHODDEF \ + {"keys", (PyCFunction)pysqlite_row_keys, METH_NOARGS, pysqlite_row_keys__doc__}, + +static PyObject * +pysqlite_row_keys_impl(pysqlite_Row *self); + +static PyObject * +pysqlite_row_keys(pysqlite_Row *self, PyObject *Py_UNUSED(ignored)) +{ + return pysqlite_row_keys_impl(self); +} +/*[clinic end generated code: output=8d29220b9cde035d input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/_sqlite/connection.c b/contrib/tools/python3/src/Modules/_sqlite/connection.c index 67688e8753..c9c10b4139 100644 --- a/contrib/tools/python3/src/Modules/_sqlite/connection.c +++ b/contrib/tools/python3/src/Modules/_sqlite/connection.c @@ -33,15 +33,16 @@ #define ACTION_FINALIZE 1 #define ACTION_RESET 2 -#if SQLITE_VERSION_NUMBER >= 3003008 -#ifndef SQLITE_OMIT_LOAD_EXTENSION -#define HAVE_LOAD_EXTENSION -#endif +#if SQLITE_VERSION_NUMBER >= 3014000 +#define HAVE_TRACE_V2 #endif -#if SQLITE_VERSION_NUMBER >= 3006011 -#define HAVE_BACKUP_API -#endif +#include "clinic/connection.c.h" +/*[clinic input] +module _sqlite3 +class _sqlite3.Connection "pysqlite_Connection *" "pysqlite_ConnectionType" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=aa796073bd8f69db]*/ _Py_IDENTIFIER(cursor); @@ -56,20 +57,9 @@ static const char * const begin_statements[] = { static int pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* isolation_level, void *Py_UNUSED(ignored)); static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self); - -static void _sqlite3_result_error(sqlite3_context* ctx, const char* errmsg, int len) -{ - /* in older SQLite versions, calling sqlite3_result_error in callbacks - * triggers a bug in SQLite that leads either to irritating results or - * segfaults, depending on the SQLite version */ -#if SQLITE_VERSION_NUMBER >= 3003003 - sqlite3_result_error(ctx, errmsg, len); -#else - PyErr_SetString(pysqlite_OperationalError, errmsg); -#endif -} - -int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) +static int +pysqlite_connection_init(pysqlite_Connection *self, PyObject *args, + PyObject *kwargs) { static char *kwlist[] = { "database", "timeout", "detect_types", "isolation_level", @@ -115,21 +105,10 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject Py_INCREF(&PyUnicode_Type); Py_XSETREF(self->text_factory, (PyObject*)&PyUnicode_Type); -#ifdef SQLITE_OPEN_URI Py_BEGIN_ALLOW_THREADS rc = sqlite3_open_v2(database, &self->db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | (uri ? SQLITE_OPEN_URI : 0), NULL); -#else - if (uri) { - PyErr_SetString(pysqlite_NotSupportedError, "URIs not supported"); - return -1; - } - Py_BEGIN_ALLOW_THREADS - /* No need to use sqlite3_open_v2 as sqlite3_open(filename, db) is the - same as sqlite3_open_v2(filename, db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, NULL). */ - rc = sqlite3_open(database, &self->db); -#endif Py_END_ALLOW_THREADS Py_DECREF(database_obj); @@ -158,7 +137,7 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject } Py_DECREF(isolation_level); - self->statement_cache = (pysqlite_Cache*)PyObject_CallFunction((PyObject*)&pysqlite_CacheType, "Oi", self, cached_statements); + self->statement_cache = (pysqlite_Cache*)PyObject_CallFunction((PyObject*)pysqlite_CacheType, "Oi", self, cached_statements); if (PyErr_Occurred()) { return -1; } @@ -185,10 +164,6 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject self->timeout = timeout; (void)sqlite3_busy_timeout(self->db, (int)(timeout*1000)); self->thread_ident = PyThread_get_thread_ident(); - if (!check_same_thread && sqlite3_libversion_number() < 3003001) { - PyErr_SetString(pysqlite_NotSupportedError, "shared connections not available"); - return -1; - } self->check_same_thread = check_same_thread; self->function_pinboard_trace_callback = NULL; @@ -211,13 +186,19 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject self->ProgrammingError = pysqlite_ProgrammingError; self->NotSupportedError = pysqlite_NotSupportedError; + if (PySys_Audit("sqlite3.connect/handle", "O", self) < 0) { + return -1; + } + self->initialized = 1; return 0; } /* action in (ACTION_RESET, ACTION_FINALIZE) */ -void pysqlite_do_all_statements(pysqlite_Connection* self, int action, int reset_cursors) +static void +pysqlite_do_all_statements(pysqlite_Connection *self, int action, + int reset_cursors) { int i; PyObject* weakref; @@ -249,25 +230,53 @@ void pysqlite_do_all_statements(pysqlite_Connection* self, int action, int reset } } -void pysqlite_connection_dealloc(pysqlite_Connection* self) +static int +connection_traverse(pysqlite_Connection *self, visitproc visit, void *arg) { - Py_XDECREF(self->statement_cache); + Py_VISIT(Py_TYPE(self)); + Py_VISIT(self->isolation_level); + Py_VISIT(self->statement_cache); + Py_VISIT(self->statements); + Py_VISIT(self->cursors); + Py_VISIT(self->row_factory); + Py_VISIT(self->text_factory); + Py_VISIT(self->function_pinboard_trace_callback); + Py_VISIT(self->function_pinboard_progress_handler); + Py_VISIT(self->function_pinboard_authorizer_cb); + Py_VISIT(self->collations); + return 0; +} + +static int +connection_clear(pysqlite_Connection *self) +{ + Py_CLEAR(self->isolation_level); + Py_CLEAR(self->statement_cache); + Py_CLEAR(self->statements); + Py_CLEAR(self->cursors); + Py_CLEAR(self->row_factory); + Py_CLEAR(self->text_factory); + Py_CLEAR(self->function_pinboard_trace_callback); + Py_CLEAR(self->function_pinboard_progress_handler); + Py_CLEAR(self->function_pinboard_authorizer_cb); + Py_CLEAR(self->collations); + return 0; +} + +static void +connection_dealloc(pysqlite_Connection *self) +{ + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); + tp->tp_clear((PyObject *)self); /* Clean up if user has not called .close() explicitly. */ if (self->db) { - SQLITE3_CLOSE(self->db); - } - - Py_XDECREF(self->isolation_level); - Py_XDECREF(self->function_pinboard_trace_callback); - Py_XDECREF(self->function_pinboard_progress_handler); - Py_XDECREF(self->function_pinboard_authorizer_cb); - Py_XDECREF(self->row_factory); - Py_XDECREF(self->text_factory); - Py_XDECREF(self->collations); - Py_XDECREF(self->statements); - Py_XDECREF(self->cursors); - Py_TYPE(self)->tp_free((PyObject*)self); + sqlite3_close_v2(self->db); + } + + tp->tp_free(self); + Py_DECREF(tp); } /* @@ -296,29 +305,32 @@ error: return 0; } -PyObject* pysqlite_connection_cursor(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) +/*[clinic input] +_sqlite3.Connection.cursor as pysqlite_connection_cursor + + factory: object = NULL + +Return a cursor for the connection. +[clinic start generated code]*/ + +static PyObject * +pysqlite_connection_cursor_impl(pysqlite_Connection *self, PyObject *factory) +/*[clinic end generated code: output=562432a9e6af2aa1 input=4127345aa091b650]*/ { - static char *kwlist[] = {"factory", NULL}; - PyObject* factory = NULL; PyObject* cursor; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, - &factory)) { - return NULL; - } - if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } if (factory == NULL) { - factory = (PyObject*)&pysqlite_CursorType; + factory = (PyObject*)pysqlite_CursorType; } cursor = PyObject_CallOneArg(factory, (PyObject *)self); if (cursor == NULL) return NULL; - if (!PyObject_TypeCheck(cursor, &pysqlite_CursorType)) { + if (!PyObject_TypeCheck(cursor, pysqlite_CursorType)) { PyErr_Format(PyExc_TypeError, "factory must return a cursor, not %.100s", Py_TYPE(cursor)->tp_name); @@ -336,7 +348,15 @@ PyObject* pysqlite_connection_cursor(pysqlite_Connection* self, PyObject* args, return cursor; } -PyObject* pysqlite_connection_close(pysqlite_Connection* self, PyObject* args) +/*[clinic input] +_sqlite3.Connection.close as pysqlite_connection_close + +Closes the connection. +[clinic start generated code]*/ + +static PyObject * +pysqlite_connection_close_impl(pysqlite_Connection *self) +/*[clinic end generated code: output=a546a0da212c9b97 input=3d58064bbffaa3d3]*/ { int rc; @@ -353,7 +373,7 @@ PyObject* pysqlite_connection_close(pysqlite_Connection* self, PyObject* args) pysqlite_do_all_statements(self, ACTION_FINALIZE, 1); if (self->db) { - rc = SQLITE3_CLOSE(self->db); + rc = sqlite3_close_v2(self->db); if (rc != SQLITE_OK) { _pysqlite_seterror(self->db, NULL); @@ -389,11 +409,11 @@ int pysqlite_check_connection(pysqlite_Connection* con) PyObject* _pysqlite_connection_begin(pysqlite_Connection* self) { int rc; - const char* tail; sqlite3_stmt* statement; Py_BEGIN_ALLOW_THREADS - rc = sqlite3_prepare_v2(self->db, self->begin_statement, -1, &statement, &tail); + rc = sqlite3_prepare_v2(self->db, self->begin_statement, -1, &statement, + NULL); Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { @@ -422,10 +442,17 @@ error: } } -PyObject* pysqlite_connection_commit(pysqlite_Connection* self, PyObject* args) +/*[clinic input] +_sqlite3.Connection.commit as pysqlite_connection_commit + +Commit the current transaction. +[clinic start generated code]*/ + +static PyObject * +pysqlite_connection_commit_impl(pysqlite_Connection *self) +/*[clinic end generated code: output=3da45579e89407f2 input=39c12c04dda276a8]*/ { int rc; - const char* tail; sqlite3_stmt* statement; if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { @@ -435,7 +462,7 @@ PyObject* pysqlite_connection_commit(pysqlite_Connection* self, PyObject* args) if (!sqlite3_get_autocommit(self->db)) { Py_BEGIN_ALLOW_THREADS - rc = sqlite3_prepare_v2(self->db, "COMMIT", -1, &statement, &tail); + rc = sqlite3_prepare_v2(self->db, "COMMIT", -1, &statement, NULL); Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { _pysqlite_seterror(self->db, NULL); @@ -464,10 +491,17 @@ error: } } -PyObject* pysqlite_connection_rollback(pysqlite_Connection* self, PyObject* args) +/*[clinic input] +_sqlite3.Connection.rollback as pysqlite_connection_rollback + +Roll back the current transaction. +[clinic start generated code]*/ + +static PyObject * +pysqlite_connection_rollback_impl(pysqlite_Connection *self) +/*[clinic end generated code: output=b66fa0d43e7ef305 input=12d4e8d068942830]*/ { int rc; - const char* tail; sqlite3_stmt* statement; if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { @@ -478,7 +512,7 @@ PyObject* pysqlite_connection_rollback(pysqlite_Connection* self, PyObject* args pysqlite_do_all_statements(self, ACTION_RESET, 1); Py_BEGIN_ALLOW_THREADS - rc = sqlite3_prepare_v2(self->db, "ROLLBACK", -1, &statement, &tail); + rc = sqlite3_prepare_v2(self->db, "ROLLBACK", -1, &statement, NULL); Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { _pysqlite_seterror(self->db, NULL); @@ -556,13 +590,14 @@ _pysqlite_set_result(sqlite3_context* context, PyObject* py_val) return 0; } -PyObject* _pysqlite_build_py_params(sqlite3_context *context, int argc, sqlite3_value** argv) +static PyObject * +_pysqlite_build_py_params(sqlite3_context *context, int argc, + sqlite3_value **argv) { PyObject* args; int i; sqlite3_value* cur_value; PyObject* cur_py_value; - Py_ssize_t buflen; args = PyTuple_New(argc); if (!args) { @@ -591,23 +626,29 @@ PyObject* _pysqlite_build_py_params(sqlite3_context *context, int argc, sqlite3_ cur_py_value = PyUnicode_FromStringAndSize(text, size); break; } - case SQLITE_BLOB: - buflen = sqlite3_value_bytes(cur_value); - cur_py_value = PyBytes_FromStringAndSize( - sqlite3_value_blob(cur_value), buflen); + case SQLITE_BLOB: { + sqlite3 *db = sqlite3_context_db_handle(context); + const void *blob = sqlite3_value_blob(cur_value); + + if (blob == NULL && sqlite3_errcode(db) == SQLITE_NOMEM) { + PyErr_NoMemory(); + goto error; + } + + Py_ssize_t size = sqlite3_value_bytes(cur_value); + cur_py_value = PyBytes_FromStringAndSize(blob, size); break; + } case SQLITE_NULL: default: - Py_INCREF(Py_None); - cur_py_value = Py_None; + cur_py_value = Py_NewRef(Py_None); } if (!cur_py_value) { goto error; } - PyTuple_SetItem(args, i, cur_py_value); - + PyTuple_SET_ITEM(args, i, cur_py_value); } return args; @@ -617,7 +658,8 @@ error: return NULL; } -void _pysqlite_func_callback(sqlite3_context* context, int argc, sqlite3_value** argv) +static void +_pysqlite_func_callback(sqlite3_context *context, int argc, sqlite3_value **argv) { PyObject* args; PyObject* py_func; @@ -647,7 +689,7 @@ void _pysqlite_func_callback(sqlite3_context* context, int argc, sqlite3_value** } else { PyErr_Clear(); } - _sqlite3_result_error(context, "user-defined function raised exception", -1); + sqlite3_result_error(context, "user-defined function raised exception", -1); } PyGILState_Release(threadstate); @@ -679,7 +721,7 @@ static void _pysqlite_step_callback(sqlite3_context *context, int argc, sqlite3_ } else { PyErr_Clear(); } - _sqlite3_result_error(context, "user-defined aggregate's '__init__' method raised error", -1); + sqlite3_result_error(context, "user-defined aggregate's '__init__' method raised error", -1); goto error; } } @@ -703,7 +745,7 @@ static void _pysqlite_step_callback(sqlite3_context *context, int argc, sqlite3_ } else { PyErr_Clear(); } - _sqlite3_result_error(context, "user-defined aggregate's 'step' method raised error", -1); + sqlite3_result_error(context, "user-defined aggregate's 'step' method raised error", -1); } error: @@ -713,21 +755,25 @@ error: PyGILState_Release(threadstate); } -void _pysqlite_final_callback(sqlite3_context* context) +static void +_pysqlite_final_callback(sqlite3_context *context) { PyObject* function_result; PyObject** aggregate_instance; _Py_IDENTIFIER(finalize); int ok; PyObject *exception, *value, *tb; - int restore; PyGILState_STATE threadstate; threadstate = PyGILState_Ensure(); - aggregate_instance = (PyObject**)sqlite3_aggregate_context(context, sizeof(PyObject*)); - if (!*aggregate_instance) { + aggregate_instance = (PyObject**)sqlite3_aggregate_context(context, 0); + if (aggregate_instance == NULL) { + /* No rows matched the query; the step handler was never called. */ + goto error; + } + else if (!*aggregate_instance) { /* this branch is executed if there was an exception in the aggregate's * __init__ */ @@ -736,7 +782,6 @@ void _pysqlite_final_callback(sqlite3_context* context) /* Keep the exception (if any) of the last call to step() */ PyErr_Fetch(&exception, &value, &tb); - restore = 1; function_result = _PyObject_CallMethodIdNoArgs(*aggregate_instance, &PyId_finalize); @@ -753,19 +798,12 @@ void _pysqlite_final_callback(sqlite3_context* context) } else { PyErr_Clear(); } - _sqlite3_result_error(context, "user-defined aggregate's 'finalize' method raised error", -1); -#if SQLITE_VERSION_NUMBER < 3003003 - /* with old SQLite versions, _sqlite3_result_error() sets a new Python - exception, so don't restore the previous exception */ - restore = 0; -#endif + sqlite3_result_error(context, "user-defined aggregate's 'finalize' method raised error", -1); } - if (restore) { - /* Restore the exception (if any) of the last call to step(), - but clear also the current exception if finalize() failed */ - PyErr_Restore(exception, value, tb); - } + /* Restore the exception (if any) of the last call to step(), + but clear also the current exception if finalize() failed */ + PyErr_Restore(exception, value, tb); error: PyGILState_Release(threadstate); @@ -835,30 +873,39 @@ static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self) static void _destructor(void* args) { + // This function may be called without the GIL held, so we need to ensure + // that we destroy 'args' with the GIL + PyGILState_STATE gstate; + gstate = PyGILState_Ensure(); Py_DECREF((PyObject*)args); + PyGILState_Release(gstate); } -PyObject* pysqlite_connection_create_function(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) -{ - static char *kwlist[] = {"name", "narg", "func", "deterministic", NULL}; +/*[clinic input] +_sqlite3.Connection.create_function as pysqlite_connection_create_function - PyObject* func; - char* name; - int narg; + name: str + narg: int + func: object + * + deterministic: bool = False + +Creates a new function. +[clinic start generated code]*/ + +static PyObject * +pysqlite_connection_create_function_impl(pysqlite_Connection *self, + const char *name, int narg, + PyObject *func, int deterministic) +/*[clinic end generated code: output=07d1877dd98c0308 input=17e16b285ee44819]*/ +{ int rc; - int deterministic = 0; int flags = SQLITE_UTF8; if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "siO|$p", kwlist, - &name, &narg, &func, &deterministic)) - { - return NULL; - } - if (deterministic) { #if SQLITE_VERSION_NUMBER < 3008003 PyErr_SetString(pysqlite_NotSupportedError, @@ -873,12 +920,11 @@ PyObject* pysqlite_connection_create_function(pysqlite_Connection* self, PyObjec flags |= SQLITE_DETERMINISTIC; #endif } - Py_INCREF(func); rc = sqlite3_create_function_v2(self->db, name, narg, flags, - (void*)func, + (void*)Py_NewRef(func), _pysqlite_func_callback, NULL, NULL, @@ -892,29 +938,33 @@ PyObject* pysqlite_connection_create_function(pysqlite_Connection* self, PyObjec Py_RETURN_NONE; } -PyObject* pysqlite_connection_create_aggregate(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) -{ - PyObject* aggregate_class; +/*[clinic input] +_sqlite3.Connection.create_aggregate as pysqlite_connection_create_aggregate + + name: str + n_arg: int + aggregate_class: object - int n_arg; - char* name; - static char *kwlist[] = { "name", "n_arg", "aggregate_class", NULL }; +Creates a new aggregate. +[clinic start generated code]*/ + +static PyObject * +pysqlite_connection_create_aggregate_impl(pysqlite_Connection *self, + const char *name, int n_arg, + PyObject *aggregate_class) +/*[clinic end generated code: output=fbb2f858cfa4d8db input=a17afd1fcc930ecf]*/ +{ int rc; if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "siO:create_aggregate", - kwlist, &name, &n_arg, &aggregate_class)) { - return NULL; - } - Py_INCREF(aggregate_class); rc = sqlite3_create_function_v2(self->db, name, n_arg, SQLITE_UTF8, - (void*)aggregate_class, + (void*)Py_NewRef(aggregate_class), 0, &_pysqlite_step_callback, &_pysqlite_final_callback, @@ -993,13 +1043,29 @@ static int _progress_handler(void* user_arg) return rc; } +#ifdef HAVE_TRACE_V2 +/* + * From https://sqlite.org/c3ref/trace_v2.html: + * The integer return value from the callback is currently ignored, though this + * may change in future releases. Callback implementations should return zero + * to ensure future compatibility. + */ +static int _trace_callback(unsigned int type, void* user_arg, void* prepared_statement, void* statement_string) +#else static void _trace_callback(void* user_arg, const char* statement_string) +#endif { PyObject *py_statement = NULL; PyObject *ret = NULL; PyGILState_STATE gilstate; +#ifdef HAVE_TRACE_V2 + if (type != SQLITE_TRACE_STMT) { + return 0; + } +#endif + gilstate = PyGILState_Ensure(); py_statement = PyUnicode_DecodeUTF8(statement_string, strlen(statement_string), "replace"); @@ -1019,24 +1085,30 @@ static void _trace_callback(void* user_arg, const char* statement_string) } PyGILState_Release(gilstate); +#ifdef HAVE_TRACE_V2 + return 0; +#endif } -static PyObject* pysqlite_connection_set_authorizer(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) -{ - PyObject* authorizer_cb; +/*[clinic input] +_sqlite3.Connection.set_authorizer as pysqlite_connection_set_authorizer + + authorizer_callback as authorizer_cb: object - static char *kwlist[] = { "authorizer_callback", NULL }; +Sets authorizer callback. +[clinic start generated code]*/ + +static PyObject * +pysqlite_connection_set_authorizer_impl(pysqlite_Connection *self, + PyObject *authorizer_cb) +/*[clinic end generated code: output=f18ba575d788b35c input=446676a87c949d68]*/ +{ int rc; if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:set_authorizer", - kwlist, &authorizer_cb)) { - return NULL; - } - rc = sqlite3_set_authorizer(self->db, _authorizer_callback, (void*)authorizer_cb); if (rc != SQLITE_OK) { PyErr_SetString(pysqlite_OperationalError, "Error setting authorizer callback"); @@ -1049,19 +1121,22 @@ static PyObject* pysqlite_connection_set_authorizer(pysqlite_Connection* self, P Py_RETURN_NONE; } -static PyObject* pysqlite_connection_set_progress_handler(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) -{ - PyObject* progress_handler; - int n; +/*[clinic input] +_sqlite3.Connection.set_progress_handler as pysqlite_connection_set_progress_handler - static char *kwlist[] = { "progress_handler", "n", NULL }; + progress_handler: object + n: int - if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { - return NULL; - } +Sets progress handler callback. +[clinic start generated code]*/ - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi:set_progress_handler", - kwlist, &progress_handler, &n)) { +static PyObject * +pysqlite_connection_set_progress_handler_impl(pysqlite_Connection *self, + PyObject *progress_handler, + int n) +/*[clinic end generated code: output=35a7c10364cb1b04 input=d9379b629c7391c7]*/ +{ + if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } @@ -1077,27 +1152,43 @@ static PyObject* pysqlite_connection_set_progress_handler(pysqlite_Connection* s Py_RETURN_NONE; } -static PyObject* pysqlite_connection_set_trace_callback(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) -{ - PyObject* trace_callback; +/*[clinic input] +_sqlite3.Connection.set_trace_callback as pysqlite_connection_set_trace_callback - static char *kwlist[] = { "trace_callback", NULL }; + trace_callback: object - if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { - return NULL; - } +Sets a trace callback called for each SQL statement (passed as unicode). +[clinic start generated code]*/ - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:set_trace_callback", - kwlist, &trace_callback)) { +static PyObject * +pysqlite_connection_set_trace_callback_impl(pysqlite_Connection *self, + PyObject *trace_callback) +/*[clinic end generated code: output=fb0e307b9924d454 input=885e460ebbf79f0c]*/ +{ + if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } if (trace_callback == Py_None) { - /* None clears the trace callback previously set */ + /* + * None clears the trace callback previously set + * + * Ref. + * - https://sqlite.org/c3ref/c_trace.html + * - https://sqlite.org/c3ref/trace_v2.html + */ +#ifdef HAVE_TRACE_V2 + sqlite3_trace_v2(self->db, SQLITE_TRACE_STMT, 0, 0); +#else sqlite3_trace(self->db, 0, (void*)0); +#endif Py_XSETREF(self->function_pinboard_trace_callback, NULL); } else { +#ifdef HAVE_TRACE_V2 + sqlite3_trace_v2(self->db, SQLITE_TRACE_STMT, _trace_callback, trace_callback); +#else sqlite3_trace(self->db, _trace_callback, trace_callback); +#endif Py_INCREF(trace_callback); Py_XSETREF(self->function_pinboard_trace_callback, trace_callback); } @@ -1105,17 +1196,29 @@ static PyObject* pysqlite_connection_set_trace_callback(pysqlite_Connection* sel Py_RETURN_NONE; } -#ifdef HAVE_LOAD_EXTENSION -static PyObject* pysqlite_enable_load_extension(pysqlite_Connection* self, PyObject* args) +#ifndef SQLITE_OMIT_LOAD_EXTENSION +/*[clinic input] +_sqlite3.Connection.enable_load_extension as pysqlite_connection_enable_load_extension + + enable as onoff: bool(accept={int}) + / + +Enable dynamic loading of SQLite extension modules. +[clinic start generated code]*/ + +static PyObject * +pysqlite_connection_enable_load_extension_impl(pysqlite_Connection *self, + int onoff) +/*[clinic end generated code: output=9cac37190d388baf input=5f00e93f7a9d3540]*/ { int rc; - int onoff; - if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { + if (PySys_Audit("sqlite3.enable_load_extension", + "OO", self, onoff ? Py_True : Py_False) < 0) { return NULL; } - if (!PyArg_ParseTuple(args, "i", &onoff)) { + if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } @@ -1129,17 +1232,28 @@ static PyObject* pysqlite_enable_load_extension(pysqlite_Connection* self, PyObj } } -static PyObject* pysqlite_load_extension(pysqlite_Connection* self, PyObject* args) +/*[clinic input] +_sqlite3.Connection.load_extension as pysqlite_connection_load_extension + + name as extension_name: str + / + +Load SQLite extension module. +[clinic start generated code]*/ + +static PyObject * +pysqlite_connection_load_extension_impl(pysqlite_Connection *self, + const char *extension_name) +/*[clinic end generated code: output=47eb1d7312bc97a7 input=edd507389d89d621]*/ { int rc; - char* extension_name; char* errmsg; - if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { + if (PySys_Audit("sqlite3.load_extension", "Os", self, extension_name) < 0) { return NULL; } - if (!PyArg_ParseTuple(args, "s", &extension_name)) { + if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } @@ -1173,8 +1287,7 @@ static PyObject* pysqlite_connection_get_isolation_level(pysqlite_Connection* se if (!pysqlite_check_connection(self)) { return NULL; } - Py_INCREF(self->isolation_level); - return self->isolation_level; + return Py_NewRef(self->isolation_level); } static PyObject* pysqlite_connection_get_total_changes(pysqlite_Connection* self, void* unused) @@ -1254,12 +1367,13 @@ pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* iso return 0; } -PyObject* pysqlite_connection_call(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) +static PyObject * +pysqlite_connection_call(pysqlite_Connection *self, PyObject *args, + PyObject *kwargs) { PyObject* sql; pysqlite_Statement* statement; PyObject* weakref; - int rc; if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; @@ -1273,31 +1387,11 @@ PyObject* pysqlite_connection_call(pysqlite_Connection* self, PyObject* args, Py _pysqlite_drop_unused_statement_references(self); - statement = PyObject_New(pysqlite_Statement, &pysqlite_StatementType); - if (!statement) { + statement = pysqlite_statement_create(self, sql); + if (statement == NULL) { return NULL; } - statement->db = NULL; - statement->st = NULL; - statement->sql = NULL; - statement->in_use = 0; - statement->in_weakreflist = NULL; - - rc = pysqlite_statement_create(statement, self, sql); - if (rc != SQLITE_OK) { - if (rc == PYSQLITE_TOO_MUCH_SQL) { - PyErr_SetString(pysqlite_Warning, "You can only execute one statement at a time."); - } else if (rc == PYSQLITE_SQL_WRONG_TYPE) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) - PyErr_SetString(pysqlite_Warning, "SQL is of wrong type. Must be string."); - } else { - (void)pysqlite_statement_reset(statement); - _pysqlite_seterror(self->db, NULL); - } - goto error; - } - weakref = PyWeakref_NewRef((PyObject*)statement, NULL); if (weakref == NULL) goto error; @@ -1314,89 +1408,108 @@ error: return NULL; } -PyObject* pysqlite_connection_execute(pysqlite_Connection* self, PyObject* args) +/*[clinic input] +_sqlite3.Connection.execute as pysqlite_connection_execute + + sql: unicode + parameters: object = NULL + / + +Executes an SQL statement. +[clinic start generated code]*/ + +static PyObject * +pysqlite_connection_execute_impl(pysqlite_Connection *self, PyObject *sql, + PyObject *parameters) +/*[clinic end generated code: output=5be05ae01ee17ee4 input=27aa7792681ddba2]*/ { + _Py_IDENTIFIER(execute); PyObject* cursor = 0; PyObject* result = 0; - PyObject* method = 0; cursor = _PyObject_CallMethodIdNoArgs((PyObject*)self, &PyId_cursor); if (!cursor) { goto error; } - method = PyObject_GetAttrString(cursor, "execute"); - if (!method) { - Py_CLEAR(cursor); - goto error; - } - - result = PyObject_CallObject(method, args); + result = _PyObject_CallMethodIdObjArgs(cursor, &PyId_execute, sql, parameters, NULL); if (!result) { Py_CLEAR(cursor); } error: Py_XDECREF(result); - Py_XDECREF(method); return cursor; } -PyObject* pysqlite_connection_executemany(pysqlite_Connection* self, PyObject* args) +/*[clinic input] +_sqlite3.Connection.executemany as pysqlite_connection_executemany + + sql: unicode + parameters: object + / + +Repeatedly executes an SQL statement. +[clinic start generated code]*/ + +static PyObject * +pysqlite_connection_executemany_impl(pysqlite_Connection *self, + PyObject *sql, PyObject *parameters) +/*[clinic end generated code: output=776cd2fd20bfe71f input=495be76551d525db]*/ { + _Py_IDENTIFIER(executemany); PyObject* cursor = 0; PyObject* result = 0; - PyObject* method = 0; cursor = _PyObject_CallMethodIdNoArgs((PyObject*)self, &PyId_cursor); if (!cursor) { goto error; } - method = PyObject_GetAttrString(cursor, "executemany"); - if (!method) { - Py_CLEAR(cursor); - goto error; - } - - result = PyObject_CallObject(method, args); + result = _PyObject_CallMethodIdObjArgs(cursor, &PyId_executemany, sql, + parameters, NULL); if (!result) { Py_CLEAR(cursor); } error: Py_XDECREF(result); - Py_XDECREF(method); return cursor; } -PyObject* pysqlite_connection_executescript(pysqlite_Connection* self, PyObject* args) +/*[clinic input] +_sqlite3.Connection.executescript as pysqlite_connection_executescript + + sql_script as script_obj: object + / + +Executes multiple SQL statements at once. +[clinic start generated code]*/ + +static PyObject * +pysqlite_connection_executescript(pysqlite_Connection *self, + PyObject *script_obj) +/*[clinic end generated code: output=4c4f9d77aa0ae37d input=f6e5f1ccfa313db4]*/ { + _Py_IDENTIFIER(executescript); PyObject* cursor = 0; PyObject* result = 0; - PyObject* method = 0; cursor = _PyObject_CallMethodIdNoArgs((PyObject*)self, &PyId_cursor); if (!cursor) { goto error; } - method = PyObject_GetAttrString(cursor, "executescript"); - if (!method) { - Py_CLEAR(cursor); - goto error; - } - - result = PyObject_CallObject(method, args); + result = _PyObject_CallMethodIdObjArgs(cursor, &PyId_executescript, + script_obj, NULL); if (!result) { Py_CLEAR(cursor); } error: Py_XDECREF(result); - Py_XDECREF(method); return cursor; } @@ -1456,8 +1569,15 @@ finally: return result; } +/*[clinic input] +_sqlite3.Connection.interrupt as pysqlite_connection_interrupt + +Abort any pending database operation. +[clinic start generated code]*/ + static PyObject * -pysqlite_connection_interrupt(pysqlite_Connection* self, PyObject* args) +pysqlite_connection_interrupt_impl(pysqlite_Connection *self) +/*[clinic end generated code: output=f193204bc9e70b47 input=75ad03ade7012859]*/ { PyObject* retval = NULL; @@ -1467,8 +1587,7 @@ pysqlite_connection_interrupt(pysqlite_Connection* self, PyObject* args) sqlite3_interrupt(self->db); - Py_INCREF(Py_None); - retval = Py_None; + retval = Py_NewRef(Py_None); finally: return retval; @@ -1478,8 +1597,15 @@ finally: * Class method of Connection to call the Python function _iterdump * of the sqlite3 module. */ +/*[clinic input] +_sqlite3.Connection.iterdump as pysqlite_connection_iterdump + +Returns iterator to the dump of the database in an SQL text format. +[clinic start generated code]*/ + static PyObject * -pysqlite_connection_iterdump(pysqlite_Connection* self, PyObject* args) +pysqlite_connection_iterdump_impl(pysqlite_Connection *self) +/*[clinic end generated code: output=586997aaf9808768 input=1911ca756066da89]*/ { _Py_IDENTIFIER(_iterdump); PyObject* retval = NULL; @@ -1517,52 +1643,40 @@ finally: return retval; } -#ifdef HAVE_BACKUP_API +/*[clinic input] +_sqlite3.Connection.backup as pysqlite_connection_backup + + target: object(type='pysqlite_Connection *', subclass_of='pysqlite_ConnectionType') + * + pages: int = -1 + progress: object = None + name: str = "main" + sleep: double = 0.250 + +Makes a backup of the database. +[clinic start generated code]*/ + static PyObject * -pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject *kwds) +pysqlite_connection_backup_impl(pysqlite_Connection *self, + pysqlite_Connection *target, int pages, + PyObject *progress, const char *name, + double sleep) +/*[clinic end generated code: output=306a3e6a38c36334 input=458a0b6997c4960b]*/ { - PyObject *target = NULL; - int pages = -1; - PyObject *progress = Py_None; - const char *name = "main"; int rc; - int callback_error = 0; - PyObject *sleep_obj = NULL; - int sleep_ms = 250; + int sleep_ms = (int)(sleep * 1000.0); sqlite3 *bck_conn; sqlite3_backup *bck_handle; - static char *keywords[] = {"target", "pages", "progress", "name", "sleep", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|$iOsO:backup", keywords, - &pysqlite_ConnectionType, &target, - &pages, &progress, &name, &sleep_obj)) { - return NULL; - } - - if (sleep_obj != NULL) { - _PyTime_t sleep_secs; - if (_PyTime_FromSecondsObject(&sleep_secs, sleep_obj, - _PyTime_ROUND_TIMEOUT)) { - return NULL; - } - _PyTime_t ms = _PyTime_AsMilliseconds(sleep_secs, - _PyTime_ROUND_TIMEOUT); - if (ms < INT_MIN || ms > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, "sleep is too large"); - return NULL; - } - sleep_ms = (int)ms; - } if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } - if (!pysqlite_check_connection((pysqlite_Connection *)target)) { + if (!pysqlite_check_connection(target)) { return NULL; } - if ((pysqlite_Connection *)target == self) { + if (target == self) { PyErr_SetString(PyExc_ValueError, "target cannot be the same connection instance"); return NULL; } @@ -1570,7 +1684,7 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject * #if SQLITE_VERSION_NUMBER < 3008008 /* Since 3.8.8 this is already done, per commit https://www.sqlite.org/src/info/169b5505498c0a7e */ - if (!sqlite3_get_autocommit(((pysqlite_Connection *)target)->db)) { + if (!sqlite3_get_autocommit(target->db)) { PyErr_SetString(pysqlite_OperationalError, "target is in transaction"); return NULL; } @@ -1585,102 +1699,74 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject * pages = -1; } - bck_conn = ((pysqlite_Connection *)target)->db; + bck_conn = target->db; Py_BEGIN_ALLOW_THREADS bck_handle = sqlite3_backup_init(bck_conn, "main", self->db, name); Py_END_ALLOW_THREADS - if (bck_handle) { - do { - Py_BEGIN_ALLOW_THREADS - rc = sqlite3_backup_step(bck_handle, pages); - Py_END_ALLOW_THREADS + if (bck_handle == NULL) { + _pysqlite_seterror(bck_conn, NULL); + return NULL; + } - if (progress != Py_None) { - PyObject *res; - - res = PyObject_CallFunction(progress, "iii", rc, - sqlite3_backup_remaining(bck_handle), - sqlite3_backup_pagecount(bck_handle)); - if (res == NULL) { - /* User's callback raised an error: interrupt the loop and - propagate it. */ - callback_error = 1; - rc = -1; - } else { - Py_DECREF(res); - } - } + do { + Py_BEGIN_ALLOW_THREADS + rc = sqlite3_backup_step(bck_handle, pages); + Py_END_ALLOW_THREADS - /* Sleep for a while if there are still further pages to copy and - the engine could not make any progress */ - if (rc == SQLITE_BUSY || rc == SQLITE_LOCKED) { + if (progress != Py_None) { + int remaining = sqlite3_backup_remaining(bck_handle); + int pagecount = sqlite3_backup_pagecount(bck_handle); + PyObject *res = PyObject_CallFunction(progress, "iii", rc, + remaining, pagecount); + if (res == NULL) { + /* Callback failed: abort backup and bail. */ Py_BEGIN_ALLOW_THREADS - sqlite3_sleep(sleep_ms); + sqlite3_backup_finish(bck_handle); Py_END_ALLOW_THREADS + return NULL; } - } while (rc == SQLITE_OK || rc == SQLITE_BUSY || rc == SQLITE_LOCKED); - - Py_BEGIN_ALLOW_THREADS - rc = sqlite3_backup_finish(bck_handle); - Py_END_ALLOW_THREADS - } else { - rc = _pysqlite_seterror(bck_conn, NULL); - } + Py_DECREF(res); + } - if (!callback_error && rc != SQLITE_OK) { - /* We cannot use _pysqlite_seterror() here because the backup APIs do - not set the error status on the connection object, but rather on - the backup handle. */ - if (rc == SQLITE_NOMEM) { - (void)PyErr_NoMemory(); - } else { -#if SQLITE_VERSION_NUMBER > 3007015 - PyErr_SetString(pysqlite_OperationalError, sqlite3_errstr(rc)); -#else - switch (rc) { - case SQLITE_ERROR: - /* Description of SQLITE_ERROR in SQLite 3.7.14 and older - releases. */ - PyErr_SetString(pysqlite_OperationalError, - "SQL logic error or missing database"); - break; - case SQLITE_READONLY: - PyErr_SetString(pysqlite_OperationalError, - "attempt to write a readonly database"); - break; - case SQLITE_BUSY: - PyErr_SetString(pysqlite_OperationalError, "database is locked"); - break; - case SQLITE_LOCKED: - PyErr_SetString(pysqlite_OperationalError, - "database table is locked"); - break; - default: - PyErr_Format(pysqlite_OperationalError, - "unrecognized error code: %d", rc); - break; - } -#endif + /* Sleep for a while if there are still further pages to copy and + the engine could not make any progress */ + if (rc == SQLITE_BUSY || rc == SQLITE_LOCKED) { + Py_BEGIN_ALLOW_THREADS + sqlite3_sleep(sleep_ms); + Py_END_ALLOW_THREADS } - } + } while (rc == SQLITE_OK || rc == SQLITE_BUSY || rc == SQLITE_LOCKED); - if (!callback_error && rc == SQLITE_OK) { - Py_RETURN_NONE; - } else { + Py_BEGIN_ALLOW_THREADS + rc = sqlite3_backup_finish(bck_handle); + Py_END_ALLOW_THREADS + + if (rc != SQLITE_OK) { + _pysqlite_seterror(bck_conn, NULL); return NULL; } + + Py_RETURN_NONE; } -#endif + +/*[clinic input] +_sqlite3.Connection.create_collation as pysqlite_connection_create_collation + + name: unicode + callback as callable: object + / + +Creates a collation function. +[clinic start generated code]*/ static PyObject * -pysqlite_connection_create_collation(pysqlite_Connection* self, PyObject* args) +pysqlite_connection_create_collation_impl(pysqlite_Connection *self, + PyObject *name, PyObject *callable) +/*[clinic end generated code: output=0f63b8995565ae22 input=eb2c4328dc493ee8]*/ { - PyObject* callable; PyObject* uppercase_name = 0; - PyObject* name; - PyObject* retval; Py_ssize_t i, len; _Py_IDENTIFIER(upper); const char *uppercase_name_str; @@ -1692,11 +1778,6 @@ pysqlite_connection_create_collation(pysqlite_Connection* self, PyObject* args) goto finally; } - if (!PyArg_ParseTuple(args, "UO:create_collation(name, callback)", - &name, &callable)) { - goto finally; - } - uppercase_name = _PyObject_CallMethodIdOneArg((PyObject *)&PyUnicode_Type, &PyId_upper, name); if (!uppercase_name) { @@ -1757,42 +1838,53 @@ finally: Py_XDECREF(uppercase_name); if (PyErr_Occurred()) { - retval = NULL; - } else { - Py_INCREF(Py_None); - retval = Py_None; + return NULL; } - - return retval; + return Py_NewRef(Py_None); } -/* Called when the connection is used as a context manager. Returns itself as a - * convenience to the caller. */ +/*[clinic input] +_sqlite3.Connection.__enter__ as pysqlite_connection_enter + +Called when the connection is used as a context manager. + +Returns itself as a convenience to the caller. +[clinic start generated code]*/ + static PyObject * -pysqlite_connection_enter(pysqlite_Connection* self, PyObject* args) +pysqlite_connection_enter_impl(pysqlite_Connection *self) +/*[clinic end generated code: output=457b09726d3e9dcd input=127d7a4f17e86d8f]*/ { - Py_INCREF(self); - return (PyObject*)self; + return Py_NewRef((PyObject *)self); } -/** Called when the connection is used as a context manager. If there was any - * exception, a rollback takes place; otherwise we commit. */ +/*[clinic input] +_sqlite3.Connection.__exit__ as pysqlite_connection_exit + + type as exc_type: object + value as exc_value: object + traceback as exc_tb: object + / + +Called when the connection is used as a context manager. + +If there was any exception, a rollback takes place; otherwise we commit. +[clinic start generated code]*/ + static PyObject * -pysqlite_connection_exit(pysqlite_Connection* self, PyObject* args) +pysqlite_connection_exit_impl(pysqlite_Connection *self, PyObject *exc_type, + PyObject *exc_value, PyObject *exc_tb) +/*[clinic end generated code: output=0705200e9321202a input=bd66f1532c9c54a7]*/ { - PyObject *exc_type, *exc_value, *exc_tb; - if (!PyArg_ParseTuple(args, "OOO", &exc_type, &exc_value, &exc_tb)) { - return NULL; - } - int commit = 0; - PyObject *result; + PyObject* result; + if (exc_type == Py_None && exc_value == Py_None && exc_tb == Py_None) { commit = 1; - result = pysqlite_connection_commit(self, NULL); + result = pysqlite_connection_commit_impl(self); } else { - result = pysqlite_connection_rollback(self, NULL); + result = pysqlite_connection_rollback_impl(self); } if (result == NULL) { @@ -1801,7 +1893,7 @@ pysqlite_connection_exit(pysqlite_Connection* self, PyObject* args) * If rollback also fails, chain the exceptions. */ PyObject *exc, *val, *tb; PyErr_Fetch(&exc, &val, &tb); - result = pysqlite_connection_rollback(self, NULL); + result = pysqlite_connection_rollback_impl(self); if (result == NULL) { _PyErr_ChainExceptions(exc, val, tb); } @@ -1828,50 +1920,26 @@ static PyGetSetDef connection_getset[] = { }; static PyMethodDef connection_methods[] = { - {"cursor", (PyCFunction)(void(*)(void))pysqlite_connection_cursor, METH_VARARGS|METH_KEYWORDS, - PyDoc_STR("Return a cursor for the connection.")}, - {"close", (PyCFunction)pysqlite_connection_close, METH_NOARGS, - PyDoc_STR("Closes the connection.")}, - {"commit", (PyCFunction)pysqlite_connection_commit, METH_NOARGS, - PyDoc_STR("Commit the current transaction.")}, - {"rollback", (PyCFunction)pysqlite_connection_rollback, METH_NOARGS, - PyDoc_STR("Roll back the current transaction.")}, - {"create_function", (PyCFunction)(void(*)(void))pysqlite_connection_create_function, METH_VARARGS|METH_KEYWORDS, - PyDoc_STR("Creates a new function.")}, - {"create_aggregate", (PyCFunction)(void(*)(void))pysqlite_connection_create_aggregate, METH_VARARGS|METH_KEYWORDS, - PyDoc_STR("Creates a new aggregate.")}, - {"set_authorizer", (PyCFunction)(void(*)(void))pysqlite_connection_set_authorizer, METH_VARARGS|METH_KEYWORDS, - PyDoc_STR("Sets authorizer callback.")}, - #ifdef HAVE_LOAD_EXTENSION - {"enable_load_extension", (PyCFunction)pysqlite_enable_load_extension, METH_VARARGS, - PyDoc_STR("Enable dynamic loading of SQLite extension modules.")}, - {"load_extension", (PyCFunction)pysqlite_load_extension, METH_VARARGS, - PyDoc_STR("Load SQLite extension module.")}, - #endif - {"set_progress_handler", (PyCFunction)(void(*)(void))pysqlite_connection_set_progress_handler, METH_VARARGS|METH_KEYWORDS, - PyDoc_STR("Sets progress handler callback.")}, - {"set_trace_callback", (PyCFunction)(void(*)(void))pysqlite_connection_set_trace_callback, METH_VARARGS|METH_KEYWORDS, - PyDoc_STR("Sets a trace callback called for each SQL statement (passed as unicode).")}, - {"execute", (PyCFunction)pysqlite_connection_execute, METH_VARARGS, - PyDoc_STR("Executes an SQL statement.")}, - {"executemany", (PyCFunction)pysqlite_connection_executemany, METH_VARARGS, - PyDoc_STR("Repeatedly executes an SQL statement.")}, - {"executescript", (PyCFunction)pysqlite_connection_executescript, METH_VARARGS, - PyDoc_STR("Executes a multiple SQL statements at once.")}, - {"create_collation", (PyCFunction)pysqlite_connection_create_collation, METH_VARARGS, - PyDoc_STR("Creates a collation function.")}, - {"interrupt", (PyCFunction)pysqlite_connection_interrupt, METH_NOARGS, - PyDoc_STR("Abort any pending database operation.")}, - {"iterdump", (PyCFunction)pysqlite_connection_iterdump, METH_NOARGS, - PyDoc_STR("Returns iterator to the dump of the database in an SQL text format.")}, - #ifdef HAVE_BACKUP_API - {"backup", (PyCFunction)(void(*)(void))pysqlite_connection_backup, METH_VARARGS | METH_KEYWORDS, - PyDoc_STR("Makes a backup of the database.")}, - #endif - {"__enter__", (PyCFunction)pysqlite_connection_enter, METH_NOARGS, - PyDoc_STR("For context manager.")}, - {"__exit__", (PyCFunction)pysqlite_connection_exit, METH_VARARGS, - PyDoc_STR("For context manager.")}, + PYSQLITE_CONNECTION_BACKUP_METHODDEF + PYSQLITE_CONNECTION_CLOSE_METHODDEF + PYSQLITE_CONNECTION_COMMIT_METHODDEF + PYSQLITE_CONNECTION_CREATE_AGGREGATE_METHODDEF + PYSQLITE_CONNECTION_CREATE_COLLATION_METHODDEF + PYSQLITE_CONNECTION_CREATE_FUNCTION_METHODDEF + PYSQLITE_CONNECTION_CURSOR_METHODDEF + PYSQLITE_CONNECTION_ENABLE_LOAD_EXTENSION_METHODDEF + PYSQLITE_CONNECTION_ENTER_METHODDEF + PYSQLITE_CONNECTION_EXECUTEMANY_METHODDEF + PYSQLITE_CONNECTION_EXECUTESCRIPT_METHODDEF + PYSQLITE_CONNECTION_EXECUTE_METHODDEF + PYSQLITE_CONNECTION_EXIT_METHODDEF + PYSQLITE_CONNECTION_INTERRUPT_METHODDEF + PYSQLITE_CONNECTION_ITERDUMP_METHODDEF + PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF + PYSQLITE_CONNECTION_ROLLBACK_METHODDEF + PYSQLITE_CONNECTION_SET_AUTHORIZER_METHODDEF + PYSQLITE_CONNECTION_SET_PROGRESS_HANDLER_METHODDEF + PYSQLITE_CONNECTION_SET_TRACE_CALLBACK_METHODDEF {NULL, NULL} }; @@ -1892,50 +1960,35 @@ static struct PyMemberDef connection_members[] = {NULL} }; -PyTypeObject pysqlite_ConnectionType = { - PyVarObject_HEAD_INIT(NULL, 0) - MODULE_NAME ".Connection", /* tp_name */ - sizeof(pysqlite_Connection), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)pysqlite_connection_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - (ternaryfunc)pysqlite_connection_call, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ - connection_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - connection_methods, /* tp_methods */ - connection_members, /* tp_members */ - connection_getset, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)pysqlite_connection_init, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0 /* tp_free */ +static PyType_Slot connection_slots[] = { + {Py_tp_dealloc, connection_dealloc}, + {Py_tp_doc, (void *)connection_doc}, + {Py_tp_methods, connection_methods}, + {Py_tp_members, connection_members}, + {Py_tp_getset, connection_getset}, + {Py_tp_init, pysqlite_connection_init}, + {Py_tp_call, pysqlite_connection_call}, + {Py_tp_traverse, connection_traverse}, + {Py_tp_clear, connection_clear}, + {0, NULL}, +}; + +static PyType_Spec connection_spec = { + .name = MODULE_NAME ".Connection", + .basicsize = sizeof(pysqlite_Connection), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), + .slots = connection_slots, }; -extern int pysqlite_connection_setup_types(void) +PyTypeObject *pysqlite_ConnectionType = NULL; + +int +pysqlite_connection_setup_types(PyObject *module) { - pysqlite_ConnectionType.tp_new = PyType_GenericNew; - return PyType_Ready(&pysqlite_ConnectionType); + pysqlite_ConnectionType = (PyTypeObject *)PyType_FromModuleAndSpec(module, &connection_spec, NULL); + if (pysqlite_ConnectionType == NULL) { + return -1; + } + return 0; } diff --git a/contrib/tools/python3/src/Modules/_sqlite/connection.h b/contrib/tools/python3/src/Modules/_sqlite/connection.h index 206085e00a..8773c9eac0 100644 --- a/contrib/tools/python3/src/Modules/_sqlite/connection.h +++ b/contrib/tools/python3/src/Modules/_sqlite/connection.h @@ -93,7 +93,7 @@ typedef struct /* a dictionary of registered collation name => collation callable mappings */ PyObject* collations; - /* Exception objects */ + /* Exception objects: borrowed refs. */ PyObject* Warning; PyObject* Error; PyObject* InterfaceError; @@ -106,22 +106,14 @@ typedef struct PyObject* NotSupportedError; } pysqlite_Connection; -extern PyTypeObject pysqlite_ConnectionType; +extern PyTypeObject *pysqlite_ConnectionType; -PyObject* pysqlite_connection_alloc(PyTypeObject* type, int aware); -void pysqlite_connection_dealloc(pysqlite_Connection* self); -PyObject* pysqlite_connection_cursor(pysqlite_Connection* self, PyObject* args, PyObject* kwargs); -PyObject* pysqlite_connection_close(pysqlite_Connection* self, PyObject* args); PyObject* _pysqlite_connection_begin(pysqlite_Connection* self); -PyObject* pysqlite_connection_commit(pysqlite_Connection* self, PyObject* args); -PyObject* pysqlite_connection_rollback(pysqlite_Connection* self, PyObject* args); -PyObject* pysqlite_connection_new(PyTypeObject* type, PyObject* args, PyObject* kw); -int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject* kwargs); int pysqlite_connection_register_cursor(pysqlite_Connection* connection, PyObject* cursor); int pysqlite_check_thread(pysqlite_Connection* self); int pysqlite_check_connection(pysqlite_Connection* con); -int pysqlite_connection_setup_types(void); +int pysqlite_connection_setup_types(PyObject *module); #endif diff --git a/contrib/tools/python3/src/Modules/_sqlite/cursor.c b/contrib/tools/python3/src/Modules/_sqlite/cursor.c index e2635e18c7..85267cc9e7 100644 --- a/contrib/tools/python3/src/Modules/_sqlite/cursor.c +++ b/contrib/tools/python3/src/Modules/_sqlite/cursor.c @@ -24,20 +24,29 @@ #include "cursor.h" #include "module.h" #include "util.h" +#include "clinic/cursor.c.h" -PyObject* pysqlite_cursor_iternext(pysqlite_Cursor* self); +/*[clinic input] +module _sqlite3 +class _sqlite3.Cursor "pysqlite_Cursor *" "pysqlite_CursorType" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b2072d8db95411d5]*/ static const char errmsg_fetch_across_rollback[] = "Cursor needed to be reset because of commit/rollback and can no longer be fetched from."; -static int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs) -{ - pysqlite_Connection* connection; +/*[clinic input] +_sqlite3.Cursor.__init__ as pysqlite_cursor_init - if (!PyArg_ParseTuple(args, "O!", &pysqlite_ConnectionType, &connection)) - { - return -1; - } + connection: object(type='pysqlite_Connection *', subclass_of='pysqlite_ConnectionType') + / + +[clinic start generated code]*/ +static int +pysqlite_cursor_init_impl(pysqlite_Cursor *self, + pysqlite_Connection *connection) +/*[clinic end generated code: output=ac59dce49a809ca8 input=a8a4f75ac90999b2]*/ +{ Py_INCREF(connection); Py_XSETREF(self->connection, connection); Py_CLEAR(self->statement); @@ -72,26 +81,49 @@ static int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject* return 0; } -static void pysqlite_cursor_dealloc(pysqlite_Cursor* self) +static int +cursor_traverse(pysqlite_Cursor *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + Py_VISIT(self->connection); + Py_VISIT(self->description); + Py_VISIT(self->row_cast_map); + Py_VISIT(self->lastrowid); + Py_VISIT(self->row_factory); + Py_VISIT(self->statement); + Py_VISIT(self->next_row); + return 0; +} + +static int +cursor_clear(pysqlite_Cursor *self) { - /* Reset the statement if the user has not closed the cursor */ + Py_CLEAR(self->connection); + Py_CLEAR(self->description); + Py_CLEAR(self->row_cast_map); + Py_CLEAR(self->lastrowid); + Py_CLEAR(self->row_factory); if (self->statement) { + /* Reset the statement if the user has not closed the cursor */ pysqlite_statement_reset(self->statement); - Py_DECREF(self->statement); + Py_CLEAR(self->statement); } + Py_CLEAR(self->next_row); - Py_XDECREF(self->connection); - Py_XDECREF(self->row_cast_map); - Py_XDECREF(self->description); - Py_XDECREF(self->lastrowid); - Py_XDECREF(self->row_factory); - Py_XDECREF(self->next_row); + return 0; +} +static void +cursor_dealloc(pysqlite_Cursor *self) +{ + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); if (self->in_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject*)self); } - - Py_TYPE(self)->tp_free((PyObject*)self); + tp->tp_clear((PyObject *)self); + tp->tp_free(self); + Py_DECREF(tp); } static PyObject * @@ -123,7 +155,6 @@ pysqlite_build_row_cast_map(pysqlite_Cursor* self) { int i; const char* pos; - const char* colname; const char* decltype; PyObject* converter; @@ -140,21 +171,24 @@ pysqlite_build_row_cast_map(pysqlite_Cursor* self) converter = NULL; if (self->connection->detect_types & PARSE_COLNAMES) { - colname = sqlite3_column_name(self->statement->st, i); - if (colname) { - const char *type_start = NULL; - for (pos = colname; *pos != 0; pos++) { - if (*pos == '[') { - type_start = pos + 1; - } - else if (*pos == ']' && type_start != NULL) { - converter = _pysqlite_get_converter(type_start, pos - type_start); - if (!converter && PyErr_Occurred()) { - Py_CLEAR(self->row_cast_map); - return -1; - } - break; + const char *colname = sqlite3_column_name(self->statement->st, i); + if (colname == NULL) { + PyErr_NoMemory(); + Py_CLEAR(self->row_cast_map); + return -1; + } + const char *type_start = NULL; + for (pos = colname; *pos != 0; pos++) { + if (*pos == '[') { + type_start = pos + 1; + } + else if (*pos == ']' && type_start != NULL) { + converter = _pysqlite_get_converter(type_start, pos - type_start); + if (!converter && PyErr_Occurred()) { + Py_CLEAR(self->row_cast_map); + return -1; } + break; } } } @@ -198,10 +232,6 @@ _pysqlite_build_column_name(pysqlite_Cursor *self, const char *colname) const char* pos; Py_ssize_t len; - if (!colname) { - Py_RETURN_NONE; - } - if (self->connection->detect_types & PARSE_COLNAMES) { for (pos = colname; *pos; pos++) { if (*pos == '[') { @@ -230,12 +260,10 @@ _pysqlite_fetch_one_row(pysqlite_Cursor* self) { int i, numcols; PyObject* row; - PyObject* item = NULL; int coltype; PyObject* converter; PyObject* converted; Py_ssize_t nbytes; - const char* val_str; char buf[200]; const char* colname; PyObject* error_msg; @@ -253,6 +281,7 @@ _pysqlite_fetch_one_row(pysqlite_Cursor* self) if (!row) return NULL; + sqlite3 *db = self->connection->db; for (i = 0; i < numcols; i++) { if (self->connection->detect_types && self->row_cast_map != NULL @@ -264,16 +293,27 @@ _pysqlite_fetch_one_row(pysqlite_Cursor* self) converter = Py_None; } + /* + * Note, sqlite3_column_bytes() must come after sqlite3_column_blob() + * or sqlite3_column_text(). + * + * See https://sqlite.org/c3ref/column_blob.html for details. + */ if (converter != Py_None) { - nbytes = sqlite3_column_bytes(self->statement->st, i); - val_str = (const char*)sqlite3_column_blob(self->statement->st, i); - if (!val_str) { - Py_INCREF(Py_None); - converted = Py_None; - } else { - item = PyBytes_FromStringAndSize(val_str, nbytes); - if (!item) + const void *blob = sqlite3_column_blob(self->statement->st, i); + if (blob == NULL) { + if (sqlite3_errcode(db) == SQLITE_NOMEM) { + PyErr_NoMemory(); + goto error; + } + converted = Py_NewRef(Py_None); + } + else { + nbytes = sqlite3_column_bytes(self->statement->st, i); + PyObject *item = PyBytes_FromStringAndSize(blob, nbytes); + if (item == NULL) { goto error; + } converted = PyObject_CallOneArg(converter, item); Py_DECREF(item); } @@ -282,25 +322,30 @@ _pysqlite_fetch_one_row(pysqlite_Cursor* self) coltype = sqlite3_column_type(self->statement->st, i); Py_END_ALLOW_THREADS if (coltype == SQLITE_NULL) { - Py_INCREF(Py_None); - converted = Py_None; + converted = Py_NewRef(Py_None); } else if (coltype == SQLITE_INTEGER) { converted = PyLong_FromLongLong(sqlite3_column_int64(self->statement->st, i)); } else if (coltype == SQLITE_FLOAT) { converted = PyFloat_FromDouble(sqlite3_column_double(self->statement->st, i)); } else if (coltype == SQLITE_TEXT) { - val_str = (const char*)sqlite3_column_text(self->statement->st, i); + const char *text = (const char*)sqlite3_column_text(self->statement->st, i); + if (text == NULL && sqlite3_errcode(db) == SQLITE_NOMEM) { + PyErr_NoMemory(); + goto error; + } + nbytes = sqlite3_column_bytes(self->statement->st, i); if (self->connection->text_factory == (PyObject*)&PyUnicode_Type) { - converted = PyUnicode_FromStringAndSize(val_str, nbytes); + converted = PyUnicode_FromStringAndSize(text, nbytes); if (!converted && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) { PyErr_Clear(); colname = sqlite3_column_name(self->statement->st, i); - if (!colname) { - colname = "<unknown column name>"; + if (colname == NULL) { + PyErr_NoMemory(); + goto error; } PyOS_snprintf(buf, sizeof(buf) - 1, "Could not decode to UTF-8 column '%s' with text '%s'", - colname , val_str); + colname , text); error_msg = PyUnicode_Decode(buf, strlen(buf), "ascii", "replace"); if (!error_msg) { PyErr_SetString(pysqlite_OperationalError, "Could not decode to UTF-8"); @@ -310,24 +355,29 @@ _pysqlite_fetch_one_row(pysqlite_Cursor* self) } } } else if (self->connection->text_factory == (PyObject*)&PyBytes_Type) { - converted = PyBytes_FromStringAndSize(val_str, nbytes); + converted = PyBytes_FromStringAndSize(text, nbytes); } else if (self->connection->text_factory == (PyObject*)&PyByteArray_Type) { - converted = PyByteArray_FromStringAndSize(val_str, nbytes); + converted = PyByteArray_FromStringAndSize(text, nbytes); } else { - converted = PyObject_CallFunction(self->connection->text_factory, "y#", val_str, nbytes); + converted = PyObject_CallFunction(self->connection->text_factory, "y#", text, nbytes); } } else { /* coltype == SQLITE_BLOB */ + const void *blob = sqlite3_column_blob(self->statement->st, i); + if (blob == NULL && sqlite3_errcode(db) == SQLITE_NOMEM) { + PyErr_NoMemory(); + goto error; + } + nbytes = sqlite3_column_bytes(self->statement->st, i); - converted = PyBytes_FromStringAndSize( - sqlite3_column_blob(self->statement->st, i), nbytes); + converted = PyBytes_FromStringAndSize(blob, nbytes); } } if (!converted) { goto error; } - PyTuple_SetItem(row, i, converted); + PyTuple_SET_ITEM(row, i, converted); } if (PyErr_Occurred()) @@ -366,9 +416,8 @@ static int check_cursor(pysqlite_Cursor* cur) } static PyObject * -_pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args) +_pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation, PyObject* second_argument) { - PyObject* operation; PyObject* parameters_list = NULL; PyObject* parameters_iter = NULL; PyObject* parameters = NULL; @@ -377,9 +426,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args) PyObject* func_args; PyObject* result; int numcols; - PyObject* descriptor; PyObject* column_name; - PyObject* second_argument = NULL; sqlite_int64 lastrowid; if (!check_cursor(self)) { @@ -392,15 +439,9 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args) Py_CLEAR(self->next_row); if (multiple) { - /* executemany() */ - if (!PyArg_ParseTuple(args, "UO", &operation, &second_argument)) { - goto error; - } - if (PyIter_Check(second_argument)) { /* iterator */ - Py_INCREF(second_argument); - parameters_iter = second_argument; + parameters_iter = Py_NewRef(second_argument); } else { /* sequence */ parameters_iter = PyObject_GetIter(second_argument); @@ -409,11 +450,6 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args) } } } else { - /* execute() */ - if (!PyArg_ParseTuple(args, "U|O", &operation, &second_argument)) { - goto error; - } - parameters_list = PyList_New(0); if (!parameters_list) { goto error; @@ -453,8 +489,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args) if (!func_args) { goto error; } - Py_INCREF(operation); - if (PyTuple_SetItem(func_args, 0, operation) != 0) { + if (PyTuple_SetItem(func_args, 0, Py_NewRef(operation)) != 0) { goto error; } @@ -472,13 +507,8 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args) if (self->statement->in_use) { Py_SETREF(self->statement, - PyObject_New(pysqlite_Statement, &pysqlite_StatementType)); - if (!self->statement) { - goto error; - } - rc = pysqlite_statement_create(self->statement, self->connection, operation); - if (rc != SQLITE_OK) { - Py_CLEAR(self->statement); + pysqlite_statement_create(self->connection, operation)); + if (self->statement == NULL) { goto error; } } @@ -541,24 +571,24 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args) goto error; } for (i = 0; i < numcols; i++) { - descriptor = PyTuple_New(7); - if (!descriptor) { + const char *colname; + colname = sqlite3_column_name(self->statement->st, i); + if (colname == NULL) { + PyErr_NoMemory(); goto error; } - column_name = _pysqlite_build_column_name(self, - sqlite3_column_name(self->statement->st, i)); - if (!column_name) { - Py_DECREF(descriptor); + column_name = _pysqlite_build_column_name(self, colname); + if (column_name == NULL) { goto error; } - PyTuple_SetItem(descriptor, 0, column_name); - Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 1, Py_None); - Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 2, Py_None); - Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 3, Py_None); - Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 4, Py_None); - Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 5, Py_None); - Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 6, Py_None); - PyTuple_SetItem(self->description, i, descriptor); + PyObject *descriptor = PyTuple_Pack(7, column_name, + Py_None, Py_None, Py_None, + Py_None, Py_None, Py_None); + Py_DECREF(column_name); + if (descriptor == NULL) { + goto error; + } + PyTuple_SET_ITEM(self->description, i, descriptor); } } @@ -609,34 +639,65 @@ error: self->rowcount = -1L; return NULL; } else { - Py_INCREF(self); - return (PyObject*)self; + return Py_NewRef((PyObject *)self); } } -PyObject* pysqlite_cursor_execute(pysqlite_Cursor* self, PyObject* args) +/*[clinic input] +_sqlite3.Cursor.execute as pysqlite_cursor_execute + + sql: unicode + parameters: object(c_default = 'NULL') = () + / + +Executes an SQL statement. +[clinic start generated code]*/ + +static PyObject * +pysqlite_cursor_execute_impl(pysqlite_Cursor *self, PyObject *sql, + PyObject *parameters) +/*[clinic end generated code: output=d81b4655c7c0bbad input=a8e0200a11627f94]*/ { - return _pysqlite_query_execute(self, 0, args); + return _pysqlite_query_execute(self, 0, sql, parameters); } -PyObject* pysqlite_cursor_executemany(pysqlite_Cursor* self, PyObject* args) +/*[clinic input] +_sqlite3.Cursor.executemany as pysqlite_cursor_executemany + + sql: unicode + seq_of_parameters: object + / + +Repeatedly executes an SQL statement. +[clinic start generated code]*/ + +static PyObject * +pysqlite_cursor_executemany_impl(pysqlite_Cursor *self, PyObject *sql, + PyObject *seq_of_parameters) +/*[clinic end generated code: output=2c65a3c4733fb5d8 input=0d0a52e5eb7ccd35]*/ { - return _pysqlite_query_execute(self, 1, args); + return _pysqlite_query_execute(self, 1, sql, seq_of_parameters); } +/*[clinic input] +_sqlite3.Cursor.executescript as pysqlite_cursor_executescript + + sql_script as script_obj: object + / + +Executes multiple SQL statements at once. +[clinic start generated code]*/ + static PyObject * -pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args) +pysqlite_cursor_executescript(pysqlite_Cursor *self, PyObject *script_obj) +/*[clinic end generated code: output=115a8132b0f200fe input=75270e5bcdb4d6aa]*/ { - PyObject* script_obj; + _Py_IDENTIFIER(commit); const char* script_cstr; sqlite3_stmt* statement; int rc; PyObject* result; - if (!PyArg_ParseTuple(args, "O", &script_obj)) { - return NULL; - } - if (!check_cursor(self)) { return NULL; } @@ -654,7 +715,7 @@ pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args) } /* commit first */ - result = pysqlite_connection_commit(self->connection, NULL); + result = _PyObject_CallMethodIdNoArgs((PyObject *)self->connection, &PyId_commit); if (!result) { goto error; } @@ -674,14 +735,13 @@ pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args) } /* execute statement, and ignore results of SELECT statements */ - rc = SQLITE_ROW; - while (rc == SQLITE_ROW) { + do { rc = pysqlite_step(statement, self->connection); if (PyErr_Occurred()) { (void)sqlite3_finalize(statement); goto error; } - } + } while (rc == SQLITE_ROW); if (rc != SQLITE_DONE) { (void)sqlite3_finalize(statement); @@ -704,12 +764,12 @@ error: if (PyErr_Occurred()) { return NULL; } else { - Py_INCREF(self); - return (PyObject*)self; + return Py_NewRef((PyObject *)self); } } -PyObject* pysqlite_cursor_iternext(pysqlite_Cursor *self) +static PyObject * +pysqlite_cursor_iternext(pysqlite_Cursor *self) { PyObject* next_row_tuple; PyObject* next_row; @@ -773,7 +833,15 @@ PyObject* pysqlite_cursor_iternext(pysqlite_Cursor *self) return next_row; } -PyObject* pysqlite_cursor_fetchone(pysqlite_Cursor* self, PyObject* args) +/*[clinic input] +_sqlite3.Cursor.fetchone as pysqlite_cursor_fetchone + +Fetches one row from the resultset. +[clinic start generated code]*/ + +static PyObject * +pysqlite_cursor_fetchone_impl(pysqlite_Cursor *self) +/*[clinic end generated code: output=4bd2eabf5baaddb0 input=e78294ec5980fdba]*/ { PyObject* row; @@ -785,19 +853,23 @@ PyObject* pysqlite_cursor_fetchone(pysqlite_Cursor* self, PyObject* args) return row; } -PyObject* pysqlite_cursor_fetchmany(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs) -{ - static char *kwlist[] = {"size", NULL}; +/*[clinic input] +_sqlite3.Cursor.fetchmany as pysqlite_cursor_fetchmany + + size as maxrows: int(c_default='self->arraysize') = 1 + The default value is set by the Cursor.arraysize attribute. + +Fetches several rows from the resultset. +[clinic start generated code]*/ +static PyObject * +pysqlite_cursor_fetchmany_impl(pysqlite_Cursor *self, int maxrows) +/*[clinic end generated code: output=a8ef31fea64d0906 input=c26e6ca3f34debd0]*/ +{ PyObject* row; PyObject* list; - int maxrows = self->arraysize; int counter = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:fetchmany", kwlist, &maxrows)) { - return NULL; - } - list = PyList_New(0); if (!list) { return NULL; @@ -823,7 +895,15 @@ PyObject* pysqlite_cursor_fetchmany(pysqlite_Cursor* self, PyObject* args, PyObj } } -PyObject* pysqlite_cursor_fetchall(pysqlite_Cursor* self, PyObject* args) +/*[clinic input] +_sqlite3.Cursor.fetchall as pysqlite_cursor_fetchall + +Fetches all rows from the resultset. +[clinic start generated code]*/ + +static PyObject * +pysqlite_cursor_fetchall_impl(pysqlite_Cursor *self) +/*[clinic end generated code: output=d5da12aca2da4b27 input=f5d401086a8df25a]*/ { PyObject* row; PyObject* list; @@ -849,13 +929,49 @@ PyObject* pysqlite_cursor_fetchall(pysqlite_Cursor* self, PyObject* args) } } -PyObject* pysqlite_noop(pysqlite_Connection* self, PyObject* args) +/*[clinic input] +_sqlite3.Cursor.setinputsizes as pysqlite_cursor_setinputsizes + + sizes: object + / + +Required by DB-API. Does nothing in sqlite3. +[clinic start generated code]*/ + +static PyObject * +pysqlite_cursor_setinputsizes(pysqlite_Cursor *self, PyObject *sizes) +/*[clinic end generated code: output=893c817afe9d08ad input=de7950a3aec79bdf]*/ +{ + Py_RETURN_NONE; +} + +/*[clinic input] +_sqlite3.Cursor.setoutputsize as pysqlite_cursor_setoutputsize + + size: object + column: object = None + / + +Required by DB-API. Does nothing in sqlite3. +[clinic start generated code]*/ + +static PyObject * +pysqlite_cursor_setoutputsize_impl(pysqlite_Cursor *self, PyObject *size, + PyObject *column) +/*[clinic end generated code: output=018d7e9129d45efe input=607a6bece8bbb273]*/ { - /* don't care, return None */ Py_RETURN_NONE; } -PyObject* pysqlite_cursor_close(pysqlite_Cursor* self, PyObject* args) +/*[clinic input] +_sqlite3.Cursor.close as pysqlite_cursor_close + +Closes the cursor. +[clinic start generated code]*/ + +static PyObject * +pysqlite_cursor_close_impl(pysqlite_Cursor *self) +/*[clinic end generated code: output=b6055e4ec6fe63b6 input=08b36552dbb9a986]*/ { if (!self->connection) { PyErr_SetString(pysqlite_ProgrammingError, @@ -877,24 +993,15 @@ PyObject* pysqlite_cursor_close(pysqlite_Cursor* self, PyObject* args) } static PyMethodDef cursor_methods[] = { - {"execute", (PyCFunction)pysqlite_cursor_execute, METH_VARARGS, - PyDoc_STR("Executes an SQL statement.")}, - {"executemany", (PyCFunction)pysqlite_cursor_executemany, METH_VARARGS, - PyDoc_STR("Repeatedly executes an SQL statement.")}, - {"executescript", (PyCFunction)pysqlite_cursor_executescript, METH_VARARGS, - PyDoc_STR("Executes multiple SQL statements at once.")}, - {"fetchone", (PyCFunction)pysqlite_cursor_fetchone, METH_NOARGS, - PyDoc_STR("Fetches one row from the resultset.")}, - {"fetchmany", (PyCFunction)(void(*)(void))pysqlite_cursor_fetchmany, METH_VARARGS|METH_KEYWORDS, - PyDoc_STR("Fetches several rows from the resultset.")}, - {"fetchall", (PyCFunction)pysqlite_cursor_fetchall, METH_NOARGS, - PyDoc_STR("Fetches all rows from the resultset.")}, - {"close", (PyCFunction)pysqlite_cursor_close, METH_NOARGS, - PyDoc_STR("Closes the cursor.")}, - {"setinputsizes", (PyCFunction)pysqlite_noop, METH_VARARGS, - PyDoc_STR("Required by DB-API. Does nothing in sqlite3.")}, - {"setoutputsize", (PyCFunction)pysqlite_noop, METH_VARARGS, - PyDoc_STR("Required by DB-API. Does nothing in sqlite3.")}, + PYSQLITE_CURSOR_CLOSE_METHODDEF + PYSQLITE_CURSOR_EXECUTEMANY_METHODDEF + PYSQLITE_CURSOR_EXECUTESCRIPT_METHODDEF + PYSQLITE_CURSOR_EXECUTE_METHODDEF + PYSQLITE_CURSOR_FETCHALL_METHODDEF + PYSQLITE_CURSOR_FETCHMANY_METHODDEF + PYSQLITE_CURSOR_FETCHONE_METHODDEF + PYSQLITE_CURSOR_SETINPUTSIZES_METHODDEF + PYSQLITE_CURSOR_SETOUTPUTSIZE_METHODDEF {NULL, NULL} }; @@ -906,56 +1013,42 @@ static struct PyMemberDef cursor_members[] = {"lastrowid", T_OBJECT, offsetof(pysqlite_Cursor, lastrowid), READONLY}, {"rowcount", T_LONG, offsetof(pysqlite_Cursor, rowcount), READONLY}, {"row_factory", T_OBJECT, offsetof(pysqlite_Cursor, row_factory), 0}, + {"__weaklistoffset__", T_PYSSIZET, offsetof(pysqlite_Cursor, in_weakreflist), READONLY}, {NULL} }; static const char cursor_doc[] = PyDoc_STR("SQLite database cursor class."); -PyTypeObject pysqlite_CursorType = { - PyVarObject_HEAD_INIT(NULL, 0) - MODULE_NAME ".Cursor", /* tp_name */ - sizeof(pysqlite_Cursor), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)pysqlite_cursor_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ - cursor_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(pysqlite_Cursor, in_weakreflist), /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)pysqlite_cursor_iternext, /* tp_iternext */ - cursor_methods, /* tp_methods */ - cursor_members, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)pysqlite_cursor_init, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0 /* tp_free */ +static PyType_Slot cursor_slots[] = { + {Py_tp_dealloc, cursor_dealloc}, + {Py_tp_doc, (void *)cursor_doc}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, pysqlite_cursor_iternext}, + {Py_tp_methods, cursor_methods}, + {Py_tp_members, cursor_members}, + {Py_tp_init, pysqlite_cursor_init}, + {Py_tp_traverse, cursor_traverse}, + {Py_tp_clear, cursor_clear}, + {0, NULL}, }; -extern int pysqlite_cursor_setup_types(void) +static PyType_Spec cursor_spec = { + .name = MODULE_NAME ".Cursor", + .basicsize = sizeof(pysqlite_Cursor), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), + .slots = cursor_slots, +}; + +PyTypeObject *pysqlite_CursorType = NULL; + +int +pysqlite_cursor_setup_types(PyObject *module) { - pysqlite_CursorType.tp_new = PyType_GenericNew; - return PyType_Ready(&pysqlite_CursorType); + pysqlite_CursorType = (PyTypeObject *)PyType_FromModuleAndSpec(module, &cursor_spec, NULL); + if (pysqlite_CursorType == NULL) { + return -1; + } + return 0; } diff --git a/contrib/tools/python3/src/Modules/_sqlite/cursor.h b/contrib/tools/python3/src/Modules/_sqlite/cursor.h index 4a20e756f7..b26b288674 100644 --- a/contrib/tools/python3/src/Modules/_sqlite/cursor.h +++ b/contrib/tools/python3/src/Modules/_sqlite/cursor.h @@ -52,19 +52,9 @@ typedef struct PyObject* in_weakreflist; /* List of weak references */ } pysqlite_Cursor; -extern PyTypeObject pysqlite_CursorType; +extern PyTypeObject *pysqlite_CursorType; -PyObject* pysqlite_cursor_execute(pysqlite_Cursor* self, PyObject* args); -PyObject* pysqlite_cursor_executemany(pysqlite_Cursor* self, PyObject* args); -PyObject* pysqlite_cursor_getiter(pysqlite_Cursor *self); -PyObject* pysqlite_cursor_iternext(pysqlite_Cursor *self); -PyObject* pysqlite_cursor_fetchone(pysqlite_Cursor* self, PyObject* args); -PyObject* pysqlite_cursor_fetchmany(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs); -PyObject* pysqlite_cursor_fetchall(pysqlite_Cursor* self, PyObject* args); -PyObject* pysqlite_noop(pysqlite_Connection* self, PyObject* args); -PyObject* pysqlite_cursor_close(pysqlite_Cursor* self, PyObject* args); - -int pysqlite_cursor_setup_types(void); +int pysqlite_cursor_setup_types(PyObject *module); #define UNKNOWN (-1) #endif diff --git a/contrib/tools/python3/src/Modules/_sqlite/microprotocols.c b/contrib/tools/python3/src/Modules/_sqlite/microprotocols.c index 3b2d7f42b8..e219a7239f 100644 --- a/contrib/tools/python3/src/Modules/_sqlite/microprotocols.c +++ b/contrib/tools/python3/src/Modules/_sqlite/microprotocols.c @@ -29,7 +29,6 @@ #include "microprotocols.h" #include "prepare_protocol.h" - /** the adapters registry **/ static PyObject *psyco_adapters = NULL; @@ -37,14 +36,17 @@ static PyObject *psyco_adapters = NULL; /* pysqlite_microprotocols_init - initialize the adapters dictionary */ int -pysqlite_microprotocols_init(PyObject *dict) +pysqlite_microprotocols_init(PyObject *module) { /* create adapters dictionary and put it in module namespace */ if ((psyco_adapters = PyDict_New()) == NULL) { return -1; } - return PyDict_SetItemString(dict, "adapters", psyco_adapters); + int res = PyModule_AddObjectRef(module, "adapters", psyco_adapters); + Py_DECREF(psyco_adapters); + + return res; } @@ -56,7 +58,7 @@ pysqlite_microprotocols_add(PyTypeObject *type, PyObject *proto, PyObject *cast) PyObject* key; int rc; - if (proto == NULL) proto = (PyObject*)&pysqlite_PrepareProtocolType; + if (proto == NULL) proto = (PyObject*)pysqlite_PrepareProtocolType; key = Py_BuildValue("(OO)", (PyObject*)type, proto); if (!key) { @@ -138,22 +140,9 @@ pysqlite_microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt) } if (alt) { - Py_INCREF(alt); - return alt; + return Py_NewRef(alt); } /* else set the right exception and return NULL */ PyErr_SetString(pysqlite_ProgrammingError, "can't adapt"); return NULL; } - -/** module-level functions **/ - -PyObject * -pysqlite_adapt(pysqlite_Cursor *self, PyObject *args) -{ - PyObject *obj, *alt = NULL; - PyObject *proto = (PyObject*)&pysqlite_PrepareProtocolType; - - if (!PyArg_ParseTuple(args, "O|OO", &obj, &proto, &alt)) return NULL; - return pysqlite_microprotocols_adapt(obj, proto, alt); -} diff --git a/contrib/tools/python3/src/Modules/_sqlite/microprotocols.h b/contrib/tools/python3/src/Modules/_sqlite/microprotocols.h index 68c18d9355..e9adef916e 100644 --- a/contrib/tools/python3/src/Modules/_sqlite/microprotocols.h +++ b/contrib/tools/python3/src/Modules/_sqlite/microprotocols.h @@ -38,15 +38,10 @@ /** exported functions **/ /* used by module.c to init the microprotocols system */ -extern int pysqlite_microprotocols_init(PyObject *dict); +extern int pysqlite_microprotocols_init(PyObject *module); extern int pysqlite_microprotocols_add( PyTypeObject *type, PyObject *proto, PyObject *cast); extern PyObject *pysqlite_microprotocols_adapt( PyObject *obj, PyObject *proto, PyObject *alt); -extern PyObject * - pysqlite_adapt(pysqlite_Cursor* self, PyObject *args); -#define pysqlite_adapt_doc \ - "adapt(obj, protocol, alternate) -> adapt obj to given protocol." - #endif /* !defined(PSYCOPG_MICROPROTOCOLS_H) */ diff --git a/contrib/tools/python3/src/Modules/_sqlite/module.c b/contrib/tools/python3/src/Modules/_sqlite/module.c index 98909369e7..8cff4e224d 100644 --- a/contrib/tools/python3/src/Modules/_sqlite/module.c +++ b/contrib/tools/python3/src/Modules/_sqlite/module.c @@ -29,10 +29,16 @@ #include "microprotocols.h" #include "row.h" -#if SQLITE_VERSION_NUMBER >= 3003003 -#define HAVE_SHARED_CACHE +#if SQLITE_VERSION_NUMBER < 3007015 +#error "SQLite 3.7.15 or higher required" #endif +#include "clinic/module.c.h" +/*[clinic input] +module _sqlite3 +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=81e330492d57488e]*/ + /* static objects at module-level */ PyObject *pysqlite_Error = NULL; @@ -80,7 +86,7 @@ static PyObject* module_connect(PyObject* self, PyObject* args, PyObject* } if (factory == NULL) { - factory = (PyObject*)&pysqlite_ConnectionType; + factory = (PyObject*)pysqlite_ConnectionType; } return PyObject_Call(factory, args, kwargs); @@ -94,48 +100,44 @@ Opens a connection to the SQLite database file *database*. You can use\n\ \":memory:\" to open a database connection to a database that resides in\n\ RAM instead of on disk."); -static PyObject* module_complete(PyObject* self, PyObject* args, PyObject* - kwargs) -{ - static char *kwlist[] = {"statement", NULL}; - char* statement; +/*[clinic input] +_sqlite3.complete_statement as pysqlite_complete_statement - PyObject* result; + statement: str - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &statement)) - { - return NULL; - } +Checks if a string contains a complete SQL statement. +[clinic start generated code]*/ +static PyObject * +pysqlite_complete_statement_impl(PyObject *module, const char *statement) +/*[clinic end generated code: output=e55f1ff1952df558 input=ac45d257375bb828]*/ +{ if (sqlite3_complete(statement)) { - result = Py_True; + return Py_NewRef(Py_True); } else { - result = Py_False; + return Py_NewRef(Py_False); } +} - Py_INCREF(result); +/*[clinic input] +_sqlite3.enable_shared_cache as pysqlite_enable_shared_cache - return result; -} + do_enable: int -PyDoc_STRVAR(module_complete_doc, -"complete_statement(sql)\n\ -\n\ -Checks if a string contains a complete SQL statement."); +Enable or disable shared cache mode for the calling thread. -#ifdef HAVE_SHARED_CACHE -static PyObject* module_enable_shared_cache(PyObject* self, PyObject* args, PyObject* - kwargs) +This method is deprecated and will be removed in Python 3.12. +Shared cache is strongly discouraged by the SQLite 3 documentation. +If shared cache must be used, open the database in URI mode using +the cache=shared query parameter. +[clinic start generated code]*/ + +static PyObject * +pysqlite_enable_shared_cache_impl(PyObject *module, int do_enable) +/*[clinic end generated code: output=259c74eedee1516b input=26e40d5971d3487d]*/ { - static char *kwlist[] = {"do_enable", NULL}; - int do_enable; int rc; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &do_enable)) - { - return NULL; - } - rc = sqlite3_enable_shared_cache(do_enable); if (rc != SQLITE_OK) { @@ -146,22 +148,23 @@ static PyObject* module_enable_shared_cache(PyObject* self, PyObject* args, PyOb } } -PyDoc_STRVAR(module_enable_shared_cache_doc, -"enable_shared_cache(do_enable)\n\ -\n\ -Enable or disable shared cache mode for the calling thread."); -#endif /* HAVE_SHARED_CACHE */ +/*[clinic input] +_sqlite3.register_adapter as pysqlite_register_adapter + + type: object(type='PyTypeObject *') + caster: object + / + +Registers an adapter with sqlite3's adapter registry. +[clinic start generated code]*/ -static PyObject* module_register_adapter(PyObject* self, PyObject* args) +static PyObject * +pysqlite_register_adapter_impl(PyObject *module, PyTypeObject *type, + PyObject *caster) +/*[clinic end generated code: output=a287e8db18e8af23 input=b4bd87afcadc535d]*/ { - PyTypeObject* type; - PyObject* caster; int rc; - if (!PyArg_ParseTuple(args, "OO", &type, &caster)) { - return NULL; - } - /* a basic type is adapted; there's a performance optimization if that's not the case * (99 % of all usages) */ if (type == &PyLong_Type || type == &PyFloat_Type @@ -169,30 +172,32 @@ static PyObject* module_register_adapter(PyObject* self, PyObject* args) pysqlite_BaseTypeAdapted = 1; } - rc = pysqlite_microprotocols_add(type, (PyObject*)&pysqlite_PrepareProtocolType, caster); + rc = pysqlite_microprotocols_add(type, (PyObject*)pysqlite_PrepareProtocolType, caster); if (rc == -1) return NULL; Py_RETURN_NONE; } -PyDoc_STRVAR(module_register_adapter_doc, -"register_adapter(type, callable)\n\ -\n\ -Registers an adapter with sqlite3's adapter registry."); +/*[clinic input] +_sqlite3.register_converter as pysqlite_register_converter + + name as orig_name: unicode + converter as callable: object + / + +Registers a converter with sqlite3. +[clinic start generated code]*/ -static PyObject* module_register_converter(PyObject* self, PyObject* args) +static PyObject * +pysqlite_register_converter_impl(PyObject *module, PyObject *orig_name, + PyObject *callable) +/*[clinic end generated code: output=a2f2bfeed7230062 input=90f645419425d6c4]*/ { - PyObject* orig_name; PyObject* name = NULL; - PyObject* callable; PyObject* retval = NULL; _Py_IDENTIFIER(upper); - if (!PyArg_ParseTuple(args, "UO", &orig_name, &callable)) { - return NULL; - } - /* convert the name to upper case */ name = _PyObject_CallMethodIdNoArgs(orig_name, &PyId_upper); if (!name) { @@ -203,127 +208,127 @@ static PyObject* module_register_converter(PyObject* self, PyObject* args) goto error; } - Py_INCREF(Py_None); - retval = Py_None; + retval = Py_NewRef(Py_None); error: Py_XDECREF(name); return retval; } -PyDoc_STRVAR(module_register_converter_doc, -"register_converter(typename, callable)\n\ -\n\ -Registers a converter with sqlite3."); +/*[clinic input] +_sqlite3.enable_callback_tracebacks as pysqlite_enable_callback_trace -static PyObject* enable_callback_tracebacks(PyObject* self, PyObject* args) + enable: int + / + +Enable or disable callback functions throwing errors to stderr. +[clinic start generated code]*/ + +static PyObject * +pysqlite_enable_callback_trace_impl(PyObject *module, int enable) +/*[clinic end generated code: output=4ff1d051c698f194 input=cb79d3581eb77c40]*/ { - if (!PyArg_ParseTuple(args, "i", &_pysqlite_enable_callback_tracebacks)) { - return NULL; - } + _pysqlite_enable_callback_tracebacks = enable; Py_RETURN_NONE; } -PyDoc_STRVAR(enable_callback_tracebacks_doc, -"enable_callback_tracebacks(flag)\n\ -\n\ -Enable or disable callback functions throwing errors to stderr."); +/*[clinic input] +_sqlite3.adapt as pysqlite_adapt + + obj: object + proto: object(c_default='(PyObject*)pysqlite_PrepareProtocolType') = PrepareProtocolType + alt: object = NULL + / -static void converters_init(PyObject* dict) +Adapt given object to given protocol. +[clinic start generated code]*/ + +static PyObject * +pysqlite_adapt_impl(PyObject *module, PyObject *obj, PyObject *proto, + PyObject *alt) +/*[clinic end generated code: output=0c3927c5fcd23dd9 input=46ca9564710ba48a]*/ +{ + return pysqlite_microprotocols_adapt(obj, proto, alt); +} + +static int converters_init(PyObject* module) { _pysqlite_converters = PyDict_New(); if (!_pysqlite_converters) { - return; + return -1; } - PyDict_SetItemString(dict, "converters", _pysqlite_converters); + int res = PyModule_AddObjectRef(module, "converters", _pysqlite_converters); + Py_DECREF(_pysqlite_converters); + + return res; } static PyMethodDef module_methods[] = { {"connect", (PyCFunction)(void(*)(void))module_connect, METH_VARARGS | METH_KEYWORDS, module_connect_doc}, - {"complete_statement", (PyCFunction)(void(*)(void))module_complete, - METH_VARARGS | METH_KEYWORDS, module_complete_doc}, -#ifdef HAVE_SHARED_CACHE - {"enable_shared_cache", (PyCFunction)(void(*)(void))module_enable_shared_cache, - METH_VARARGS | METH_KEYWORDS, module_enable_shared_cache_doc}, -#endif - {"register_adapter", (PyCFunction)module_register_adapter, - METH_VARARGS, module_register_adapter_doc}, - {"register_converter", (PyCFunction)module_register_converter, - METH_VARARGS, module_register_converter_doc}, - {"adapt", (PyCFunction)pysqlite_adapt, METH_VARARGS, - pysqlite_adapt_doc}, - {"enable_callback_tracebacks", (PyCFunction)enable_callback_tracebacks, - METH_VARARGS, enable_callback_tracebacks_doc}, + PYSQLITE_ADAPT_METHODDEF + PYSQLITE_COMPLETE_STATEMENT_METHODDEF + PYSQLITE_ENABLE_CALLBACK_TRACE_METHODDEF + PYSQLITE_ENABLE_SHARED_CACHE_METHODDEF + PYSQLITE_REGISTER_ADAPTER_METHODDEF + PYSQLITE_REGISTER_CONVERTER_METHODDEF {NULL, NULL} }; -struct _IntConstantPair { - const char *constant_name; - int constant_value; -}; - -typedef struct _IntConstantPair IntConstantPair; - -static const IntConstantPair _int_constants[] = { - {"PARSE_DECLTYPES", PARSE_DECLTYPES}, - {"PARSE_COLNAMES", PARSE_COLNAMES}, - - {"SQLITE_OK", SQLITE_OK}, - {"SQLITE_DENY", SQLITE_DENY}, - {"SQLITE_IGNORE", SQLITE_IGNORE}, - {"SQLITE_CREATE_INDEX", SQLITE_CREATE_INDEX}, - {"SQLITE_CREATE_TABLE", SQLITE_CREATE_TABLE}, - {"SQLITE_CREATE_TEMP_INDEX", SQLITE_CREATE_TEMP_INDEX}, - {"SQLITE_CREATE_TEMP_TABLE", SQLITE_CREATE_TEMP_TABLE}, - {"SQLITE_CREATE_TEMP_TRIGGER", SQLITE_CREATE_TEMP_TRIGGER}, - {"SQLITE_CREATE_TEMP_VIEW", SQLITE_CREATE_TEMP_VIEW}, - {"SQLITE_CREATE_TRIGGER", SQLITE_CREATE_TRIGGER}, - {"SQLITE_CREATE_VIEW", SQLITE_CREATE_VIEW}, - {"SQLITE_DELETE", SQLITE_DELETE}, - {"SQLITE_DROP_INDEX", SQLITE_DROP_INDEX}, - {"SQLITE_DROP_TABLE", SQLITE_DROP_TABLE}, - {"SQLITE_DROP_TEMP_INDEX", SQLITE_DROP_TEMP_INDEX}, - {"SQLITE_DROP_TEMP_TABLE", SQLITE_DROP_TEMP_TABLE}, - {"SQLITE_DROP_TEMP_TRIGGER", SQLITE_DROP_TEMP_TRIGGER}, - {"SQLITE_DROP_TEMP_VIEW", SQLITE_DROP_TEMP_VIEW}, - {"SQLITE_DROP_TRIGGER", SQLITE_DROP_TRIGGER}, - {"SQLITE_DROP_VIEW", SQLITE_DROP_VIEW}, - {"SQLITE_INSERT", SQLITE_INSERT}, - {"SQLITE_PRAGMA", SQLITE_PRAGMA}, - {"SQLITE_READ", SQLITE_READ}, - {"SQLITE_SELECT", SQLITE_SELECT}, - {"SQLITE_TRANSACTION", SQLITE_TRANSACTION}, - {"SQLITE_UPDATE", SQLITE_UPDATE}, - {"SQLITE_ATTACH", SQLITE_ATTACH}, - {"SQLITE_DETACH", SQLITE_DETACH}, -#if SQLITE_VERSION_NUMBER >= 3002001 - {"SQLITE_ALTER_TABLE", SQLITE_ALTER_TABLE}, - {"SQLITE_REINDEX", SQLITE_REINDEX}, -#endif -#if SQLITE_VERSION_NUMBER >= 3003000 - {"SQLITE_ANALYZE", SQLITE_ANALYZE}, -#endif -#if SQLITE_VERSION_NUMBER >= 3003007 - {"SQLITE_CREATE_VTABLE", SQLITE_CREATE_VTABLE}, - {"SQLITE_DROP_VTABLE", SQLITE_DROP_VTABLE}, -#endif -#if SQLITE_VERSION_NUMBER >= 3003008 - {"SQLITE_FUNCTION", SQLITE_FUNCTION}, -#endif -#if SQLITE_VERSION_NUMBER >= 3006008 - {"SQLITE_SAVEPOINT", SQLITE_SAVEPOINT}, -#endif +static int +add_integer_constants(PyObject *module) { +#define ADD_INT(ival) \ + do { \ + if (PyModule_AddIntConstant(module, #ival, ival) < 0) { \ + return -1; \ + } \ + } while (0); \ + + ADD_INT(PARSE_DECLTYPES); + ADD_INT(PARSE_COLNAMES); + ADD_INT(SQLITE_OK); + ADD_INT(SQLITE_DENY); + ADD_INT(SQLITE_IGNORE); + ADD_INT(SQLITE_CREATE_INDEX); + ADD_INT(SQLITE_CREATE_TABLE); + ADD_INT(SQLITE_CREATE_TEMP_INDEX); + ADD_INT(SQLITE_CREATE_TEMP_TABLE); + ADD_INT(SQLITE_CREATE_TEMP_TRIGGER); + ADD_INT(SQLITE_CREATE_TEMP_VIEW); + ADD_INT(SQLITE_CREATE_TRIGGER); + ADD_INT(SQLITE_CREATE_VIEW); + ADD_INT(SQLITE_DELETE); + ADD_INT(SQLITE_DROP_INDEX); + ADD_INT(SQLITE_DROP_TABLE); + ADD_INT(SQLITE_DROP_TEMP_INDEX); + ADD_INT(SQLITE_DROP_TEMP_TABLE); + ADD_INT(SQLITE_DROP_TEMP_TRIGGER); + ADD_INT(SQLITE_DROP_TEMP_VIEW); + ADD_INT(SQLITE_DROP_TRIGGER); + ADD_INT(SQLITE_DROP_VIEW); + ADD_INT(SQLITE_INSERT); + ADD_INT(SQLITE_PRAGMA); + ADD_INT(SQLITE_READ); + ADD_INT(SQLITE_SELECT); + ADD_INT(SQLITE_TRANSACTION); + ADD_INT(SQLITE_UPDATE); + ADD_INT(SQLITE_ATTACH); + ADD_INT(SQLITE_DETACH); + ADD_INT(SQLITE_ALTER_TABLE); + ADD_INT(SQLITE_REINDEX); + ADD_INT(SQLITE_ANALYZE); + ADD_INT(SQLITE_CREATE_VTABLE); + ADD_INT(SQLITE_DROP_VTABLE); + ADD_INT(SQLITE_FUNCTION); + ADD_INT(SQLITE_SAVEPOINT); #if SQLITE_VERSION_NUMBER >= 3008003 - {"SQLITE_RECURSIVE", SQLITE_RECURSIVE}, -#endif -#if SQLITE_VERSION_NUMBER >= 3006011 - {"SQLITE_DONE", SQLITE_DONE}, + ADD_INT(SQLITE_RECURSIVE); #endif - {(char*)NULL, 0} -}; - + ADD_INT(SQLITE_DONE); +#undef ADD_INT + return 0; +} static struct PyModuleDef _sqlite3module = { PyModuleDef_HEAD_INIT, @@ -340,138 +345,100 @@ static struct PyModuleDef _sqlite3module = { #define ADD_TYPE(module, type) \ do { \ if (PyModule_AddType(module, &type) < 0) { \ - Py_DECREF(module); \ - return NULL; \ + goto error; \ } \ } while (0) +#define ADD_EXCEPTION(module, name, exc, base) \ +do { \ + exc = PyErr_NewException(MODULE_NAME "." name, base, NULL); \ + if (!exc) { \ + goto error; \ + } \ + int res = PyModule_AddObjectRef(module, name, exc); \ + Py_DECREF(exc); \ + if (res < 0) { \ + goto error; \ + } \ +} while (0) + PyMODINIT_FUNC PyInit__sqlite3(void) { - PyObject *module, *dict; - PyObject *tmp_obj; - int i; + PyObject *module; - module = PyModule_Create(&_sqlite3module); - - if (!module || - (pysqlite_row_setup_types() < 0) || - (pysqlite_cursor_setup_types() < 0) || - (pysqlite_connection_setup_types() < 0) || - (pysqlite_cache_setup_types() < 0) || - (pysqlite_statement_setup_types() < 0) || - (pysqlite_prepare_protocol_setup_types() < 0) - ) { - Py_XDECREF(module); + if (sqlite3_libversion_number() < 3007015) { + PyErr_SetString(PyExc_ImportError, MODULE_NAME ": SQLite 3.7.15 or higher required"); return NULL; } - ADD_TYPE(module, pysqlite_ConnectionType); - ADD_TYPE(module, pysqlite_CursorType); - ADD_TYPE(module, pysqlite_PrepareProtocolType); - ADD_TYPE(module, pysqlite_RowType); - - if (!(dict = PyModule_GetDict(module))) { - goto error; + int rc = sqlite3_initialize(); + if (rc != SQLITE_OK) { + PyErr_SetString(PyExc_ImportError, sqlite3_errstr(rc)); + return NULL; } - /*** Create DB-API Exception hierarchy */ - - if (!(pysqlite_Error = PyErr_NewException(MODULE_NAME ".Error", PyExc_Exception, NULL))) { - goto error; - } - PyDict_SetItemString(dict, "Error", pysqlite_Error); + module = PyModule_Create(&_sqlite3module); - if (!(pysqlite_Warning = PyErr_NewException(MODULE_NAME ".Warning", PyExc_Exception, NULL))) { + if (!module || + (pysqlite_row_setup_types(module) < 0) || + (pysqlite_cursor_setup_types(module) < 0) || + (pysqlite_connection_setup_types(module) < 0) || + (pysqlite_cache_setup_types(module) < 0) || + (pysqlite_statement_setup_types(module) < 0) || + (pysqlite_prepare_protocol_setup_types(module) < 0) + ) { goto error; } - PyDict_SetItemString(dict, "Warning", pysqlite_Warning); - /* Error subclasses */ + ADD_TYPE(module, *pysqlite_ConnectionType); + ADD_TYPE(module, *pysqlite_CursorType); + ADD_TYPE(module, *pysqlite_PrepareProtocolType); + ADD_TYPE(module, *pysqlite_RowType); - if (!(pysqlite_InterfaceError = PyErr_NewException(MODULE_NAME ".InterfaceError", pysqlite_Error, NULL))) { - goto error; - } - PyDict_SetItemString(dict, "InterfaceError", pysqlite_InterfaceError); + /*** Create DB-API Exception hierarchy */ + ADD_EXCEPTION(module, "Error", pysqlite_Error, PyExc_Exception); + ADD_EXCEPTION(module, "Warning", pysqlite_Warning, PyExc_Exception); - if (!(pysqlite_DatabaseError = PyErr_NewException(MODULE_NAME ".DatabaseError", pysqlite_Error, NULL))) { - goto error; - } - PyDict_SetItemString(dict, "DatabaseError", pysqlite_DatabaseError); + /* Error subclasses */ + ADD_EXCEPTION(module, "InterfaceError", pysqlite_InterfaceError, pysqlite_Error); + ADD_EXCEPTION(module, "DatabaseError", pysqlite_DatabaseError, pysqlite_Error); /* pysqlite_DatabaseError subclasses */ + ADD_EXCEPTION(module, "InternalError", pysqlite_InternalError, pysqlite_DatabaseError); + ADD_EXCEPTION(module, "OperationalError", pysqlite_OperationalError, pysqlite_DatabaseError); + ADD_EXCEPTION(module, "ProgrammingError", pysqlite_ProgrammingError, pysqlite_DatabaseError); + ADD_EXCEPTION(module, "IntegrityError", pysqlite_IntegrityError, pysqlite_DatabaseError); + ADD_EXCEPTION(module, "DataError", pysqlite_DataError, pysqlite_DatabaseError); + ADD_EXCEPTION(module, "NotSupportedError", pysqlite_NotSupportedError, pysqlite_DatabaseError); - if (!(pysqlite_InternalError = PyErr_NewException(MODULE_NAME ".InternalError", pysqlite_DatabaseError, NULL))) { - goto error; - } - PyDict_SetItemString(dict, "InternalError", pysqlite_InternalError); - - if (!(pysqlite_OperationalError = PyErr_NewException(MODULE_NAME ".OperationalError", pysqlite_DatabaseError, NULL))) { - goto error; - } - PyDict_SetItemString(dict, "OperationalError", pysqlite_OperationalError); - - if (!(pysqlite_ProgrammingError = PyErr_NewException(MODULE_NAME ".ProgrammingError", pysqlite_DatabaseError, NULL))) { - goto error; - } - PyDict_SetItemString(dict, "ProgrammingError", pysqlite_ProgrammingError); - - if (!(pysqlite_IntegrityError = PyErr_NewException(MODULE_NAME ".IntegrityError", pysqlite_DatabaseError,NULL))) { + /* Set integer constants */ + if (add_integer_constants(module) < 0) { goto error; } - PyDict_SetItemString(dict, "IntegrityError", pysqlite_IntegrityError); - if (!(pysqlite_DataError = PyErr_NewException(MODULE_NAME ".DataError", pysqlite_DatabaseError, NULL))) { + if (PyModule_AddStringConstant(module, "version", PYSQLITE_VERSION) < 0) { goto error; } - PyDict_SetItemString(dict, "DataError", pysqlite_DataError); - if (!(pysqlite_NotSupportedError = PyErr_NewException(MODULE_NAME ".NotSupportedError", pysqlite_DatabaseError, NULL))) { + if (PyModule_AddStringConstant(module, "sqlite_version", sqlite3_libversion())) { goto error; } - PyDict_SetItemString(dict, "NotSupportedError", pysqlite_NotSupportedError); - - /* In Python 2.x, setting Connection.text_factory to - OptimizedUnicode caused Unicode objects to be returned for - non-ASCII data and bytestrings to be returned for ASCII data. - Now OptimizedUnicode is an alias for str, so it has no - effect. */ - Py_INCREF((PyObject*)&PyUnicode_Type); - PyDict_SetItemString(dict, "OptimizedUnicode", (PyObject*)&PyUnicode_Type); - - /* Set integer constants */ - for (i = 0; _int_constants[i].constant_name != NULL; i++) { - tmp_obj = PyLong_FromLong(_int_constants[i].constant_value); - if (!tmp_obj) { - goto error; - } - PyDict_SetItemString(dict, _int_constants[i].constant_name, tmp_obj); - Py_DECREF(tmp_obj); - } - if (!(tmp_obj = PyUnicode_FromString(PYSQLITE_VERSION))) { + /* initialize microprotocols layer */ + if (pysqlite_microprotocols_init(module) < 0) { goto error; } - PyDict_SetItemString(dict, "version", tmp_obj); - Py_DECREF(tmp_obj); - if (!(tmp_obj = PyUnicode_FromString(sqlite3_libversion()))) { + /* initialize the default converters */ + if (converters_init(module) < 0) { goto error; } - PyDict_SetItemString(dict, "sqlite_version", tmp_obj); - Py_DECREF(tmp_obj); - - /* initialize microprotocols layer */ - pysqlite_microprotocols_init(dict); - /* initialize the default converters */ - converters_init(dict); + return module; error: - if (PyErr_Occurred()) - { - PyErr_SetString(PyExc_ImportError, MODULE_NAME ": init failed"); - Py_DECREF(module); - module = NULL; - } - return module; + sqlite3_shutdown(); + PyErr_SetString(PyExc_ImportError, MODULE_NAME ": init failed"); + Py_XDECREF(module); + return NULL; } diff --git a/contrib/tools/python3/src/Modules/_sqlite/module.h b/contrib/tools/python3/src/Modules/_sqlite/module.h index 3185ec9788..9aede92ea3 100644 --- a/contrib/tools/python3/src/Modules/_sqlite/module.h +++ b/contrib/tools/python3/src/Modules/_sqlite/module.h @@ -27,6 +27,7 @@ #include "Python.h" #define PYSQLITE_VERSION "2.6.0" +#define MODULE_NAME "sqlite3" extern PyObject* pysqlite_Error; extern PyObject* pysqlite_Warning; diff --git a/contrib/tools/python3/src/Modules/_sqlite/prepare_protocol.c b/contrib/tools/python3/src/Modules/_sqlite/prepare_protocol.c index 05a2ca5a65..800eef8794 100644 --- a/contrib/tools/python3/src/Modules/_sqlite/prepare_protocol.c +++ b/contrib/tools/python3/src/Modules/_sqlite/prepare_protocol.c @@ -23,61 +23,52 @@ #include "prepare_protocol.h" -int pysqlite_prepare_protocol_init(pysqlite_PrepareProtocol* self, PyObject* args, PyObject* kwargs) +static int +pysqlite_prepare_protocol_init(pysqlite_PrepareProtocol *self, PyObject *args, + PyObject *kwargs) { return 0; } -void pysqlite_prepare_protocol_dealloc(pysqlite_PrepareProtocol* self) +static int +pysqlite_prepare_protocol_traverse(PyObject *self, visitproc visit, void *arg) { - Py_TYPE(self)->tp_free((PyObject*)self); + Py_VISIT(Py_TYPE(self)); + return 0; +} + +static void +pysqlite_prepare_protocol_dealloc(pysqlite_PrepareProtocol *self) +{ + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); + tp->tp_free(self); + Py_DECREF(tp); } -PyTypeObject pysqlite_PrepareProtocolType= { - PyVarObject_HEAD_INIT(NULL, 0) - MODULE_NAME ".PrepareProtocol", /* tp_name */ - sizeof(pysqlite_PrepareProtocol), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)pysqlite_prepare_protocol_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)pysqlite_prepare_protocol_init, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0 /* tp_free */ +static PyType_Slot type_slots[] = { + {Py_tp_dealloc, pysqlite_prepare_protocol_dealloc}, + {Py_tp_init, pysqlite_prepare_protocol_init}, + {Py_tp_traverse, pysqlite_prepare_protocol_traverse}, + {0, NULL}, }; -extern int pysqlite_prepare_protocol_setup_types(void) +static PyType_Spec type_spec = { + .name = MODULE_NAME ".PrepareProtocol", + .basicsize = sizeof(pysqlite_PrepareProtocol), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = type_slots, +}; + +PyTypeObject *pysqlite_PrepareProtocolType = NULL; + +int +pysqlite_prepare_protocol_setup_types(PyObject *module) { - pysqlite_PrepareProtocolType.tp_new = PyType_GenericNew; - Py_SET_TYPE(&pysqlite_PrepareProtocolType, &PyType_Type); - return PyType_Ready(&pysqlite_PrepareProtocolType); + pysqlite_PrepareProtocolType = (PyTypeObject *)PyType_FromModuleAndSpec(module, &type_spec, NULL); + if (pysqlite_PrepareProtocolType == NULL) { + return -1; + } + return 0; } diff --git a/contrib/tools/python3/src/Modules/_sqlite/prepare_protocol.h b/contrib/tools/python3/src/Modules/_sqlite/prepare_protocol.h index 3998a55e51..593961331c 100644 --- a/contrib/tools/python3/src/Modules/_sqlite/prepare_protocol.h +++ b/contrib/tools/python3/src/Modules/_sqlite/prepare_protocol.h @@ -23,20 +23,16 @@ #ifndef PYSQLITE_PREPARE_PROTOCOL_H #define PYSQLITE_PREPARE_PROTOCOL_H -#define PY_SSIZE_T_CLEAN -#include "Python.h" +#include "module.h" typedef struct { PyObject_HEAD } pysqlite_PrepareProtocol; -extern PyTypeObject pysqlite_PrepareProtocolType; +extern PyTypeObject *pysqlite_PrepareProtocolType; -int pysqlite_prepare_protocol_init(pysqlite_PrepareProtocol* self, PyObject* args, PyObject* kwargs); -void pysqlite_prepare_protocol_dealloc(pysqlite_PrepareProtocol* self); - -int pysqlite_prepare_protocol_setup_types(void); +int pysqlite_prepare_protocol_setup_types(PyObject *module); #define UNKNOWN (-1) #endif diff --git a/contrib/tools/python3/src/Modules/_sqlite/row.c b/contrib/tools/python3/src/Modules/_sqlite/row.c index 4b47108278..643194df04 100644 --- a/contrib/tools/python3/src/Modules/_sqlite/row.c +++ b/contrib/tools/python3/src/Modules/_sqlite/row.c @@ -23,57 +23,74 @@ #include "row.h" #include "cursor.h" +#include "clinic/row.c.h" -void pysqlite_row_dealloc(pysqlite_Row* self) +/*[clinic input] +module _sqlite3 +class _sqlite3.Row "pysqlite_Row *" "pysqlite_RowType" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=384227da65f250fd]*/ + +static int +row_clear(pysqlite_Row *self) { - Py_XDECREF(self->data); - Py_XDECREF(self->description); + Py_CLEAR(self->data); + Py_CLEAR(self->description); + return 0; +} - Py_TYPE(self)->tp_free((PyObject*)self); +static int +row_traverse(pysqlite_Row *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + Py_VISIT(self->data); + Py_VISIT(self->description); + return 0; } -static PyObject * -pysqlite_row_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +static void +pysqlite_row_dealloc(PyObject *self) { - pysqlite_Row *self; - PyObject* data; - pysqlite_Cursor* cursor; + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); + tp->tp_clear(self); + tp->tp_free(self); + Py_DECREF(tp); +} - assert(type != NULL && type->tp_alloc != NULL); +/*[clinic input] +@classmethod +_sqlite3.Row.__new__ as pysqlite_row_new - if (!_PyArg_NoKeywords("Row", kwargs)) - return NULL; - if (!PyArg_ParseTuple(args, "OO", &cursor, &data)) - return NULL; + cursor: object(type='pysqlite_Cursor *', subclass_of='pysqlite_CursorType') + data: object(subclass_of='&PyTuple_Type') + / - if (!PyObject_TypeCheck((PyObject*)cursor, &pysqlite_CursorType)) { - PyErr_SetString(PyExc_TypeError, "instance of cursor required for first argument"); - return NULL; - } +[clinic start generated code]*/ - if (!PyTuple_Check(data)) { - PyErr_SetString(PyExc_TypeError, "tuple required for second argument"); - return NULL; - } +static PyObject * +pysqlite_row_new_impl(PyTypeObject *type, pysqlite_Cursor *cursor, + PyObject *data) +/*[clinic end generated code: output=10d58b09a819a4c1 input=f6cd7e6e0935828d]*/ +{ + pysqlite_Row *self; + + assert(type != NULL && type->tp_alloc != NULL); self = (pysqlite_Row *) type->tp_alloc(type, 0); if (self == NULL) return NULL; - Py_INCREF(data); - self->data = data; - - Py_INCREF(cursor->description); - self->description = cursor->description; + self->data = Py_NewRef(data); + self->description = Py_NewRef(cursor->description); return (PyObject *) self; } PyObject* pysqlite_row_item(pysqlite_Row* self, Py_ssize_t idx) { - PyObject* item = PyTuple_GetItem(self->data, idx); - Py_XINCREF(item); - return item; + PyObject *item = PyTuple_GetItem(self->data, idx); + return Py_XNewRef(item); } static int @@ -104,11 +121,11 @@ equal_ignore_case(PyObject *left, PyObject *right) return 1; } -PyObject* pysqlite_row_subscript(pysqlite_Row* self, PyObject* idx) +static PyObject * +pysqlite_row_subscript(pysqlite_Row *self, PyObject *idx) { Py_ssize_t _idx; Py_ssize_t nitems, i; - PyObject* item; if (PyLong_Check(idx)) { _idx = PyNumber_AsSsize_t(idx, PyExc_IndexError); @@ -116,9 +133,9 @@ PyObject* pysqlite_row_subscript(pysqlite_Row* self, PyObject* idx) return NULL; if (_idx < 0) _idx += PyTuple_GET_SIZE(self->data); - item = PyTuple_GetItem(self->data, _idx); - Py_XINCREF(item); - return item; + + PyObject *item = PyTuple_GetItem(self->data, _idx); + return Py_XNewRef(item); } else if (PyUnicode_Check(idx)) { nitems = PyTuple_Size(self->description); @@ -132,9 +149,8 @@ PyObject* pysqlite_row_subscript(pysqlite_Row* self, PyObject* idx) } if (eq) { /* found item */ - item = PyTuple_GetItem(self->data, i); - Py_INCREF(item); - return item; + PyObject *item = PyTuple_GetItem(self->data, i); + return Py_XNewRef(item); } } @@ -156,7 +172,15 @@ pysqlite_row_length(pysqlite_Row* self) return PyTuple_GET_SIZE(self->data); } -PyObject* pysqlite_row_keys(pysqlite_Row* self, PyObject *Py_UNUSED(ignored)) +/*[clinic input] +_sqlite3.Row.keys as pysqlite_row_keys + +Returns the keys of the row. +[clinic start generated code]*/ + +static PyObject * +pysqlite_row_keys_impl(pysqlite_Row *self) +/*[clinic end generated code: output=efe3dfb3af6edc07 input=7549a122827c5563]*/ { PyObject* list; Py_ssize_t nitems, i; @@ -192,7 +216,7 @@ static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other, if (opid != Py_EQ && opid != Py_NE) Py_RETURN_NOTIMPLEMENTED; - if (PyObject_TypeCheck(_other, &pysqlite_RowType)) { + if (PyObject_TypeCheck(_other, pysqlite_RowType)) { pysqlite_Row *other = (pysqlite_Row *)_other; int eq = PyObject_RichCompareBool(self->description, other->description, Py_EQ); if (eq < 0) { @@ -206,73 +230,43 @@ static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other, Py_RETURN_NOTIMPLEMENTED; } -PyMappingMethods pysqlite_row_as_mapping = { - /* mp_length */ (lenfunc)pysqlite_row_length, - /* mp_subscript */ (binaryfunc)pysqlite_row_subscript, - /* mp_ass_subscript */ (objobjargproc)0, +static PyMethodDef row_methods[] = { + PYSQLITE_ROW_KEYS_METHODDEF + {NULL, NULL} }; -static PySequenceMethods pysqlite_row_as_sequence = { - /* sq_length */ (lenfunc)pysqlite_row_length, - /* sq_concat */ 0, - /* sq_repeat */ 0, - /* sq_item */ (ssizeargfunc)pysqlite_row_item, +static PyType_Slot row_slots[] = { + {Py_tp_dealloc, pysqlite_row_dealloc}, + {Py_tp_hash, pysqlite_row_hash}, + {Py_tp_methods, row_methods}, + {Py_tp_richcompare, pysqlite_row_richcompare}, + {Py_tp_iter, pysqlite_iter}, + {Py_mp_length, pysqlite_row_length}, + {Py_mp_subscript, pysqlite_row_subscript}, + {Py_sq_length, pysqlite_row_length}, + {Py_sq_item, pysqlite_row_item}, + {Py_tp_new, pysqlite_row_new}, + {Py_tp_traverse, row_traverse}, + {Py_tp_clear, row_clear}, + {0, NULL}, }; - -static PyMethodDef pysqlite_row_methods[] = { - {"keys", (PyCFunction)pysqlite_row_keys, METH_NOARGS, - PyDoc_STR("Returns the keys of the row.")}, - {NULL, NULL} +static PyType_Spec row_spec = { + .name = MODULE_NAME ".Row", + .basicsize = sizeof(pysqlite_Row), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), + .slots = row_slots, }; +PyTypeObject *pysqlite_RowType = NULL; -PyTypeObject pysqlite_RowType = { - PyVarObject_HEAD_INIT(NULL, 0) - MODULE_NAME ".Row", /* tp_name */ - sizeof(pysqlite_Row), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)pysqlite_row_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)pysqlite_row_hash, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ - 0, /* tp_doc */ - (traverseproc)0, /* tp_traverse */ - 0, /* tp_clear */ - (richcmpfunc)pysqlite_row_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - (getiterfunc)pysqlite_iter, /* tp_iter */ - 0, /* tp_iternext */ - pysqlite_row_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0 /* tp_free */ -}; - -extern int pysqlite_row_setup_types(void) +int +pysqlite_row_setup_types(PyObject *module) { - pysqlite_RowType.tp_new = pysqlite_row_new; - pysqlite_RowType.tp_as_mapping = &pysqlite_row_as_mapping; - pysqlite_RowType.tp_as_sequence = &pysqlite_row_as_sequence; - return PyType_Ready(&pysqlite_RowType); + pysqlite_RowType = (PyTypeObject *)PyType_FromModuleAndSpec(module, &row_spec, NULL); + if (pysqlite_RowType == NULL) { + return -1; + } + return 0; } diff --git a/contrib/tools/python3/src/Modules/_sqlite/row.h b/contrib/tools/python3/src/Modules/_sqlite/row.h index 4ad506f8dd..2dac41e89e 100644 --- a/contrib/tools/python3/src/Modules/_sqlite/row.h +++ b/contrib/tools/python3/src/Modules/_sqlite/row.h @@ -33,8 +33,8 @@ typedef struct _Row PyObject* description; } pysqlite_Row; -extern PyTypeObject pysqlite_RowType; +extern PyTypeObject *pysqlite_RowType; -int pysqlite_row_setup_types(void); +int pysqlite_row_setup_types(PyObject *module); #endif diff --git a/contrib/tools/python3/src/Modules/_sqlite/statement.c b/contrib/tools/python3/src/Modules/_sqlite/statement.c index 0272ce1120..3bc86420aa 100644 --- a/contrib/tools/python3/src/Modules/_sqlite/statement.c +++ b/contrib/tools/python3/src/Modules/_sqlite/statement.c @@ -48,7 +48,8 @@ typedef enum { TYPE_UNKNOWN } parameter_type; -int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* connection, PyObject* sql) +pysqlite_Statement * +pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql) { const char* tail; int rc; @@ -56,28 +57,36 @@ int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* con Py_ssize_t sql_cstr_len; const char* p; - self->st = NULL; - self->in_use = 0; - assert(PyUnicode_Check(sql)); sql_cstr = PyUnicode_AsUTF8AndSize(sql, &sql_cstr_len); if (sql_cstr == NULL) { - rc = PYSQLITE_SQL_WRONG_TYPE; - return rc; + PyErr_Format(pysqlite_Warning, + "SQL is of wrong type ('%s'). Must be string.", + Py_TYPE(sql)->tp_name); + return NULL; } if (strlen(sql_cstr) != (size_t)sql_cstr_len) { - PyErr_SetString(PyExc_ValueError, "the query contains a null character"); - return PYSQLITE_SQL_WRONG_TYPE; + PyErr_SetString(PyExc_ValueError, + "the query contains a null character"); + return NULL; + } + + pysqlite_Statement *self = PyObject_GC_New(pysqlite_Statement, + pysqlite_StatementType); + if (self == NULL) { + return NULL; } + self->db = connection->db; + self->st = NULL; + self->sql = Py_NewRef(sql); + self->in_use = 0; + self->is_dml = 0; self->in_weakreflist = NULL; - Py_INCREF(sql); - self->sql = sql; /* Determine if the statement is a DML statement. SELECT is the only exception. See #9924. */ - self->is_dml = 0; for (p = sql_cstr; *p != 0; p++) { switch (*p) { case ' ': @@ -95,22 +104,33 @@ int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* con } Py_BEGIN_ALLOW_THREADS - rc = sqlite3_prepare_v2(connection->db, + rc = sqlite3_prepare_v2(self->db, sql_cstr, -1, &self->st, &tail); Py_END_ALLOW_THREADS - self->db = connection->db; + PyObject_GC_Track(self); + + if (rc != SQLITE_OK) { + _pysqlite_seterror(self->db, NULL); + goto error; + } if (rc == SQLITE_OK && pysqlite_check_remaining_sql(tail)) { (void)sqlite3_finalize(self->st); self->st = NULL; - rc = PYSQLITE_TOO_MUCH_SQL; + PyErr_SetString(pysqlite_Warning, + "You can only execute one statement at a time."); + goto error; } - return rc; + return self; + +error: + Py_DECREF(self); + return NULL; } int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObject* parameter) @@ -247,11 +267,11 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para } for (i = 0; i < num_params; i++) { if (PyTuple_CheckExact(parameters)) { - current_param = PyTuple_GET_ITEM(parameters, i); - Py_INCREF(current_param); + PyObject *item = PyTuple_GET_ITEM(parameters, i); + current_param = Py_NewRef(item); } else if (PyList_CheckExact(parameters)) { - current_param = PyList_GetItem(parameters, i); - Py_XINCREF(current_param); + PyObject *item = PyList_GetItem(parameters, i); + current_param = Py_XNewRef(item); } else { current_param = PySequence_GetItem(parameters, i); } @@ -262,7 +282,7 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para if (!_need_adapt(current_param)) { adapted = current_param; } else { - adapted = pysqlite_microprotocols_adapt(current_param, (PyObject*)&pysqlite_PrepareProtocolType, current_param); + adapted = pysqlite_microprotocols_adapt(current_param, (PyObject*)pysqlite_PrepareProtocolType, current_param); Py_DECREF(current_param); if (!adapted) { return; @@ -297,15 +317,15 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para return; } if (PyDict_CheckExact(parameters)) { - current_param = PyDict_GetItemWithError(parameters, binding_name_obj); - Py_XINCREF(current_param); + PyObject *item = PyDict_GetItemWithError(parameters, binding_name_obj); + current_param = Py_XNewRef(item); } else { current_param = PyObject_GetItem(parameters, binding_name_obj); } Py_DECREF(binding_name_obj); if (!current_param) { if (!PyErr_Occurred() || PyErr_ExceptionMatches(PyExc_LookupError)) { - PyErr_Format(pysqlite_ProgrammingError, "You did not supply a value for binding %d.", i); + PyErr_Format(pysqlite_ProgrammingError, "You did not supply a value for binding parameter :%s.", binding_name); } return; } @@ -313,7 +333,7 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para if (!_need_adapt(current_param)) { adapted = current_param; } else { - adapted = pysqlite_microprotocols_adapt(current_param, (PyObject*)&pysqlite_PrepareProtocolType, current_param); + adapted = pysqlite_microprotocols_adapt(current_param, (PyObject*)pysqlite_PrepareProtocolType, current_param); Py_DECREF(current_param); if (!adapted) { return; @@ -376,23 +396,38 @@ void pysqlite_statement_mark_dirty(pysqlite_Statement* self) self->in_use = 1; } -void pysqlite_statement_dealloc(pysqlite_Statement* self) +static void +stmt_dealloc(pysqlite_Statement *self) { + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); + if (self->in_weakreflist != NULL) { + PyObject_ClearWeakRefs((PyObject*)self); + } if (self->st) { Py_BEGIN_ALLOW_THREADS sqlite3_finalize(self->st); Py_END_ALLOW_THREADS + self->st = 0; } + tp->tp_clear((PyObject *)self); + tp->tp_free(self); + Py_DECREF(tp); +} - self->st = NULL; - - Py_XDECREF(self->sql); - - if (self->in_weakreflist != NULL) { - PyObject_ClearWeakRefs((PyObject*)self); - } +static int +stmt_clear(pysqlite_Statement *self) +{ + Py_CLEAR(self->sql); + return 0; +} - Py_TYPE(self)->tp_free((PyObject*)self); +static int +stmt_traverse(pysqlite_Statement *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + Py_VISIT(self->sql); + return 0; } /* @@ -465,50 +500,33 @@ static int pysqlite_check_remaining_sql(const char* tail) return 0; } -PyTypeObject pysqlite_StatementType = { - PyVarObject_HEAD_INIT(NULL, 0) - MODULE_NAME ".Statement", /* tp_name */ - sizeof(pysqlite_Statement), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)pysqlite_statement_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(pysqlite_Statement, in_weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0 /* tp_free */ +static PyMemberDef stmt_members[] = { + {"__weaklistoffset__", T_PYSSIZET, offsetof(pysqlite_Statement, in_weakreflist), READONLY}, + {NULL}, +}; +static PyType_Slot stmt_slots[] = { + {Py_tp_members, stmt_members}, + {Py_tp_dealloc, stmt_dealloc}, + {Py_tp_traverse, stmt_traverse}, + {Py_tp_clear, stmt_clear}, + {0, NULL}, +}; + +static PyType_Spec stmt_spec = { + .name = MODULE_NAME ".Statement", + .basicsize = sizeof(pysqlite_Statement), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION), + .slots = stmt_slots, }; +PyTypeObject *pysqlite_StatementType = NULL; -extern int pysqlite_statement_setup_types(void) +int +pysqlite_statement_setup_types(PyObject *module) { - pysqlite_StatementType.tp_new = PyType_GenericNew; - return PyType_Ready(&pysqlite_StatementType); + pysqlite_StatementType = (PyTypeObject *)PyType_FromModuleAndSpec(module, &stmt_spec, NULL); + if (pysqlite_StatementType == NULL) { + return -1; + } + return 0; } diff --git a/contrib/tools/python3/src/Modules/_sqlite/statement.h b/contrib/tools/python3/src/Modules/_sqlite/statement.h index 5002f02dc5..e8c86a0ec9 100644 --- a/contrib/tools/python3/src/Modules/_sqlite/statement.h +++ b/contrib/tools/python3/src/Modules/_sqlite/statement.h @@ -29,9 +29,6 @@ #include "connection.h" #include "sqlite3.h" -#define PYSQLITE_TOO_MUCH_SQL (-100) -#define PYSQLITE_SQL_WRONG_TYPE (-101) - typedef struct { PyObject_HEAD @@ -43,10 +40,9 @@ typedef struct PyObject* in_weakreflist; /* List of weak references */ } pysqlite_Statement; -extern PyTypeObject pysqlite_StatementType; +extern PyTypeObject *pysqlite_StatementType; -int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* connection, PyObject* sql); -void pysqlite_statement_dealloc(pysqlite_Statement* self); +pysqlite_Statement *pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql); int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObject* parameter); void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* parameters); @@ -55,6 +51,6 @@ int pysqlite_statement_finalize(pysqlite_Statement* self); int pysqlite_statement_reset(pysqlite_Statement* self); void pysqlite_statement_mark_dirty(pysqlite_Statement* self); -int pysqlite_statement_setup_types(void); +int pysqlite_statement_setup_types(PyObject *module); #endif diff --git a/contrib/tools/python3/src/Modules/_sqlite/util.c b/contrib/tools/python3/src/Modules/_sqlite/util.c index 1dbabcdd94..0f4eba0ab3 100644 --- a/contrib/tools/python3/src/Modules/_sqlite/util.c +++ b/contrib/tools/python3/src/Modules/_sqlite/util.c @@ -28,15 +28,9 @@ int pysqlite_step(sqlite3_stmt* statement, pysqlite_Connection* connection) { int rc; - if (statement == NULL) { - /* this is a workaround for SQLite 3.5 and later. it now apparently - * returns NULL for "no-operation" statements */ - rc = SQLITE_OK; - } else { - Py_BEGIN_ALLOW_THREADS - rc = sqlite3_step(statement); - Py_END_ALLOW_THREADS - } + Py_BEGIN_ALLOW_THREADS + rc = sqlite3_step(statement); + Py_END_ALLOW_THREADS return rc; } diff --git a/contrib/tools/python3/src/Modules/_sqlite/util.h b/contrib/tools/python3/src/Modules/_sqlite/util.h index c5a220e9b0..cff31cda95 100644 --- a/contrib/tools/python3/src/Modules/_sqlite/util.h +++ b/contrib/tools/python3/src/Modules/_sqlite/util.h @@ -39,10 +39,4 @@ int _pysqlite_seterror(sqlite3* db, sqlite3_stmt* st); sqlite_int64 _pysqlite_long_as_int64(PyObject * value); -#if SQLITE_VERSION_NUMBER >= 3007014 -#define SQLITE3_CLOSE sqlite3_close_v2 -#else -#define SQLITE3_CLOSE sqlite3_close -#endif - #endif diff --git a/contrib/tools/python3/src/Modules/_sre.c b/contrib/tools/python3/src/Modules/_sre.c index 338530e2dc..911626dafc 100644 --- a/contrib/tools/python3/src/Modules/_sre.c +++ b/contrib/tools/python3/src/Modules/_sre.c @@ -41,6 +41,8 @@ static const char copyright[] = #define PY_SSIZE_T_CLEAN #include "Python.h" +#include "pycore_long.h" // _PyLong_GetZero() +#include "pycore_moduleobject.h" // _PyModule_GetState() #include "structmember.h" // PyMemberDef #include "sre.h" @@ -196,7 +198,7 @@ static void data_stack_dealloc(SRE_STATE* state) { if (state->data_stack) { - PyMem_FREE(state->data_stack); + PyMem_Free(state->data_stack); state->data_stack = NULL; } state->data_stack_size = state->data_stack_base = 0; @@ -211,8 +213,8 @@ data_stack_grow(SRE_STATE* state, Py_ssize_t size) if (cursize < minsize) { void* stack; cursize = minsize+minsize/4+1024; - TRACE(("allocate/grow stack %" PY_FORMAT_SIZE_T "d\n", cursize)); - stack = PyMem_REALLOC(state->data_stack, cursize); + TRACE(("allocate/grow stack %zd\n", cursize)); + stack = PyMem_Realloc(state->data_stack, cursize); if (!stack) { data_stack_dealloc(state); return SRE_ERROR_MEMORY; @@ -247,22 +249,36 @@ data_stack_grow(SRE_STATE* state, Py_ssize_t size) /* -------------------------------------------------------------------- */ /* factories and destructors */ -/* see sre.h for object declarations */ -static PyObject*pattern_new_match(PatternObject*, SRE_STATE*, Py_ssize_t); -static PyObject *pattern_scanner(PatternObject *, PyObject *, Py_ssize_t, Py_ssize_t); +/* module state */ +typedef struct { + PyTypeObject *Pattern_Type; + PyTypeObject *Match_Type; + PyTypeObject *Scanner_Type; +} _sremodulestate; + +static _sremodulestate * +get_sre_module_state(PyObject *m) +{ + _sremodulestate *state = (_sremodulestate *)_PyModule_GetState(m); + assert(state); + return state; +} + +static struct PyModuleDef sremodule; +#define get_sre_module_state_by_class(cls) \ + (get_sre_module_state(PyType_GetModule(cls))) +/* see sre.h for object declarations */ +static PyObject*pattern_new_match(_sremodulestate *, PatternObject*, SRE_STATE*, Py_ssize_t); +static PyObject *pattern_scanner(_sremodulestate *, PatternObject *, PyObject *, Py_ssize_t, Py_ssize_t); /*[clinic input] module _sre -class _sre.SRE_Pattern "PatternObject *" "&Pattern_Type" -class _sre.SRE_Match "MatchObject *" "&Match_Type" -class _sre.SRE_Scanner "ScannerObject *" "&Scanner_Type" +class _sre.SRE_Pattern "PatternObject *" "get_sre_module_state_by_class(tp)->Pattern_Type" +class _sre.SRE_Match "MatchObject *" "get_sre_module_state_by_class(tp)->Match_Type" +class _sre.SRE_Scanner "ScannerObject *" "get_sre_module_state_by_class(tp)->Scanner_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b0230ec19a0deac8]*/ - -static PyTypeObject Pattern_Type; -static PyTypeObject Match_Type; -static PyTypeObject Scanner_Type; +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=fe2966e32b66a231]*/ /*[clinic input] _sre.getcodesize -> int @@ -457,7 +473,7 @@ state_init(SRE_STATE* state, PatternObject* pattern, PyObject* string, /* We add an explicit cast here because MSVC has a bug when compiling C code where it believes that `const void**` cannot be safely casted to `void*`, see bpo-39943 for details. */ - PyMem_Del((void*) state->mark); + PyMem_Free((void*) state->mark); state->mark = NULL; if (state->buffer.buf) PyBuffer_Release(&state->buffer); @@ -472,7 +488,7 @@ state_fini(SRE_STATE* state) Py_XDECREF(state->string); data_stack_dealloc(state); /* See above PyMem_Del for why we explicitly cast here. */ - PyMem_Del((void*) state->mark); + PyMem_Free((void*) state->mark); state->mark = NULL; } @@ -546,15 +562,37 @@ pattern_error(Py_ssize_t status) } } +static int +pattern_traverse(PatternObject *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + Py_VISIT(self->groupindex); + Py_VISIT(self->indexgroup); + Py_VISIT(self->pattern); + return 0; +} + +static int +pattern_clear(PatternObject *self) +{ + Py_CLEAR(self->groupindex); + Py_CLEAR(self->indexgroup); + Py_CLEAR(self->pattern); + return 0; +} + static void pattern_dealloc(PatternObject* self) { - if (self->weakreflist != NULL) + PyTypeObject *tp = Py_TYPE(self); + + PyObject_GC_UnTrack(self); + if (self->weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject *) self); - Py_XDECREF(self->pattern); - Py_XDECREF(self->groupindex); - Py_XDECREF(self->indexgroup); - PyObject_DEL(self); + } + (void)pattern_clear(self); + tp->tp_free(self); + Py_DECREF(tp); } LOCAL(Py_ssize_t) @@ -582,6 +620,8 @@ sre_search(SRE_STATE* state, SRE_CODE* pattern) /*[clinic input] _sre.SRE_Pattern.match + cls: defining_class + / string: object pos: Py_ssize_t = 0 endpos: Py_ssize_t(c_default="PY_SSIZE_T_MAX") = sys.maxsize @@ -590,10 +630,12 @@ Matches zero or more characters at the beginning of the string. [clinic start generated code]*/ static PyObject * -_sre_SRE_Pattern_match_impl(PatternObject *self, PyObject *string, - Py_ssize_t pos, Py_ssize_t endpos) -/*[clinic end generated code: output=ea2d838888510661 input=a2ba191647abebe5]*/ +_sre_SRE_Pattern_match_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos) +/*[clinic end generated code: output=ec6208ea58a0cca0 input=4bdb9c3e564d13ac]*/ { + _sremodulestate *module_state = get_sre_module_state_by_class(cls); SRE_STATE state; Py_ssize_t status; PyObject *match; @@ -613,7 +655,7 @@ _sre_SRE_Pattern_match_impl(PatternObject *self, PyObject *string, return NULL; } - match = pattern_new_match(self, &state, status); + match = pattern_new_match(module_state, self, &state, status); state_fini(&state); return match; } @@ -621,6 +663,8 @@ _sre_SRE_Pattern_match_impl(PatternObject *self, PyObject *string, /*[clinic input] _sre.SRE_Pattern.fullmatch + cls: defining_class + / string: object pos: Py_ssize_t = 0 endpos: Py_ssize_t(c_default="PY_SSIZE_T_MAX") = sys.maxsize @@ -629,10 +673,12 @@ Matches against all of the string. [clinic start generated code]*/ static PyObject * -_sre_SRE_Pattern_fullmatch_impl(PatternObject *self, PyObject *string, - Py_ssize_t pos, Py_ssize_t endpos) -/*[clinic end generated code: output=5833c47782a35f4a input=d9fb03a7625b5828]*/ +_sre_SRE_Pattern_fullmatch_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos) +/*[clinic end generated code: output=625b75b027ef94da input=50981172ab0fcfdd]*/ { + _sremodulestate *module_state = get_sre_module_state_by_class(cls); SRE_STATE state; Py_ssize_t status; PyObject *match; @@ -653,7 +699,7 @@ _sre_SRE_Pattern_fullmatch_impl(PatternObject *self, PyObject *string, return NULL; } - match = pattern_new_match(self, &state, status); + match = pattern_new_match(module_state, self, &state, status); state_fini(&state); return match; } @@ -661,6 +707,8 @@ _sre_SRE_Pattern_fullmatch_impl(PatternObject *self, PyObject *string, /*[clinic input] _sre.SRE_Pattern.search + cls: defining_class + / string: object pos: Py_ssize_t = 0 endpos: Py_ssize_t(c_default="PY_SSIZE_T_MAX") = sys.maxsize @@ -671,10 +719,12 @@ Return None if no position in the string matches. [clinic start generated code]*/ static PyObject * -_sre_SRE_Pattern_search_impl(PatternObject *self, PyObject *string, - Py_ssize_t pos, Py_ssize_t endpos) -/*[clinic end generated code: output=25f302a644e951e8 input=4ae5cb7dc38fed1b]*/ +_sre_SRE_Pattern_search_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos) +/*[clinic end generated code: output=bd7f2d9d583e1463 input=afa9afb66a74a4b3]*/ { + _sremodulestate *module_state = get_sre_module_state_by_class(cls); SRE_STATE state; Py_ssize_t status; PyObject *match; @@ -693,7 +743,7 @@ _sre_SRE_Pattern_search_impl(PatternObject *self, PyObject *string, return NULL; } - match = pattern_new_match(self, &state, status); + match = pattern_new_match(module_state, self, &state, status); state_fini(&state); return match; } @@ -825,6 +875,8 @@ error: /*[clinic input] _sre.SRE_Pattern.finditer + cls: defining_class + / string: object pos: Py_ssize_t = 0 endpos: Py_ssize_t(c_default="PY_SSIZE_T_MAX") = sys.maxsize @@ -835,15 +887,17 @@ For each match, the iterator returns a match object. [clinic start generated code]*/ static PyObject * -_sre_SRE_Pattern_finditer_impl(PatternObject *self, PyObject *string, - Py_ssize_t pos, Py_ssize_t endpos) -/*[clinic end generated code: output=0bbb1a0aeb38bb14 input=612aab69e9fe08e4]*/ +_sre_SRE_Pattern_finditer_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos) +/*[clinic end generated code: output=1791dbf3618ade56 input=812e332a4848cbaf]*/ { + _sremodulestate *module_state = get_sre_module_state_by_class(cls); PyObject* scanner; PyObject* search; PyObject* iterator; - scanner = pattern_scanner(self, string, pos, endpos); + scanner = pattern_scanner(module_state, self, string, pos, endpos); if (!scanner) return NULL; @@ -861,6 +915,8 @@ _sre_SRE_Pattern_finditer_impl(PatternObject *self, PyObject *string, /*[clinic input] _sre.SRE_Pattern.scanner + cls: defining_class + / string: object pos: Py_ssize_t = 0 endpos: Py_ssize_t(c_default="PY_SSIZE_T_MAX") = sys.maxsize @@ -868,11 +924,14 @@ _sre.SRE_Pattern.scanner [clinic start generated code]*/ static PyObject * -_sre_SRE_Pattern_scanner_impl(PatternObject *self, PyObject *string, - Py_ssize_t pos, Py_ssize_t endpos) -/*[clinic end generated code: output=54ea548aed33890b input=3aacdbde77a3a637]*/ +_sre_SRE_Pattern_scanner_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos) +/*[clinic end generated code: output=f70cd506112f1bd9 input=2e487e5151bcee4c]*/ { - return pattern_scanner(self, string, pos, endpos); + _sremodulestate *module_state = get_sre_module_state_by_class(cls); + + return pattern_scanner(module_state, self, string, pos, endpos); } /*[clinic input] @@ -979,8 +1038,12 @@ error: } static PyObject* -pattern_subx(PatternObject* self, PyObject* ptemplate, PyObject* string, - Py_ssize_t count, Py_ssize_t subn) +pattern_subx(_sremodulestate* module_state, + PatternObject* self, + PyObject* ptemplate, + PyObject* string, + Py_ssize_t count, + Py_ssize_t subn) { SRE_STATE state; PyObject* list; @@ -1082,7 +1145,7 @@ pattern_subx(PatternObject* self, PyObject* ptemplate, PyObject* string, if (filter_is_callable) { /* pass match object through filter */ - match = pattern_new_match(self, &state, 1); + match = pattern_new_match(module_state, self, &state, 1); if (!match) goto error; item = PyObject_CallOneArg(filter, match); @@ -1162,6 +1225,8 @@ error: /*[clinic input] _sre.SRE_Pattern.sub + cls: defining_class + / repl: object string: object count: Py_ssize_t = 0 @@ -1170,16 +1235,20 @@ Return the string obtained by replacing the leftmost non-overlapping occurrences [clinic start generated code]*/ static PyObject * -_sre_SRE_Pattern_sub_impl(PatternObject *self, PyObject *repl, - PyObject *string, Py_ssize_t count) -/*[clinic end generated code: output=1dbf2ec3479cba00 input=c53d70be0b3caf86]*/ +_sre_SRE_Pattern_sub_impl(PatternObject *self, PyTypeObject *cls, + PyObject *repl, PyObject *string, Py_ssize_t count) +/*[clinic end generated code: output=4be141ab04bca60d input=d8d1d4ac2311a07c]*/ { - return pattern_subx(self, repl, string, count, 0); + _sremodulestate *module_state = get_sre_module_state_by_class(cls); + + return pattern_subx(module_state, self, repl, string, count, 0); } /*[clinic input] _sre.SRE_Pattern.subn + cls: defining_class + / repl: object string: object count: Py_ssize_t = 0 @@ -1188,11 +1257,14 @@ Return the tuple (new_string, number_of_subs_made) found by replacing the leftmo [clinic start generated code]*/ static PyObject * -_sre_SRE_Pattern_subn_impl(PatternObject *self, PyObject *repl, - PyObject *string, Py_ssize_t count) -/*[clinic end generated code: output=0d9522cd529e9728 input=e7342d7ce6083577]*/ +_sre_SRE_Pattern_subn_impl(PatternObject *self, PyTypeObject *cls, + PyObject *repl, PyObject *string, + Py_ssize_t count) +/*[clinic end generated code: output=da02fd85258b1e1f input=8b78a65b8302e58d]*/ { - return pattern_subx(self, repl, string, count, 1); + _sremodulestate *module_state = get_sre_module_state_by_class(cls); + + return pattern_subx(module_state, self, repl, string, count, 1); } /*[clinic input] @@ -1337,12 +1409,13 @@ _sre_compile_impl(PyObject *module, PyObject *pattern, int flags, { /* "compile" pattern descriptor to pattern object */ + _sremodulestate *module_state = get_sre_module_state(module); PatternObject* self; Py_ssize_t i, n; n = PyList_GET_SIZE(code); /* coverity[ampersand_in_size] */ - self = PyObject_NewVar(PatternObject, &Pattern_Type, n); + self = PyObject_GC_NewVar(PatternObject, module_state->Pattern_Type, n); if (!self) return NULL; self->weakreflist = NULL; @@ -1362,6 +1435,7 @@ _sre_compile_impl(PyObject *module, PyObject *pattern, int flags, break; } } + PyObject_GC_Track(self); if (PyErr_Occurred()) { Py_DECREF(self); @@ -1883,13 +1957,34 @@ _validate(PatternObject *self) /* -------------------------------------------------------------------- */ /* match methods */ +static int +match_traverse(MatchObject *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + Py_VISIT(self->string); + Py_VISIT(self->regs); + Py_VISIT(self->pattern); + return 0; +} + +static int +match_clear(MatchObject *self) +{ + Py_CLEAR(self->string); + Py_CLEAR(self->regs); + Py_CLEAR(self->pattern); + return 0; +} + static void match_dealloc(MatchObject* self) { - Py_XDECREF(self->regs); - Py_XDECREF(self->string); - Py_DECREF(self->pattern); - PyObject_DEL(self); + PyTypeObject *tp = Py_TYPE(self); + + PyObject_GC_UnTrack(self); + (void)match_clear(self); + tp->tp_free(self); + Py_DECREF(tp); } static PyObject* @@ -1999,7 +2094,7 @@ match_group(MatchObject* self, PyObject* args) switch (size) { case 0: - result = match_getslice(self, _PyLong_Zero, Py_None); + result = match_getslice(self, _PyLong_GetZero(), Py_None); break; case 1: result = match_getslice(self, PyTuple_GET_ITEM(args, 0), Py_None); @@ -2318,7 +2413,10 @@ match_repr(MatchObject *self) static PyObject* -pattern_new_match(PatternObject* pattern, SRE_STATE* state, Py_ssize_t status) +pattern_new_match(_sremodulestate* module_state, + PatternObject* pattern, + SRE_STATE* state, + Py_ssize_t status) { /* create match object (from state object) */ @@ -2331,8 +2429,9 @@ pattern_new_match(PatternObject* pattern, SRE_STATE* state, Py_ssize_t status) /* create match object (with room for extra group marks) */ /* coverity[ampersand_in_size] */ - match = PyObject_NewVar(MatchObject, &Match_Type, - 2*(pattern->groups+1)); + match = PyObject_GC_NewVar(MatchObject, + module_state->Match_Type, + 2*(pattern->groups+1)); if (!match) return NULL; @@ -2365,6 +2464,7 @@ pattern_new_match(PatternObject* pattern, SRE_STATE* state, Py_ssize_t status) match->lastindex = state->lastindex; + PyObject_GC_Track(match); return (PyObject*) match; } else if (status == 0) { @@ -2383,12 +2483,31 @@ pattern_new_match(PatternObject* pattern, SRE_STATE* state, Py_ssize_t status) /* -------------------------------------------------------------------- */ /* scanner methods (experimental) */ +static int +scanner_traverse(ScannerObject *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + Py_VISIT(self->pattern); + return 0; +} + +static int +scanner_clear(ScannerObject *self) +{ + Py_CLEAR(self->pattern); + return 0; +} + static void scanner_dealloc(ScannerObject* self) { + PyTypeObject *tp = Py_TYPE(self); + + PyObject_GC_UnTrack(self); state_fini(&self->state); - Py_XDECREF(self->pattern); - PyObject_DEL(self); + (void)scanner_clear(self); + tp->tp_free(self); + Py_DECREF(tp); } static int @@ -2413,12 +2532,16 @@ scanner_end(ScannerObject* self) /*[clinic input] _sre.SRE_Scanner.match + cls: defining_class + / + [clinic start generated code]*/ static PyObject * -_sre_SRE_Scanner_match_impl(ScannerObject *self) -/*[clinic end generated code: output=936b30c63d4b81eb input=881a0154f8c13d9a]*/ +_sre_SRE_Scanner_match_impl(ScannerObject *self, PyTypeObject *cls) +/*[clinic end generated code: output=6e22c149dc0f0325 input=b5146e1f30278cb7]*/ { + _sremodulestate *module_state = get_sre_module_state_by_class(cls); SRE_STATE* state = &self->state; PyObject* match; Py_ssize_t status; @@ -2441,8 +2564,8 @@ _sre_SRE_Scanner_match_impl(ScannerObject *self) return NULL; } - match = pattern_new_match((PatternObject*) self->pattern, - state, status); + match = pattern_new_match(module_state, (PatternObject*) self->pattern, + state, status); if (status == 0) state->start = NULL; @@ -2459,12 +2582,16 @@ _sre_SRE_Scanner_match_impl(ScannerObject *self) /*[clinic input] _sre.SRE_Scanner.search + cls: defining_class + / + [clinic start generated code]*/ static PyObject * -_sre_SRE_Scanner_search_impl(ScannerObject *self) -/*[clinic end generated code: output=7dc211986088f025 input=161223ee92ef9270]*/ +_sre_SRE_Scanner_search_impl(ScannerObject *self, PyTypeObject *cls) +/*[clinic end generated code: output=23e8fc78013f9161 input=056c2d37171d0bf2]*/ { + _sremodulestate *module_state = get_sre_module_state_by_class(cls); SRE_STATE* state = &self->state; PyObject* match; Py_ssize_t status; @@ -2487,8 +2614,8 @@ _sre_SRE_Scanner_search_impl(ScannerObject *self) return NULL; } - match = pattern_new_match((PatternObject*) self->pattern, - state, status); + match = pattern_new_match(module_state, (PatternObject*) self->pattern, + state, status); if (status == 0) state->start = NULL; @@ -2502,12 +2629,16 @@ _sre_SRE_Scanner_search_impl(ScannerObject *self) } static PyObject * -pattern_scanner(PatternObject *self, PyObject *string, Py_ssize_t pos, Py_ssize_t endpos) +pattern_scanner(_sremodulestate *module_state, + PatternObject *self, + PyObject *string, + Py_ssize_t pos, + Py_ssize_t endpos) { ScannerObject* scanner; /* create scanner object */ - scanner = PyObject_New(ScannerObject, &Scanner_Type); + scanner = PyObject_GC_New(ScannerObject, module_state->Scanner_Type); if (!scanner) return NULL; scanner->pattern = NULL; @@ -2522,6 +2653,7 @@ pattern_scanner(PatternObject *self, PyObject *string, Py_ssize_t pos, Py_ssize_ Py_INCREF(self); scanner->pattern = (PyObject*) self; + PyObject_GC_Track(scanner); return (PyObject*) scanner; } @@ -2551,6 +2683,8 @@ pattern_hash(PatternObject *self) static PyObject* pattern_richcompare(PyObject *lefto, PyObject *righto, int op) { + PyTypeObject *tp = Py_TYPE(lefto); + _sremodulestate *module_state = get_sre_module_state_by_class(tp); PatternObject *left, *right; int cmp; @@ -2558,7 +2692,8 @@ pattern_richcompare(PyObject *lefto, PyObject *righto, int op) Py_RETURN_NOTIMPLEMENTED; } - if (!Py_IS_TYPE(lefto, &Pattern_Type) || !Py_IS_TYPE(righto, &Pattern_Type)) { + if (!Py_IS_TYPE(righto, module_state->Pattern_Type)) + { Py_RETURN_NOTIMPLEMENTED; } @@ -2627,47 +2762,31 @@ static PyMemberDef pattern_members[] = { "The regex matching flags."}, {"groups", T_PYSSIZET, PAT_OFF(groups), READONLY, "The number of capturing groups in the pattern."}, + {"__weaklistoffset__", T_PYSSIZET, offsetof(PatternObject, weakreflist), READONLY}, {NULL} /* Sentinel */ }; -static PyTypeObject Pattern_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "re.Pattern", - sizeof(PatternObject), sizeof(SRE_CODE), - (destructor)pattern_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)pattern_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)pattern_hash, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - pattern_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - pattern_richcompare, /* tp_richcompare */ - offsetof(PatternObject, weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - pattern_methods, /* tp_methods */ - pattern_members, /* tp_members */ - pattern_getset, /* tp_getset */ +static PyType_Slot pattern_slots[] = { + {Py_tp_dealloc, (destructor)pattern_dealloc}, + {Py_tp_repr, (reprfunc)pattern_repr}, + {Py_tp_hash, (hashfunc)pattern_hash}, + {Py_tp_doc, (void *)pattern_doc}, + {Py_tp_richcompare, pattern_richcompare}, + {Py_tp_methods, pattern_methods}, + {Py_tp_members, pattern_members}, + {Py_tp_getset, pattern_getset}, + {Py_tp_traverse, pattern_traverse}, + {Py_tp_clear, pattern_clear}, + {0, NULL}, }; -/* Match objects do not support length or assignment, but do support - __getitem__. */ -static PyMappingMethods match_as_mapping = { - NULL, - (binaryfunc)match_getitem, - NULL +static PyType_Spec pattern_spec = { + .name = "re.Pattern", + .basicsize = sizeof(PatternObject), + .itemsize = sizeof(SRE_CODE), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | + Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_HAVE_GC), + .slots = pattern_slots, }; static PyMethodDef match_methods[] = { @@ -2709,37 +2828,33 @@ static PyMemberDef match_members[] = { /* FIXME: implement setattr("string", None) as a special case (to detach the associated string, if any */ +static PyType_Slot match_slots[] = { + {Py_tp_dealloc, match_dealloc}, + {Py_tp_repr, match_repr}, + {Py_tp_doc, (void *)match_doc}, + {Py_tp_methods, match_methods}, + {Py_tp_members, match_members}, + {Py_tp_getset, match_getset}, + {Py_tp_traverse, match_traverse}, + {Py_tp_clear, match_clear}, + + /* As mapping. + * + * Match objects do not support length or assignment, but do support + * __getitem__. + */ + {Py_mp_subscript, match_getitem}, + + {0, NULL}, +}; -static PyTypeObject Match_Type = { - PyVarObject_HEAD_INIT(NULL,0) - "re.Match", - sizeof(MatchObject), sizeof(Py_ssize_t), - (destructor)match_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)match_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - &match_as_mapping, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - match_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - match_methods, /* tp_methods */ - match_members, /* tp_members */ - match_getset, /* tp_getset */ +static PyType_Spec match_spec = { + .name = "re.Match", + .basicsize = sizeof(MatchObject), + .itemsize = sizeof(Py_ssize_t), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | + Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_HAVE_GC), + .slots = match_slots, }; static PyMethodDef scanner_methods[] = { @@ -2754,36 +2869,21 @@ static PyMemberDef scanner_members[] = { {NULL} /* Sentinel */ }; -static PyTypeObject Scanner_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_" SRE_MODULE ".SRE_Scanner", - sizeof(ScannerObject), 0, - (destructor)scanner_dealloc,/* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - scanner_methods, /* tp_methods */ - scanner_members, /* tp_members */ - 0, /* tp_getset */ +static PyType_Slot scanner_slots[] = { + {Py_tp_dealloc, scanner_dealloc}, + {Py_tp_methods, scanner_methods}, + {Py_tp_members, scanner_members}, + {Py_tp_traverse, scanner_traverse}, + {Py_tp_clear, scanner_clear}, + {0, NULL}, +}; + +static PyType_Spec scanner_spec = { + .name = "_" SRE_MODULE ".SRE_Scanner", + .basicsize = sizeof(ScannerObject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | + Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_HAVE_GC), + .slots = scanner_slots, }; static PyMethodDef _functions[] = { @@ -2796,64 +2896,108 @@ static PyMethodDef _functions[] = { {NULL, NULL} }; -static struct PyModuleDef sremodule = { - PyModuleDef_HEAD_INIT, - "_" SRE_MODULE, - NULL, - -1, - _functions, - NULL, - NULL, - NULL, - NULL -}; +static int +sre_traverse(PyObject *module, visitproc visit, void *arg) +{ + _sremodulestate *state = get_sre_module_state(module); + + Py_VISIT(state->Pattern_Type); + Py_VISIT(state->Match_Type); + Py_VISIT(state->Scanner_Type); + + return 0; +} -PyMODINIT_FUNC PyInit__sre(void) +static int +sre_clear(PyObject *module) { - PyObject* m; - PyObject* d; - PyObject* x; + _sremodulestate *state = get_sre_module_state(module); - /* Patch object types */ - if (PyType_Ready(&Pattern_Type) || PyType_Ready(&Match_Type) || - PyType_Ready(&Scanner_Type)) - return NULL; + Py_CLEAR(state->Pattern_Type); + Py_CLEAR(state->Match_Type); + Py_CLEAR(state->Scanner_Type); - m = PyModule_Create(&sremodule); - if (m == NULL) - return NULL; - d = PyModule_GetDict(m); + return 0; +} - x = PyLong_FromLong(SRE_MAGIC); - if (x) { - PyDict_SetItemString(d, "MAGIC", x); - Py_DECREF(x); - } +static void +sre_free(void *module) +{ + sre_clear((PyObject *)module); +} + +#define CREATE_TYPE(m, type, spec) \ +do { \ + type = (PyTypeObject *)PyType_FromModuleAndSpec(m, spec, NULL); \ + if (type == NULL) { \ + goto error; \ + } \ +} while (0) + +#define ADD_ULONG_CONSTANT(module, name, value) \ + do { \ + PyObject *o = PyLong_FromUnsignedLong(value); \ + if (!o) \ + goto error; \ + int res = PyModule_AddObjectRef(module, name, o); \ + Py_DECREF(o); \ + if (res < 0) { \ + goto error; \ + } \ +} while (0) - x = PyLong_FromLong(sizeof(SRE_CODE)); - if (x) { - PyDict_SetItemString(d, "CODESIZE", x); - Py_DECREF(x); - } +static int +sre_exec(PyObject *m) +{ + _sremodulestate *state; - x = PyLong_FromUnsignedLong(SRE_MAXREPEAT); - if (x) { - PyDict_SetItemString(d, "MAXREPEAT", x); - Py_DECREF(x); + /* Create heap types */ + state = get_sre_module_state(m); + CREATE_TYPE(m, state->Pattern_Type, &pattern_spec); + CREATE_TYPE(m, state->Match_Type, &match_spec); + CREATE_TYPE(m, state->Scanner_Type, &scanner_spec); + + if (PyModule_AddIntConstant(m, "MAGIC", SRE_MAGIC) < 0) { + goto error; } - x = PyLong_FromUnsignedLong(SRE_MAXGROUPS); - if (x) { - PyDict_SetItemString(d, "MAXGROUPS", x); - Py_DECREF(x); + if (PyModule_AddIntConstant(m, "CODESIZE", sizeof(SRE_CODE)) < 0) { + goto error; } - x = PyUnicode_FromString(copyright); - if (x) { - PyDict_SetItemString(d, "copyright", x); - Py_DECREF(x); + ADD_ULONG_CONSTANT(m, "MAXREPEAT", SRE_MAXREPEAT); + ADD_ULONG_CONSTANT(m, "MAXGROUPS", SRE_MAXGROUPS); + + if (PyModule_AddStringConstant(m, "copyright", copyright) < 0) { + goto error; } - return m; + + return 0; + +error: + return -1; +} + +static PyModuleDef_Slot sre_slots[] = { + {Py_mod_exec, sre_exec}, + {0, NULL}, +}; + +static struct PyModuleDef sremodule = { + .m_base = PyModuleDef_HEAD_INIT, + .m_name = "_" SRE_MODULE, + .m_size = sizeof(_sremodulestate), + .m_methods = _functions, + .m_slots = sre_slots, + .m_traverse = sre_traverse, + .m_free = sre_free, + .m_clear = sre_clear, +}; + +PyMODINIT_FUNC +PyInit__sre(void) +{ + return PyModuleDef_Init(&sremodule); } /* vim:ts=4:sw=4:et diff --git a/contrib/tools/python3/src/Modules/_ssl.c b/contrib/tools/python3/src/Modules/_ssl.c index b42e78e916..983a183382 100644 --- a/contrib/tools/python3/src/Modules/_ssl.c +++ b/contrib/tools/python3/src/Modules/_ssl.c @@ -25,13 +25,22 @@ #include "Python.h" +/* Include symbols from _socket module */ +#include "socketmodule.h" + +#ifdef _MSC_VER +#include <wincrypt.h> +#endif + +#include "_ssl.h" + /* Redefined below for Windows debug builds after important #includes */ #define _PySSL_FIX_ERRNO #define PySSL_BEGIN_ALLOW_THREADS_S(save) \ - do { if (_ssl_locks_count>0) { (save) = PyEval_SaveThread(); } } while (0) + do { (save) = PyEval_SaveThread(); } while(0) #define PySSL_END_ALLOW_THREADS_S(save) \ - do { if (_ssl_locks_count>0) { PyEval_RestoreThread(save); } _PySSL_FIX_ERRNO; } while (0) + do { PyEval_RestoreThread(save); _PySSL_FIX_ERRNO; } while(0) #define PySSL_BEGIN_ALLOW_THREADS { \ PyThreadState *_save = NULL; \ PySSL_BEGIN_ALLOW_THREADS_S(_save); @@ -39,10 +48,6 @@ #define PySSL_UNBLOCK_THREADS PySSL_BEGIN_ALLOW_THREADS_S(_save); #define PySSL_END_ALLOW_THREADS PySSL_END_ALLOW_THREADS_S(_save); } -/* Include symbols from _socket module */ -#include "socketmodule.h" - -static PySocketModule_APIObject PySocketModule; #if defined(HAVE_POLL_H) #include <poll.h> @@ -50,10 +55,6 @@ static PySocketModule_APIObject PySocketModule; #include <sys/poll.h> #endif -#ifdef _MSC_VER -#include <wincrypt.h> -#endif - /* Include OpenSSL header files */ #include "openssl/rsa.h" #include "openssl/crypto.h" @@ -66,38 +67,17 @@ static PySocketModule_APIObject PySocketModule; #include "openssl/bio.h" #include "openssl/dh.h" -#ifndef HAVE_X509_VERIFY_PARAM_SET1_HOST -# ifdef LIBRESSL_VERSION_NUMBER -# error "LibreSSL is missing X509_VERIFY_PARAM_set1_host(), see https://github.com/libressl-portable/portable/issues/381" -# elif OPENSSL_VERSION_NUMBER > 0x1000200fL -# define HAVE_X509_VERIFY_PARAM_SET1_HOST -# else -# error "libssl is too old and does not support X509_VERIFY_PARAM_set1_host()" -# endif -#endif - #ifndef OPENSSL_THREADS # error "OPENSSL_THREADS is not defined, Python requires thread-safe OpenSSL" #endif -/* SSL error object */ -static PyObject *PySSLErrorObject; -static PyObject *PySSLCertVerificationErrorObject; -static PyObject *PySSLZeroReturnErrorObject; -static PyObject *PySSLWantReadErrorObject; -static PyObject *PySSLWantWriteErrorObject; -static PyObject *PySSLSyscallErrorObject; -static PyObject *PySSLEOFErrorObject; -/* Error mappings */ -static PyObject *err_codes_to_names; -static PyObject *err_names_to_codes; -static PyObject *lib_codes_to_names; struct py_ssl_error_code { const char *mnemonic; int library, reason; }; + struct py_ssl_library_code { const char *library; int code; @@ -146,15 +126,10 @@ static void _PySSLFixErrno(void) { #include "_ssl_data.h" #endif -#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER) -# define OPENSSL_VERSION_1_1 1 -# define PY_OPENSSL_1_1_API 1 +/* OpenSSL API 1.1.0+ does not include version methods */ +#ifndef OPENSSL_NO_SSL3_METHOD +extern const SSL_METHOD *SSLv3_method(void); #endif - -/* OpenSSL API 1.1.0+ does not include version methods. Define the methods - * unless OpenSSL is compiled without the methods. It's the easiest way to - * make 1.0.2, 1.1.0, 1.1.1, and 3.0.0 happy without deprecation warnings. - */ #ifndef OPENSSL_NO_TLS1_METHOD extern const SSL_METHOD *TLSv1_method(void); #endif @@ -165,129 +140,12 @@ extern const SSL_METHOD *TLSv1_1_method(void); extern const SSL_METHOD *TLSv1_2_method(void); #endif -/* LibreSSL 2.7.0 provides necessary OpenSSL 1.1.0 APIs */ -#if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x2070000fL -# define PY_OPENSSL_1_1_API 1 -#endif - -/* SNI support (client- and server-side) appeared in OpenSSL 1.0.0 and 0.9.8f - * This includes the SSL_set_SSL_CTX() function. - */ -#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME -# define HAVE_SNI 1 -#else -# define HAVE_SNI 0 -#endif - -#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation -# define HAVE_ALPN 1 -#else -# define HAVE_ALPN 0 -#endif - -/* We cannot rely on OPENSSL_NO_NEXTPROTONEG because LibreSSL 2.6.1 dropped - * NPN support but did not set OPENSSL_NO_NEXTPROTONEG for compatibility - * reasons. The check for TLSEXT_TYPE_next_proto_neg works with - * OpenSSL 1.0.1+ and LibreSSL. - * OpenSSL 1.1.1-pre1 dropped NPN but still has TLSEXT_TYPE_next_proto_neg. - */ -#ifdef OPENSSL_NO_NEXTPROTONEG -# define HAVE_NPN 0 -#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L) && !defined(LIBRESSL_VERSION_NUMBER) -# define HAVE_NPN 0 -#elif defined(TLSEXT_TYPE_next_proto_neg) -# define HAVE_NPN 1 -#else -# define HAVE_NPN 0 -#endif - -#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) && !defined(LIBRESSL_VERSION_NUMBER) -#define HAVE_OPENSSL_KEYLOG 1 -#endif - #ifndef INVALID_SOCKET /* MS defines this */ #define INVALID_SOCKET (-1) #endif -/* OpenSSL 1.0.2 and LibreSSL needs extra code for locking */ -#ifndef OPENSSL_VERSION_1_1 -#define HAVE_OPENSSL_CRYPTO_LOCK -#endif - -#if defined(OPENSSL_VERSION_1_1) && !defined(OPENSSL_NO_SSL2) +/* OpenSSL 1.1 does not have SSL 2.0 */ #define OPENSSL_NO_SSL2 -#endif - -#ifndef PY_OPENSSL_1_1_API -/* OpenSSL 1.1 API shims for OpenSSL < 1.1.0 and LibreSSL < 2.7.0 */ - -#define TLS_method SSLv23_method -#define TLS_client_method SSLv23_client_method -#define TLS_server_method SSLv23_server_method -#define ASN1_STRING_get0_data ASN1_STRING_data -#define X509_get0_notBefore X509_get_notBefore -#define X509_get0_notAfter X509_get_notAfter -#define OpenSSL_version_num SSLeay -#define OpenSSL_version SSLeay_version -#define OPENSSL_VERSION SSLEAY_VERSION - -static int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne) -{ - return ne->set; -} - -#ifndef OPENSSL_NO_COMP -/* LCOV_EXCL_START */ -static int COMP_get_type(const COMP_METHOD *meth) -{ - return meth->type; -} -/* LCOV_EXCL_STOP */ -#endif - -static pem_password_cb *SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx) -{ - return ctx->default_passwd_callback; -} - -static void *SSL_CTX_get_default_passwd_cb_userdata(SSL_CTX *ctx) -{ - return ctx->default_passwd_callback_userdata; -} - -static int X509_OBJECT_get_type(X509_OBJECT *x) -{ - return x->type; -} - -static X509 *X509_OBJECT_get0_X509(X509_OBJECT *x) -{ - return x->data.x509; -} - -static int BIO_up_ref(BIO *b) -{ - CRYPTO_add(&b->references, 1, CRYPTO_LOCK_BIO); - return 1; -} - -static STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *store) { - return store->objs; -} - -static int -SSL_SESSION_has_ticket(const SSL_SESSION *s) -{ - return (s->tlsext_ticklen > 0) ? 1 : 0; -} - -static unsigned long -SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s) -{ - return s->tlsext_tick_lifetime_hint; -} - -#endif /* OpenSSL < 1.1.0 or LibreSSL < 2.7.0 */ /* Default cipher suites */ #ifndef PY_SSL_DEFAULT_CIPHERS @@ -298,15 +156,27 @@ SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s) #ifndef PY_SSL_DEFAULT_CIPHER_STRING #error "Py_SSL_DEFAULT_CIPHERS 0 needs Py_SSL_DEFAULT_CIPHER_STRING" #endif + #ifndef PY_SSL_MIN_PROTOCOL + #define PY_SSL_MIN_PROTOCOL TLS1_2_VERSION + #endif #elif PY_SSL_DEFAULT_CIPHERS == 1 /* Python custom selection of sensible cipher suites - * DEFAULT: OpenSSL's default cipher list. Since 1.0.2 the list is in sensible order. + * @SECLEVEL=2: security level 2 with 112 bits minimum security (e.g. 2048 bits RSA key) + * ECDH+*: enable ephemeral elliptic curve Diffie-Hellman + * DHE+*: fallback to ephemeral finite field Diffie-Hellman + * encryption order: AES AEAD (GCM), ChaCha AEAD, AES CBC * !aNULL:!eNULL: really no NULL ciphers - * !MD5:!3DES:!DES:!RC4:!IDEA:!SEED: no weak or broken algorithms on old OpenSSL versions. * !aDSS: no authentication with discrete logarithm DSA algorithm - * !SRP:!PSK: no secure remote password or pre-shared key authentication + * !SHA1: no weak SHA1 MAC + * !AESCCM: no CCM mode, it's uncommon and slow + * + * Based on Hynek's excellent blog post (update 2021-02-11) + * https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/ */ - #define PY_SSL_DEFAULT_CIPHER_STRING "DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK" + #define PY_SSL_DEFAULT_CIPHER_STRING "DEFAULT:ECDH+AESGCM:ECDH+CHACHA20:ECDH+AES:DHE+AES:!aNULL:!eNULL:!aDSS:!SHA1:!AESCCM" + #ifndef PY_SSL_MIN_PROTOCOL + #define PY_SSL_MIN_PROTOCOL TLS1_2_VERSION + #endif #elif PY_SSL_DEFAULT_CIPHERS == 2 /* Ignored in SSLContext constructor, only used to as _ssl.DEFAULT_CIPHER_STRING */ #define PY_SSL_DEFAULT_CIPHER_STRING SSL_DEFAULT_CIPHER_LIST @@ -399,24 +269,10 @@ enum py_proto_version { #endif }; - -/* serves as a flag to see whether we've initialized the SSL thread support. */ -/* 0 means no, greater than 0 means yes */ - -static unsigned int _ssl_locks_count = 0; - /* SSL socket object */ #define X509_NAME_MAXLEN 256 -/* SSL_CTX_clear_options() and SSL_clear_options() were first added in - * OpenSSL 0.9.8m but do not appear in some 0.9.9-dev versions such the - * 0.9.9 from "May 2008" that NetBSD 5.0 uses. */ -#if OPENSSL_VERSION_NUMBER >= 0x009080dfL && OPENSSL_VERSION_NUMBER != 0x00909000L -# define HAVE_SSL_CTX_CLEAR_OPTIONS -#else -# undef HAVE_SSL_CTX_CLEAR_OPTIONS -#endif /* In case of 'tls-unique' it will be 12 bytes for TLS, 36 bytes for * older SSL, but let's be safe */ @@ -426,17 +282,9 @@ static unsigned int _ssl_locks_count = 0; typedef struct { PyObject_HEAD SSL_CTX *ctx; -#if HAVE_NPN - unsigned char *npn_protocols; - int npn_protocols_len; -#endif -#if HAVE_ALPN unsigned char *alpn_protocols; unsigned int alpn_protocols_len; -#endif -#ifndef OPENSSL_NO_TLSEXT PyObject *set_sni_cb; -#endif int check_hostname; /* OpenSSL has no API to get hostflags from X509_VERIFY_PARAM* struct. * We have to maintain our own copy. OpenSSL's hostflags default to 0. @@ -447,10 +295,10 @@ typedef struct { int post_handshake_auth; #endif PyObject *msg_cb; -#ifdef HAVE_OPENSSL_KEYLOG PyObject *keylog_filename; BIO *keylog_bio; -#endif + /* Cached module state, also used in SSLSocket and SSLSession code. */ + _sslmodulestate *state; } PySSLContext; typedef struct { @@ -492,11 +340,6 @@ typedef struct { PySSLContext *ctx; } PySSLSession; -static PyTypeObject PySSLContext_Type; -static PyTypeObject PySSLSocket_Type; -static PyTypeObject PySSLMemoryBIO_Type; -static PyTypeObject PySSLSession_Type; - static inline _PySSLError _PySSL_errno(int failed, const SSL *ssl, int retcode) { _PySSLError err = { 0 }; @@ -513,12 +356,12 @@ static inline _PySSLError _PySSL_errno(int failed, const SSL *ssl, int retcode) /*[clinic input] module _ssl -class _ssl._SSLContext "PySSLContext *" "&PySSLContext_Type" -class _ssl._SSLSocket "PySSLSocket *" "&PySSLSocket_Type" -class _ssl.MemoryBIO "PySSLMemoryBIO *" "&PySSLMemoryBIO_Type" -class _ssl.SSLSession "PySSLSession *" "&PySSLSession_Type" +class _ssl._SSLContext "PySSLContext *" "get_state_type(type)->PySSLContext_Type" +class _ssl._SSLSocket "PySSLSocket *" "get_state_type(type)->PySSLSocket_Type" +class _ssl.MemoryBIO "PySSLMemoryBIO *" "get_state_type(type)->PySSLMemoryBIO_Type" +class _ssl.SSLSession "PySSLSession *" "get_state_type(type)->PySSLSession_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=bdc67fafeeaa8109]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d293bed8bae240fd]*/ #include "clinic/_ssl.c.h" @@ -526,9 +369,6 @@ static int PySSL_select(PySocketSockObject *s, int writing, _PyTime_t timeout); static int PySSL_set_owner(PySSLSocket *, PyObject *, void *); static int PySSL_set_session(PySSLSocket *, PyObject *, void *); -#define PySSLSocket_Check(v) Py_IS_TYPE(v, &PySSLSocket_Type) -#define PySSLMemoryBIO_Check(v) Py_IS_TYPE(v, &PySSLMemoryBIO_Type) -#define PySSLSession_Check(v) Py_IS_TYPE(v, &PySSLSession_Type) typedef enum { SOCKET_IS_NONBLOCKING, @@ -592,22 +432,21 @@ SSLError_str(PyOSErrorObject *self) } static PyType_Slot sslerror_type_slots[] = { - {Py_tp_base, NULL}, /* Filled out in module init as it's not a constant */ {Py_tp_doc, (void*)SSLError_doc}, {Py_tp_str, SSLError_str}, {0, 0}, }; static PyType_Spec sslerror_type_spec = { - "ssl.SSLError", - sizeof(PyOSErrorObject), - 0, - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - sslerror_type_slots + .name = "ssl.SSLError", + .basicsize = sizeof(PyOSErrorObject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_IMMUTABLETYPE), + .slots = sslerror_type_slots }; static void -fill_and_set_sslerror(PySSLSocket *sslsock, PyObject *type, int ssl_errno, +fill_and_set_sslerror(_sslmodulestate *state, + PySSLSocket *sslsock, PyObject *type, int ssl_errno, const char *errstr, int lineno, unsigned long errcode) { PyObject *err_value = NULL, *reason_obj = NULL, *lib_obj = NULL; @@ -626,7 +465,7 @@ fill_and_set_sslerror(PySSLSocket *sslsock, PyObject *type, int ssl_errno, key = Py_BuildValue("ii", lib, reason); if (key == NULL) goto fail; - reason_obj = PyDict_GetItemWithError(err_codes_to_names, key); + reason_obj = PyDict_GetItemWithError(state->err_codes_to_names, key); Py_DECREF(key); if (reason_obj == NULL && PyErr_Occurred()) { goto fail; @@ -634,7 +473,7 @@ fill_and_set_sslerror(PySSLSocket *sslsock, PyObject *type, int ssl_errno, key = PyLong_FromLong(lib); if (key == NULL) goto fail; - lib_obj = PyDict_GetItemWithError(lib_codes_to_names, key); + lib_obj = PyDict_GetItemWithError(state->lib_codes_to_names, key); Py_DECREF(key); if (lib_obj == NULL && PyErr_Occurred()) { goto fail; @@ -646,7 +485,7 @@ fill_and_set_sslerror(PySSLSocket *sslsock, PyObject *type, int ssl_errno, errstr = "unknown error"; /* verify code for cert validation error */ - if ((sslsock != NULL) && (type == PySSLCertVerificationErrorObject)) { + if ((sslsock != NULL) && (type == state->PySSLCertVerificationErrorObject)) { const char *verify_str = NULL; long verify_code; @@ -657,23 +496,18 @@ fill_and_set_sslerror(PySSLSocket *sslsock, PyObject *type, int ssl_errno, } switch (verify_code) { -#ifdef X509_V_ERR_HOSTNAME_MISMATCH - /* OpenSSL >= 1.0.2, LibreSSL >= 2.5.3 */ case X509_V_ERR_HOSTNAME_MISMATCH: verify_obj = PyUnicode_FromFormat( "Hostname mismatch, certificate is not valid for '%S'.", sslsock->server_hostname ); break; -#endif -#ifdef X509_V_ERR_IP_ADDRESS_MISMATCH case X509_V_ERR_IP_ADDRESS_MISMATCH: verify_obj = PyUnicode_FromFormat( "IP address mismatch, certificate is not valid for '%S'.", sslsock->server_hostname ); break; -#endif default: verify_str = X509_verify_cert_error_string(verify_code); if (verify_str != NULL) { @@ -723,7 +557,7 @@ fill_and_set_sslerror(PySSLSocket *sslsock, PyObject *type, int ssl_errno, if (_PyObject_SetAttrId(err_value, &PyId_library, lib_obj)) goto fail; - if ((sslsock != NULL) && (type == PySSLCertVerificationErrorObject)) { + if ((sslsock != NULL) && (type == state->PySSLCertVerificationErrorObject)) { /* Only set verify code / message for SSLCertVerificationError */ if (_PyObject_SetAttrId(err_value, &PyId_verify_code, verify_code_obj)) @@ -754,12 +588,17 @@ PySSL_ChainExceptions(PySSLSocket *sslsock) { static PyObject * PySSL_SetError(PySSLSocket *sslsock, int ret, const char *filename, int lineno) { - PyObject *type = PySSLErrorObject; + PyObject *type; char *errstr = NULL; _PySSLError err; enum py_ssl_error p = PY_SSL_ERROR_NONE; unsigned long e = 0; + assert(sslsock != NULL); + + _sslmodulestate *state = get_state_sock(sslsock); + type = state->PySSLErrorObject; + assert(ret <= 0); e = ERR_peek_last_error(); @@ -769,17 +608,17 @@ PySSL_SetError(PySSLSocket *sslsock, int ret, const char *filename, int lineno) switch (err.ssl) { case SSL_ERROR_ZERO_RETURN: errstr = "TLS/SSL connection has been closed (EOF)"; - type = PySSLZeroReturnErrorObject; + type = state->PySSLZeroReturnErrorObject; p = PY_SSL_ERROR_ZERO_RETURN; break; case SSL_ERROR_WANT_READ: errstr = "The operation did not complete (read)"; - type = PySSLWantReadErrorObject; + type = state->PySSLWantReadErrorObject; p = PY_SSL_ERROR_WANT_READ; break; case SSL_ERROR_WANT_WRITE: p = PY_SSL_ERROR_WANT_WRITE; - type = PySSLWantWriteErrorObject; + type = state->PySSLWantWriteErrorObject; errstr = "The operation did not complete (write)"; break; case SSL_ERROR_WANT_X509_LOOKUP: @@ -796,7 +635,7 @@ PySSL_SetError(PySSLSocket *sslsock, int ret, const char *filename, int lineno) PySocketSockObject *s = GET_SOCKET(sslsock); if (ret == 0 || (((PyObject *)s) == Py_None)) { p = PY_SSL_ERROR_EOF; - type = PySSLEOFErrorObject; + type = state->PySSLEOFErrorObject; errstr = "EOF occurred in violation of protocol"; } else if (s && ret == -1) { /* underlying BIO reported an I/O error */ @@ -812,12 +651,12 @@ PySSL_SetError(PySSLSocket *sslsock, int ret, const char *filename, int lineno) } else { p = PY_SSL_ERROR_EOF; - type = PySSLEOFErrorObject; + type = state->PySSLEOFErrorObject; errstr = "EOF occurred in violation of protocol"; } } else { /* possible? */ p = PY_SSL_ERROR_SYSCALL; - type = PySSLSyscallErrorObject; + type = state->PySSLSyscallErrorObject; errstr = "Some I/O error occurred"; } } else { @@ -834,7 +673,7 @@ PySSL_SetError(PySSLSocket *sslsock, int ret, const char *filename, int lineno) } if (ERR_GET_LIB(e) == ERR_LIB_SSL && ERR_GET_REASON(e) == SSL_R_CERTIFICATE_VERIFY_FAILED) { - type = PySSLCertVerificationErrorObject; + type = state->PySSLCertVerificationErrorObject; } break; } @@ -843,24 +682,34 @@ PySSL_SetError(PySSLSocket *sslsock, int ret, const char *filename, int lineno) errstr = "Invalid error code"; } } - fill_and_set_sslerror(sslsock, type, p, errstr, lineno, e); + fill_and_set_sslerror(state, sslsock, type, p, errstr, lineno, e); ERR_clear_error(); PySSL_ChainExceptions(sslsock); return NULL; } static PyObject * -_setSSLError (const char *errstr, int errcode, const char *filename, int lineno) { - +_setSSLError (_sslmodulestate *state, const char *errstr, int errcode, const char *filename, int lineno) +{ if (errstr == NULL) errcode = ERR_peek_last_error(); else errcode = 0; - fill_and_set_sslerror(NULL, PySSLErrorObject, errcode, errstr, lineno, errcode); + fill_and_set_sslerror(state, NULL, state->PySSLErrorObject, errcode, errstr, lineno, errcode); ERR_clear_error(); return NULL; } +static int +_ssl_deprecated(const char* msg, int stacklevel) { + return PyErr_WarnEx( + PyExc_DeprecationWarning, msg, stacklevel + ); +} + +#define PY_SSL_DEPRECATED(name, stacklevel, ret) \ + if (_ssl_deprecated((name), (stacklevel)) == -1) return (ret) + /* * SSL objects */ @@ -903,7 +752,7 @@ _ssl_configure_hostname(PySSLSocket *self, const char* server_hostname) /* Only send SNI extension for non-IP hostnames */ if (ip == NULL) { if (!SSL_set_tlsext_host_name(self->ssl, server_hostname)) { - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(get_state_sock(self), NULL, 0, __FILE__, __LINE__); goto error; } } @@ -912,13 +761,13 @@ _ssl_configure_hostname(PySSLSocket *self, const char* server_hostname) if (ip == NULL) { if (!X509_VERIFY_PARAM_set1_host(param, server_hostname, strlen(server_hostname))) { - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(get_state_sock(self), NULL, 0, __FILE__, __LINE__); goto error; } } else { if (!X509_VERIFY_PARAM_set1_ip(param, ASN1_STRING_get0_data(ip), ASN1_STRING_length(ip))) { - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(get_state_sock(self), NULL, 0, __FILE__, __LINE__); goto error; } } @@ -942,7 +791,23 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, SSL_CTX *ctx = sslctx->ctx; _PySSLError err = { 0 }; - self = PyObject_New(PySSLSocket, &PySSLSocket_Type); + if ((socket_type == PY_SSL_SERVER) && + (sslctx->protocol == PY_SSL_VERSION_TLS_CLIENT)) { + _setSSLError(get_state_ctx(sslctx), + "Cannot create a server socket with a " + "PROTOCOL_TLS_CLIENT context", 0, __FILE__, __LINE__); + return NULL; + } + if ((socket_type == PY_SSL_CLIENT) && + (sslctx->protocol == PY_SSL_VERSION_TLS_SERVER)) { + _setSSLError(get_state_ctx(sslctx), + "Cannot create a client socket with a " + "PROTOCOL_TLS_SERVER context", 0, __FILE__, __LINE__); + return NULL; + } + + self = PyObject_GC_New(PySSLSocket, + get_state_ctx(sslctx)->PySSLSocket_Type); if (self == NULL) return NULL; @@ -966,7 +831,7 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, PySSL_END_ALLOW_THREADS if (self->ssl == NULL) { Py_DECREF(self); - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(get_state_ctx(self), NULL, 0, __FILE__, __LINE__); return NULL; } /* bpo43522 and OpenSSL < 1.1.1l: copy hostflags manually */ @@ -1049,6 +914,8 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, return NULL; } } + + PyObject_GC_Track(self); return self; } @@ -1071,7 +938,8 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self) if (sock) { if (((PyObject*)sock) == Py_None) { - _setSSLError("Underlying socket connection gone", + _setSSLError(get_state_sock(self), + "Underlying socket connection gone", PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__); return NULL; } @@ -1112,15 +980,15 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self) } if (sockstate == SOCKET_HAS_TIMED_OUT) { - PyErr_SetString(PySocketModule.timeout_error, + PyErr_SetString(PyExc_TimeoutError, ERRSTR("The handshake operation timed out")); goto error; } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { - PyErr_SetString(PySSLErrorObject, + PyErr_SetString(get_state_sock(self)->PySSLErrorObject, ERRSTR("Underlying socket has been closed.")); goto error; } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) { - PyErr_SetString(PySSLErrorObject, + PyErr_SetString(get_state_sock(self)->PySSLErrorObject, ERRSTR("Underlying socket too large for select().")); goto error; } else if (sockstate == SOCKET_IS_NONBLOCKING) { @@ -1141,7 +1009,7 @@ error: } static PyObject * -_asn1obj2py(const ASN1_OBJECT *name, int no_name) +_asn1obj2py(_sslmodulestate *state, const ASN1_OBJECT *name, int no_name) { char buf[X509_NAME_MAXLEN]; char *namebuf = buf; @@ -1150,7 +1018,7 @@ _asn1obj2py(const ASN1_OBJECT *name, int no_name) buflen = OBJ_obj2txt(namebuf, X509_NAME_MAXLEN, name, no_name); if (buflen < 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(state, NULL, 0, __FILE__, __LINE__); return NULL; } /* initial buffer is too small for oid + terminating null byte */ @@ -1165,7 +1033,7 @@ _asn1obj2py(const ASN1_OBJECT *name, int no_name) } buflen = OBJ_obj2txt(namebuf, buflen + 1, name, no_name); if (buflen < 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(state, NULL, 0, __FILE__, __LINE__); goto done; } } @@ -1185,24 +1053,37 @@ _asn1obj2py(const ASN1_OBJECT *name, int no_name) } static PyObject * -_create_tuple_for_attribute(ASN1_OBJECT *name, ASN1_STRING *value) +_create_tuple_for_attribute(_sslmodulestate *state, + ASN1_OBJECT *name, ASN1_STRING *value) { Py_ssize_t buflen; - unsigned char *valuebuf = NULL; - PyObject *attr; + PyObject *pyattr; + PyObject *pyname = _asn1obj2py(state, name, 0); - buflen = ASN1_STRING_to_UTF8(&valuebuf, value); - if (buflen < 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); + if (pyname == NULL) { + _setSSLError(state, NULL, 0, __FILE__, __LINE__); return NULL; } - attr = Py_BuildValue("Ns#", _asn1obj2py(name, 0), valuebuf, buflen); - OPENSSL_free(valuebuf); - return attr; + + if (ASN1_STRING_type(value) == V_ASN1_BIT_STRING) { + buflen = ASN1_STRING_length(value); + pyattr = Py_BuildValue("Ny#", pyname, ASN1_STRING_get0_data(value), buflen); + } else { + unsigned char *valuebuf = NULL; + buflen = ASN1_STRING_to_UTF8(&valuebuf, value); + if (buflen < 0) { + _setSSLError(state, NULL, 0, __FILE__, __LINE__); + Py_DECREF(pyname); + return NULL; + } + pyattr = Py_BuildValue("Ns#", pyname, valuebuf, buflen); + OPENSSL_free(valuebuf); + } + return pyattr; } static PyObject * -_create_tuple_for_X509_NAME (X509_NAME *xname) +_create_tuple_for_X509_NAME (_sslmodulestate *state, X509_NAME *xname) { PyObject *dn = NULL; /* tuple which represents the "distinguished name" */ PyObject *rdn = NULL; /* tuple to hold a "relative distinguished name" */ @@ -1254,7 +1135,7 @@ _create_tuple_for_X509_NAME (X509_NAME *xname) /* now add this attribute to the current RDN */ name = X509_NAME_ENTRY_get_object(entry); value = X509_NAME_ENTRY_get_data(entry); - attr = _create_tuple_for_attribute(name, value); + attr = _create_tuple_for_attribute(state, name, value); /* fprintf(stderr, "RDN level %d, attribute %s: %s\n", entry->set, @@ -1301,7 +1182,7 @@ _create_tuple_for_X509_NAME (X509_NAME *xname) } static PyObject * -_get_peer_alt_names (X509 *certificate) { +_get_peer_alt_names (_sslmodulestate *state, X509 *certificate) { /* this code follows the procedure outlined in OpenSSL's crypto/x509v3/v3_prn.c:X509v3_EXT_print() @@ -1325,7 +1206,7 @@ _get_peer_alt_names (X509 *certificate) { /* get a memory buffer */ biobuf = BIO_new(BIO_s_mem()); if (biobuf == NULL) { - PyErr_SetString(PySSLErrorObject, "failed to allocate BIO"); + PyErr_SetString(state->PySSLErrorObject, "failed to allocate BIO"); return NULL; } @@ -1362,7 +1243,7 @@ _get_peer_alt_names (X509 *certificate) { } PyTuple_SET_ITEM(t, 0, v); - v = _create_tuple_for_X509_NAME (name->d.dirn); + v = _create_tuple_for_X509_NAME(state, name->d.dirn); if (v == NULL) { Py_DECREF(t); goto fail; @@ -1421,7 +1302,7 @@ _get_peer_alt_names (X509 *certificate) { len = i2t_ASN1_OBJECT(buf, sizeof(buf)-1, name->d.rid); if (len < 0) { Py_DECREF(t); - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(state, NULL, 0, __FILE__, __LINE__); goto fail; } else if (len >= (int)sizeof(buf)) { v = PyUnicode_FromString("<INVALID>"); @@ -1504,7 +1385,7 @@ _get_peer_alt_names (X509 *certificate) { GENERAL_NAME_print(biobuf, name); len = BIO_gets(biobuf, buf, sizeof(buf)-1); if (len < 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(state, NULL, 0, __FILE__, __LINE__); goto fail; } vptr = strchr(buf, ':'); @@ -1680,7 +1561,7 @@ _get_crl_dp(X509 *certificate) { } static PyObject * -_decode_certificate(X509 *certificate) { +_decode_certificate(_sslmodulestate *state, X509 *certificate) { PyObject *retval = NULL; BIO *biobuf = NULL; @@ -1701,6 +1582,7 @@ _decode_certificate(X509 *certificate) { return NULL; peer = _create_tuple_for_X509_NAME( + state, X509_get_subject_name(certificate)); if (peer == NULL) goto fail0; @@ -1711,6 +1593,7 @@ _decode_certificate(X509 *certificate) { Py_DECREF(peer); issuer = _create_tuple_for_X509_NAME( + state, X509_get_issuer_name(certificate)); if (issuer == NULL) goto fail0; @@ -1732,7 +1615,7 @@ _decode_certificate(X509 *certificate) { /* get a memory buffer */ biobuf = BIO_new(BIO_s_mem()); if (biobuf == NULL) { - PyErr_SetString(PySSLErrorObject, "failed to allocate BIO"); + PyErr_SetString(state->PySSLErrorObject, "failed to allocate BIO"); goto fail0; } @@ -1742,7 +1625,7 @@ _decode_certificate(X509 *certificate) { i2a_ASN1_INTEGER(biobuf, serialNumber); len = BIO_gets(biobuf, buf, sizeof(buf)-1); if (len < 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(state, NULL, 0, __FILE__, __LINE__); goto fail1; } sn_obj = PyUnicode_FromStringAndSize(buf, len); @@ -1759,7 +1642,7 @@ _decode_certificate(X509 *certificate) { ASN1_TIME_print(biobuf, notBefore); len = BIO_gets(biobuf, buf, sizeof(buf)-1); if (len < 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(state, NULL, 0, __FILE__, __LINE__); goto fail1; } pnotBefore = PyUnicode_FromStringAndSize(buf, len); @@ -1776,7 +1659,7 @@ _decode_certificate(X509 *certificate) { ASN1_TIME_print(biobuf, notAfter); len = BIO_gets(biobuf, buf, sizeof(buf)-1); if (len < 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(state, NULL, 0, __FILE__, __LINE__); goto fail1; } pnotAfter = PyUnicode_FromStringAndSize(buf, len); @@ -1790,7 +1673,7 @@ _decode_certificate(X509 *certificate) { /* Now look for subjectAltName */ - peer_alt_names = _get_peer_alt_names(certificate); + peer_alt_names = _get_peer_alt_names(state, certificate); if (peer_alt_names == NULL) goto fail1; else if (peer_alt_names != Py_None) { @@ -1849,7 +1732,7 @@ _decode_certificate(X509 *certificate) { } static PyObject * -_certificate_to_der(X509 *certificate) +_certificate_to_der(_sslmodulestate *state, X509 *certificate) { unsigned char *bytes_buf = NULL; int len; @@ -1858,7 +1741,7 @@ _certificate_to_der(X509 *certificate) bytes_buf = NULL; len = i2d_X509(certificate, &bytes_buf); if (len < 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(state, NULL, 0, __FILE__, __LINE__); return NULL; } /* this is actually an immutable bytes sequence */ @@ -1867,6 +1750,9 @@ _certificate_to_der(X509 *certificate) return retval; } +#include "_ssl/misc.c" +#include "_ssl/cert.c" + /*[clinic input] _ssl._test_decode_cert path: object(converter="PyUnicode_FSConverter") @@ -1881,27 +1767,28 @@ _ssl__test_decode_cert_impl(PyObject *module, PyObject *path) PyObject *retval = NULL; X509 *x=NULL; BIO *cert; + _sslmodulestate *state = get_ssl_state(module); if ((cert=BIO_new(BIO_s_file())) == NULL) { - PyErr_SetString(PySSLErrorObject, + PyErr_SetString(state->PySSLErrorObject, "Can't malloc memory to read file"); goto fail0; } if (BIO_read_filename(cert, PyBytes_AsString(path)) <= 0) { - PyErr_SetString(PySSLErrorObject, + PyErr_SetString(state->PySSLErrorObject, "Can't open file"); goto fail0; } x = PEM_read_bio_X509(cert, NULL, NULL, NULL); if (x == NULL) { - PyErr_SetString(PySSLErrorObject, + PyErr_SetString(state->PySSLErrorObject, "Error decoding PEM-encoded file"); goto fail0; } - retval = _decode_certificate(x); + retval = _decode_certificate(state, x); X509_free(x); fail0: @@ -1946,18 +1833,82 @@ _ssl__SSLSocket_getpeercert_impl(PySSLSocket *self, int binary_mode) if (binary_mode) { /* return cert in DER-encoded format */ - result = _certificate_to_der(peer_cert); + result = _certificate_to_der(get_state_sock(self), peer_cert); } else { verification = SSL_CTX_get_verify_mode(SSL_get_SSL_CTX(self->ssl)); if ((verification & SSL_VERIFY_PEER) == 0) result = PyDict_New(); else - result = _decode_certificate(peer_cert); + result = _decode_certificate(get_state_sock(self), peer_cert); } X509_free(peer_cert); return result; } +/*[clinic input] +_ssl._SSLSocket.get_verified_chain + +[clinic start generated code]*/ + +static PyObject * +_ssl__SSLSocket_get_verified_chain_impl(PySSLSocket *self) +/*[clinic end generated code: output=802421163cdc3110 input=5fb0714f77e2bd51]*/ +{ + /* borrowed reference */ + STACK_OF(X509) *chain = SSL_get0_verified_chain(self->ssl); + if (chain == NULL) { + Py_RETURN_NONE; + } + return _PySSL_CertificateFromX509Stack(self->ctx->state, chain, 1); +} + +/*[clinic input] +_ssl._SSLSocket.get_unverified_chain + +[clinic start generated code]*/ + +static PyObject * +_ssl__SSLSocket_get_unverified_chain_impl(PySSLSocket *self) +/*[clinic end generated code: output=5acdae414e13f913 input=78c33c360c635cb5]*/ +{ + PyObject *retval; + /* borrowed reference */ + /* TODO: include SSL_get_peer_certificate() for server-side sockets */ + STACK_OF(X509) *chain = SSL_get_peer_cert_chain(self->ssl); + if (chain == NULL) { + Py_RETURN_NONE; + } + retval = _PySSL_CertificateFromX509Stack(self->ctx->state, chain, 1); + if (retval == NULL) { + return NULL; + } + /* OpenSSL does not include peer cert for server side connections */ + if (self->socket_type == PY_SSL_SERVER) { + PyObject *peerobj = NULL; + X509 *peer = SSL_get_peer_certificate(self->ssl); + + if (peer == NULL) { + peerobj = Py_None; + Py_INCREF(peerobj); + } else { + /* consume X509 reference on success */ + peerobj = _PySSL_CertificateFromX509(self->ctx->state, peer, 0); + if (peerobj == NULL) { + X509_free(peer); + Py_DECREF(retval); + return NULL; + } + } + int res = PyList_Insert(retval, 0, peerobj); + Py_DECREF(peerobj); + if (res < 0) { + Py_DECREF(retval); + return NULL; + } + } + return retval; +} + static PyObject * cipher_to_tuple(const SSL_CIPHER *cipher) { @@ -2000,7 +1951,6 @@ cipher_to_tuple(const SSL_CIPHER *cipher) return NULL; } -#if OPENSSL_VERSION_NUMBER >= 0x10002000UL static PyObject * cipher_to_dict(const SSL_CIPHER *cipher) { @@ -2009,10 +1959,8 @@ cipher_to_dict(const SSL_CIPHER *cipher) unsigned long cipher_id; int alg_bits, strength_bits, len; char buf[512] = {0}; -#if OPENSSL_VERSION_1_1 int aead, nid; const char *skcipher = NULL, *digest = NULL, *kx = NULL, *auth = NULL; -#endif /* can be NULL */ cipher_name = SSL_CIPHER_get_name(cipher); @@ -2025,7 +1973,6 @@ cipher_to_dict(const SSL_CIPHER *cipher) buf[len-1] = '\0'; strength_bits = SSL_CIPHER_get_bits(cipher, &alg_bits); -#if OPENSSL_VERSION_1_1 aead = SSL_CIPHER_is_aead(cipher); nid = SSL_CIPHER_get_cipher_nid(cipher); skcipher = nid != NID_undef ? OBJ_nid2ln(nid) : NULL; @@ -2035,13 +1982,10 @@ cipher_to_dict(const SSL_CIPHER *cipher) kx = nid != NID_undef ? OBJ_nid2ln(nid) : NULL; nid = SSL_CIPHER_get_auth_nid(cipher); auth = nid != NID_undef ? OBJ_nid2ln(nid) : NULL; -#endif return Py_BuildValue( "{sksssssssisi" -#if OPENSSL_VERSION_1_1 "sOssssssss" -#endif "}", "id", cipher_id, "name", cipher_name, @@ -2049,16 +1993,13 @@ cipher_to_dict(const SSL_CIPHER *cipher) "description", buf, "strength_bits", strength_bits, "alg_bits", alg_bits -#if OPENSSL_VERSION_1_1 ,"aead", aead ? Py_True : Py_False, "symmetric", skcipher, "digest", digest, "kea", kx, "auth", auth -#endif ); } -#endif /*[clinic input] _ssl._SSLSocket.shared_ciphers @@ -2129,28 +2070,6 @@ _ssl__SSLSocket_version_impl(PySSLSocket *self) return PyUnicode_FromString(version); } -#if HAVE_NPN -/*[clinic input] -_ssl._SSLSocket.selected_npn_protocol -[clinic start generated code]*/ - -static PyObject * -_ssl__SSLSocket_selected_npn_protocol_impl(PySSLSocket *self) -/*[clinic end generated code: output=b91d494cd207ecf6 input=c28fde139204b826]*/ -{ - const unsigned char *out; - unsigned int outlen; - - SSL_get0_next_proto_negotiated(self->ssl, - &out, &outlen); - - if (out == NULL) - Py_RETURN_NONE; - return PyUnicode_FromStringAndSize((char *)out, outlen); -} -#endif - -#if HAVE_ALPN /*[clinic input] _ssl._SSLSocket.selected_alpn_protocol [clinic start generated code]*/ @@ -2168,7 +2087,6 @@ _ssl__SSLSocket_selected_alpn_protocol_impl(PySSLSocket *self) Py_RETURN_NONE; return PyUnicode_FromStringAndSize((char *)out, outlen); } -#endif /*[clinic input] _ssl._SSLSocket.compression @@ -2204,12 +2122,7 @@ static PySSLContext *PySSL_get_context(PySSLSocket *self, void *closure) { static int PySSL_set_context(PySSLSocket *self, PyObject *value, void *closure) { - if (PyObject_TypeCheck(value, &PySSLContext_Type)) { -#if !HAVE_SNI - PyErr_SetString(PyExc_NotImplementedError, "setting a socket's " - "context is not supported by your OpenSSL library"); - return -1; -#else + if (PyObject_TypeCheck(value, self->ctx->state->PySSLContext_Type)) { Py_INCREF(value); Py_SETREF(self->ctx, (PySSLContext *)value); SSL_set_SSL_CTX(self->ssl, self->ctx->ctx); @@ -2218,7 +2131,6 @@ static int PySSL_set_context(PySSLSocket *self, PyObject *value, self->ssl, self->ctx->msg_cb ? _PySSL_msg_callback : NULL ); -#endif } else { PyErr_SetString(PyExc_TypeError, "The value must be a SSLContext"); return -1; @@ -2289,6 +2201,7 @@ PySSL_traverse(PySSLSocket *self, visitproc visit, void *arg) Py_VISIT(self->exc_type); Py_VISIT(self->exc_value); Py_VISIT(self->exc_tb); + Py_VISIT(Py_TYPE(self)); return 0; } @@ -2304,13 +2217,17 @@ PySSL_clear(PySSLSocket *self) static void PySSL_dealloc(PySSLSocket *self) { - if (self->ssl) + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); + if (self->ssl) { SSL_free(self->ssl); + } Py_XDECREF(self->Socket); Py_XDECREF(self->ctx); Py_XDECREF(self->server_hostname); Py_XDECREF(self->owner); - PyObject_Del(self); + PyObject_GC_Del(self); + Py_DECREF(tp); } /* If the socket has a timeout, do a select()/poll() on the socket. @@ -2397,7 +2314,8 @@ static PyObject * _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b) /*[clinic end generated code: output=aa7a6be5527358d8 input=77262d994fe5100a]*/ { - int len; + size_t count = 0; + int retval; int sockstate; _PySSLError err; int nonblocking; @@ -2407,19 +2325,14 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b) if (sock != NULL) { if (((PyObject*)sock) == Py_None) { - _setSSLError("Underlying socket connection gone", + _setSSLError(get_state_sock(self), + "Underlying socket connection gone", PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__); return NULL; } Py_INCREF(sock); } - if (b->len > INT_MAX) { - PyErr_Format(PyExc_OverflowError, - "string longer than %d bytes", INT_MAX); - goto error; - } - if (sock != NULL) { /* just in case the blocking state of the socket has been changed */ nonblocking = (sock->sock_timeout >= 0); @@ -2434,23 +2347,23 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b) sockstate = PySSL_select(sock, 1, timeout); if (sockstate == SOCKET_HAS_TIMED_OUT) { - PyErr_SetString(PySocketModule.timeout_error, + PyErr_SetString(PyExc_TimeoutError, "The write operation timed out"); goto error; } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { - PyErr_SetString(PySSLErrorObject, + PyErr_SetString(get_state_sock(self)->PySSLErrorObject, "Underlying socket has been closed."); goto error; } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) { - PyErr_SetString(PySSLErrorObject, + PyErr_SetString(get_state_sock(self)->PySSLErrorObject, "Underlying socket too large for select()."); goto error; } do { PySSL_BEGIN_ALLOW_THREADS - len = SSL_write(self->ssl, b->buf, (int)b->len); - err = _PySSL_errno(len <= 0, self->ssl, len); + retval = SSL_write_ex(self->ssl, b->buf, (size_t)b->len, &count); + err = _PySSL_errno(retval == 0, self->ssl, retval); PySSL_END_ALLOW_THREADS self->err = err; @@ -2469,11 +2382,11 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b) } if (sockstate == SOCKET_HAS_TIMED_OUT) { - PyErr_SetString(PySocketModule.timeout_error, + PyErr_SetString(PyExc_TimeoutError, "The write operation timed out"); goto error; } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { - PyErr_SetString(PySSLErrorObject, + PyErr_SetString(get_state_sock(self)->PySSLErrorObject, "Underlying socket has been closed."); goto error; } else if (sockstate == SOCKET_IS_NONBLOCKING) { @@ -2483,11 +2396,11 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b) err.ssl == SSL_ERROR_WANT_WRITE); Py_XDECREF(sock); - if (len <= 0) - return PySSL_SetError(self, len, __FILE__, __LINE__); + if (retval == 0) + return PySSL_SetError(self, retval, __FILE__, __LINE__); if (PySSL_ChainExceptions(self) < 0) return NULL; - return PyLong_FromLong(len); + return PyLong_FromSize_t(count); error: Py_XDECREF(sock); PySSL_ChainExceptions(self); @@ -2521,7 +2434,7 @@ _ssl__SSLSocket_pending_impl(PySSLSocket *self) /*[clinic input] _ssl._SSLSocket.read - size as len: int + size as len: Py_ssize_t [ buffer: Py_buffer(accept={rwbuffer}) ] @@ -2531,13 +2444,14 @@ Read up to size bytes from the SSL socket. [clinic start generated code]*/ static PyObject * -_ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1, - Py_buffer *buffer) -/*[clinic end generated code: output=00097776cec2a0af input=ff157eb918d0905b]*/ +_ssl__SSLSocket_read_impl(PySSLSocket *self, Py_ssize_t len, + int group_right_1, Py_buffer *buffer) +/*[clinic end generated code: output=49b16e6406023734 input=ec48bf622be1c4a1]*/ { PyObject *dest = NULL; char *mem; - int count; + size_t count = 0; + int retval; int sockstate; _PySSLError err; int nonblocking; @@ -2552,7 +2466,8 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1, if (sock != NULL) { if (((PyObject*)sock) == Py_None) { - _setSSLError("Underlying socket connection gone", + _setSSLError(get_state_sock(self), + "Underlying socket connection gone", PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__); return NULL; } @@ -2599,8 +2514,8 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1, do { PySSL_BEGIN_ALLOW_THREADS - count = SSL_read(self->ssl, mem, len); - err = _PySSL_errno(count <= 0, self->ssl, count); + retval = SSL_read_ex(self->ssl, mem, (size_t)len, &count); + err = _PySSL_errno(retval == 0, self->ssl, retval); PySSL_END_ALLOW_THREADS self->err = err; @@ -2624,7 +2539,7 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1, sockstate = SOCKET_OPERATION_OK; if (sockstate == SOCKET_HAS_TIMED_OUT) { - PyErr_SetString(PySocketModule.timeout_error, + PyErr_SetString(PyExc_TimeoutError, "The read operation timed out"); goto error; } else if (sockstate == SOCKET_IS_NONBLOCKING) { @@ -2633,8 +2548,8 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1, } while (err.ssl == SSL_ERROR_WANT_READ || err.ssl == SSL_ERROR_WANT_WRITE); - if (count <= 0) { - PySSL_SetError(self, count, __FILE__, __LINE__); + if (retval == 0) { + PySSL_SetError(self, retval, __FILE__, __LINE__); goto error; } if (self->exc_type != NULL) @@ -2647,7 +2562,7 @@ done: return dest; } else { - return PyLong_FromLong(count); + return PyLong_FromSize_t(count); } error: @@ -2678,7 +2593,8 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self) if (sock != NULL) { /* Guard against closed socket */ if ((((PyObject*)sock) == Py_None) || (sock->sock_fd == INVALID_SOCKET)) { - _setSSLError("Underlying socket connection gone", + _setSSLError(get_state_sock(self), + "Underlying socket connection gone", PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__); return NULL; } @@ -2739,15 +2655,15 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self) if (sockstate == SOCKET_HAS_TIMED_OUT) { if (err.ssl == SSL_ERROR_WANT_READ) - PyErr_SetString(PySocketModule.timeout_error, + PyErr_SetString(PyExc_TimeoutError, "The read operation timed out"); else - PyErr_SetString(PySocketModule.timeout_error, + PyErr_SetString(PyExc_TimeoutError, "The write operation timed out"); goto error; } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) { - PyErr_SetString(PySSLErrorObject, + PyErr_SetString(get_state_sock(self)->PySSLErrorObject, "Underlying socket too large for select()."); goto error; } @@ -2832,7 +2748,7 @@ _ssl__SSLSocket_verify_client_post_handshake_impl(PySSLSocket *self) #ifdef TLS1_3_VERSION int err = SSL_verify_client_post_handshake(self->ssl); if (err == 0) - return _setSSLError(NULL, 0, __FILE__, __LINE__); + return _setSSLError(get_state_sock(self), NULL, 0, __FILE__, __LINE__); else Py_RETURN_NONE; #else @@ -2843,8 +2759,6 @@ _ssl__SSLSocket_verify_client_post_handshake_impl(PySSLSocket *self) #endif } -#ifdef OPENSSL_VERSION_1_1 - static SSL_SESSION* _ssl_session_dup(SSL_SESSION *session) { SSL_SESSION *newsession = NULL; @@ -2885,7 +2799,6 @@ _ssl_session_dup(SSL_SESSION *session) { } return NULL; } -#endif static PyObject * PySSL_get_session(PySSLSocket *self, void *closure) { @@ -2894,7 +2807,6 @@ PySSL_get_session(PySSLSocket *self, void *closure) { PySSLSession *pysess; SSL_SESSION *session; -#ifdef OPENSSL_VERSION_1_1 /* duplicate session as workaround for session bug in OpenSSL 1.1.0, * https://github.com/openssl/openssl/issues/1550 */ session = SSL_get0_session(self->ssl); /* borrowed reference */ @@ -2904,13 +2816,11 @@ PySSL_get_session(PySSLSocket *self, void *closure) { if ((session = _ssl_session_dup(session)) == NULL) { return NULL; } -#else session = SSL_get1_session(self->ssl); if (session == NULL) { Py_RETURN_NONE; } -#endif - pysess = PyObject_GC_New(PySSLSession, &PySSLSession_Type); + pysess = PyObject_GC_New(PySSLSession, self->ctx->state->PySSLSession_Type); if (pysess == NULL) { SSL_SESSION_free(session); return NULL; @@ -2928,12 +2838,10 @@ static int PySSL_set_session(PySSLSocket *self, PyObject *value, void *closure) { PySSLSession *pysess; -#ifdef OPENSSL_VERSION_1_1 SSL_SESSION *session; -#endif int result; - if (!PySSLSession_Check(value)) { + if (!Py_IS_TYPE(value, get_state_sock(self)->PySSLSession_Type)) { PyErr_SetString(PyExc_TypeError, "Value is not a SSLSession."); return -1; } @@ -2954,7 +2862,6 @@ static int PySSL_set_session(PySSLSocket *self, PyObject *value, "Cannot set session after handshake."); return -1; } -#ifdef OPENSSL_VERSION_1_1 /* duplicate session */ if ((session = _ssl_session_dup(pysess->session)) == NULL) { return -1; @@ -2962,11 +2869,8 @@ static int PySSL_set_session(PySSLSocket *self, PyObject *value, result = SSL_set_session(self->ssl, session); /* free duplicate, SSL_set_session() bumps ref count */ SSL_SESSION_free(session); -#else - result = SSL_set_session(self->ssl, pysess->session); -#endif if (result == 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(get_state_sock(self), NULL, 0, __FILE__, __LINE__); return -1; } return 0; @@ -3015,48 +2919,31 @@ static PyMethodDef PySSLMethods[] = { _SSL__SSLSOCKET_CIPHER_METHODDEF _SSL__SSLSOCKET_SHARED_CIPHERS_METHODDEF _SSL__SSLSOCKET_VERSION_METHODDEF - _SSL__SSLSOCKET_SELECTED_NPN_PROTOCOL_METHODDEF _SSL__SSLSOCKET_SELECTED_ALPN_PROTOCOL_METHODDEF _SSL__SSLSOCKET_COMPRESSION_METHODDEF _SSL__SSLSOCKET_SHUTDOWN_METHODDEF _SSL__SSLSOCKET_VERIFY_CLIENT_POST_HANDSHAKE_METHODDEF + _SSL__SSLSOCKET_GET_UNVERIFIED_CHAIN_METHODDEF + _SSL__SSLSOCKET_GET_VERIFIED_CHAIN_METHODDEF {NULL, NULL} }; -static PyTypeObject PySSLSocket_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_ssl._SSLSocket", /*tp_name*/ - sizeof(PySSLSocket), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)PySSL_dealloc, /*tp_dealloc*/ - 0, /*tp_vectorcall_offset*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_as_async*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - 0, /*tp_doc*/ - (traverseproc) PySSL_traverse, /*tp_traverse*/ - (inquiry) PySSL_clear, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - PySSLMethods, /*tp_methods*/ - 0, /*tp_members*/ - ssl_getsetlist, /*tp_getset*/ +static PyType_Slot PySSLSocket_slots[] = { + {Py_tp_methods, PySSLMethods}, + {Py_tp_getset, ssl_getsetlist}, + {Py_tp_dealloc, PySSL_dealloc}, + {Py_tp_traverse, PySSL_traverse}, + {Py_tp_clear, PySSL_clear}, + {0, 0}, }; +static PyType_Spec PySSLSocket_spec = { + .name = "_ssl._SSLSocket", + .basicsize = sizeof(PySSLSocket), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | + Py_TPFLAGS_HAVE_GC), + .slots = PySSLSocket_slots, +}; /* * _SSLContext objects @@ -3106,63 +2993,78 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version) { PySSLContext *self; long options; + const SSL_METHOD *method = NULL; SSL_CTX *ctx = NULL; X509_VERIFY_PARAM *params; int result; -#if defined(SSL_MODE_RELEASE_BUFFERS) - unsigned long libver; -#endif - PySSL_BEGIN_ALLOW_THREADS + /* slower approach, walk MRO and get borrowed reference to module. + * _PyType_GetModuleByDef is required for SSLContext subclasses */ + PyObject *module = _PyType_GetModuleByDef(type, &_sslmodule_def); + if (module == NULL) { + PyErr_SetString(PyExc_RuntimeError, + "Cannot find internal module state"); + return NULL; + } + switch(proto_version) { #if defined(SSL3_VERSION) && !defined(OPENSSL_NO_SSL3) case PY_SSL_VERSION_SSL3: - ctx = SSL_CTX_new(SSLv3_method()); + PY_SSL_DEPRECATED("ssl.PROTOCOL_SSLv3 is deprecated", 2, NULL); + method = SSLv3_method(); break; #endif #if (defined(TLS1_VERSION) && \ !defined(OPENSSL_NO_TLS1) && \ !defined(OPENSSL_NO_TLS1_METHOD)) case PY_SSL_VERSION_TLS1: - ctx = SSL_CTX_new(TLSv1_method()); + PY_SSL_DEPRECATED("ssl.PROTOCOL_TLSv1 is deprecated", 2, NULL); + method = TLSv1_method(); break; #endif #if (defined(TLS1_1_VERSION) && \ !defined(OPENSSL_NO_TLS1_1) && \ !defined(OPENSSL_NO_TLS1_1_METHOD)) case PY_SSL_VERSION_TLS1_1: - ctx = SSL_CTX_new(TLSv1_1_method()); + PY_SSL_DEPRECATED("ssl.PROTOCOL_TLSv1_1 is deprecated", 2, NULL); + method = TLSv1_1_method(); break; #endif #if (defined(TLS1_2_VERSION) && \ !defined(OPENSSL_NO_TLS1_2) && \ !defined(OPENSSL_NO_TLS1_2_METHOD)) case PY_SSL_VERSION_TLS1_2: - ctx = SSL_CTX_new(TLSv1_2_method()); + PY_SSL_DEPRECATED("ssl.PROTOCOL_TLSv1_2 is deprecated", 2, NULL); + method = TLSv1_2_method(); break; #endif case PY_SSL_VERSION_TLS: - /* SSLv23 */ - ctx = SSL_CTX_new(TLS_method()); + PY_SSL_DEPRECATED("ssl.PROTOCOL_TLS is deprecated", 2, NULL); + method = TLS_method(); break; case PY_SSL_VERSION_TLS_CLIENT: - ctx = SSL_CTX_new(TLS_client_method()); + method = TLS_client_method(); break; case PY_SSL_VERSION_TLS_SERVER: - ctx = SSL_CTX_new(TLS_server_method()); + method = TLS_server_method(); break; default: - proto_version = -1; + method = NULL; } - PySSL_END_ALLOW_THREADS - if (proto_version == -1) { - PyErr_SetString(PyExc_ValueError, - "invalid or unsupported protocol version"); + if (method == NULL) { + PyErr_Format(PyExc_ValueError, + "invalid or unsupported protocol version %i", + proto_version); return NULL; } + + PySSL_BEGIN_ALLOW_THREADS + ctx = SSL_CTX_new(method); + PySSL_END_ALLOW_THREADS + if (ctx == NULL) { - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(get_ssl_state(module), NULL, 0, __FILE__, __LINE__); return NULL; } @@ -3176,19 +3078,12 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version) self->hostflags = X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS; self->protocol = proto_version; self->msg_cb = NULL; -#ifdef HAVE_OPENSSL_KEYLOG self->keylog_filename = NULL; self->keylog_bio = NULL; -#endif -#if HAVE_NPN - self->npn_protocols = NULL; -#endif -#if HAVE_ALPN self->alpn_protocols = NULL; -#endif -#ifndef OPENSSL_NO_TLSEXT self->set_sni_cb = NULL; -#endif + self->state = get_ssl_state(module); + /* Don't check host name by default */ if (proto_version == PY_SSL_VERSION_TLS_CLIENT) { self->check_hostname = 1; @@ -3245,42 +3140,31 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version) if (result == 0) { Py_DECREF(self); ERR_clear_error(); - PyErr_SetString(PySSLErrorObject, + PyErr_SetString(get_state_ctx(self)->PySSLErrorObject, "No cipher can be selected."); - return NULL; + goto error; } - -#if defined(SSL_MODE_RELEASE_BUFFERS) - /* Set SSL_MODE_RELEASE_BUFFERS. This potentially greatly reduces memory - usage for no cost at all. However, don't do this for OpenSSL versions - between 1.0.1 and 1.0.1h or 1.0.0 and 1.0.0m, which are affected by CVE - 2014-0198. I can't find exactly which beta fixed this CVE, so be - conservative and assume it wasn't fixed until release. We do this check - at runtime to avoid problems from the dynamic linker. - See #25672 for more on this. */ - libver = OpenSSL_version_num(); - if (!(libver >= 0x10001000UL && libver < 0x1000108fUL) && - !(libver >= 0x10000000UL && libver < 0x100000dfUL)) { - SSL_CTX_set_mode(self->ctx, SSL_MODE_RELEASE_BUFFERS); +#ifdef PY_SSL_MIN_PROTOCOL + switch(proto_version) { + case PY_SSL_VERSION_TLS: + case PY_SSL_VERSION_TLS_CLIENT: + case PY_SSL_VERSION_TLS_SERVER: + result = SSL_CTX_set_min_proto_version(ctx, PY_SSL_MIN_PROTOCOL); + if (result == 0) { + PyErr_Format(PyExc_ValueError, + "Failed to set minimum protocol 0x%x", + PY_SSL_MIN_PROTOCOL); + goto error; + } + break; + default: + break; } #endif - -#if !defined(OPENSSL_NO_ECDH) && !defined(OPENSSL_VERSION_1_1) - /* Allow automatic ECDH curve selection (on OpenSSL 1.0.2+), or use - prime256v1 by default. This is Apache mod_ssl's initialization - policy, so we should be safe. OpenSSL 1.1 has it enabled by default. - */ -#if defined(SSL_CTX_set_ecdh_auto) - SSL_CTX_set_ecdh_auto(self->ctx, 1); -#else - { - EC_KEY *key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); - SSL_CTX_set_tmp_ecdh(self->ctx, key); - EC_KEY_free(key); - } -#endif -#endif + /* Set SSL_MODE_RELEASE_BUFFERS. This potentially greatly reduces memory + usage for no cost at all. */ + SSL_CTX_set_mode(self->ctx, SSL_MODE_RELEASE_BUFFERS); #define SID_CTX "Python" SSL_CTX_set_session_id_context(self->ctx, (const unsigned char *) SID_CTX, @@ -3288,11 +3172,9 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version) #undef SID_CTX params = SSL_CTX_get0_param(self->ctx); -#ifdef X509_V_FLAG_TRUSTED_FIRST /* Improve trust chain building when cross-signed intermediate certificates are present. See https://bugs.python.org/issue23476. */ X509_VERIFY_PARAM_set_flags(params, X509_V_FLAG_TRUSTED_FIRST); -#endif X509_VERIFY_PARAM_set_hostflags(params, self->hostflags); #ifdef TLS1_3_VERSION @@ -3301,26 +3183,26 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version) #endif return (PyObject *)self; + error: + Py_XDECREF(self); + ERR_clear_error(); + return NULL; } static int context_traverse(PySSLContext *self, visitproc visit, void *arg) { -#ifndef OPENSSL_NO_TLSEXT Py_VISIT(self->set_sni_cb); -#endif Py_VISIT(self->msg_cb); + Py_VISIT(Py_TYPE(self)); return 0; } static int context_clear(PySSLContext *self) { -#ifndef OPENSSL_NO_TLSEXT Py_CLEAR(self->set_sni_cb); -#endif Py_CLEAR(self->msg_cb); -#ifdef HAVE_OPENSSL_KEYLOG Py_CLEAR(self->keylog_filename); if (self->keylog_bio != NULL) { PySSL_BEGIN_ALLOW_THREADS @@ -3328,24 +3210,20 @@ context_clear(PySSLContext *self) PySSL_END_ALLOW_THREADS self->keylog_bio = NULL; } -#endif return 0; } static void context_dealloc(PySSLContext *self) { + PyTypeObject *tp = Py_TYPE(self); /* bpo-31095: UnTrack is needed before calling any callbacks */ PyObject_GC_UnTrack(self); context_clear(self); SSL_CTX_free(self->ctx); -#if HAVE_NPN - PyMem_FREE(self->npn_protocols); -#endif -#if HAVE_ALPN PyMem_FREE(self->alpn_protocols); -#endif Py_TYPE(self)->tp_free(self); + Py_DECREF(tp); } /*[clinic input] @@ -3364,14 +3242,13 @@ _ssl__SSLContext_set_ciphers_impl(PySSLContext *self, const char *cipherlist) otherwise the error will be reported again when another SSL call is done. */ ERR_clear_error(); - PyErr_SetString(PySSLErrorObject, + PyErr_SetString(get_state_ctx(self)->PySSLErrorObject, "No cipher can be selected."); return NULL; } Py_RETURN_NONE; } -#if OPENSSL_VERSION_NUMBER >= 0x10002000UL /*[clinic input] _ssl._SSLContext.get_ciphers [clinic start generated code]*/ @@ -3388,7 +3265,7 @@ _ssl__SSLContext_get_ciphers_impl(PySSLContext *self) ssl = SSL_new(self->ctx); if (ssl == NULL) { - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(get_state_ctx(self), NULL, 0, __FILE__, __LINE__); goto exit; } sk = SSL_get_ciphers(ssl); @@ -3414,10 +3291,8 @@ _ssl__SSLContext_get_ciphers_impl(PySSLContext *self) return result; } -#endif -#if HAVE_NPN || HAVE_ALPN static int do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen, const unsigned char *server_protocols, unsigned int server_protocols_len, @@ -3441,77 +3316,7 @@ do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen, return SSL_TLSEXT_ERR_OK; } -#endif - -#if HAVE_NPN -/* this callback gets passed to SSL_CTX_set_next_protos_advertise_cb */ -static int -_advertiseNPN_cb(SSL *s, - const unsigned char **data, unsigned int *len, - void *args) -{ - PySSLContext *ssl_ctx = (PySSLContext *) args; - - if (ssl_ctx->npn_protocols == NULL) { - *data = (unsigned char *)""; - *len = 0; - } else { - *data = ssl_ctx->npn_protocols; - *len = ssl_ctx->npn_protocols_len; - } - return SSL_TLSEXT_ERR_OK; -} -/* this callback gets passed to SSL_CTX_set_next_proto_select_cb */ -static int -_selectNPN_cb(SSL *s, - unsigned char **out, unsigned char *outlen, - const unsigned char *server, unsigned int server_len, - void *args) -{ - PySSLContext *ctx = (PySSLContext *)args; - return do_protocol_selection(0, out, outlen, server, server_len, - ctx->npn_protocols, ctx->npn_protocols_len); -} -#endif - -/*[clinic input] -_ssl._SSLContext._set_npn_protocols - protos: Py_buffer - / -[clinic start generated code]*/ - -static PyObject * -_ssl__SSLContext__set_npn_protocols_impl(PySSLContext *self, - Py_buffer *protos) -/*[clinic end generated code: output=72b002c3324390c6 input=319fcb66abf95bd7]*/ -{ -#if HAVE_NPN - PyMem_Free(self->npn_protocols); - self->npn_protocols = PyMem_Malloc(protos->len); - if (self->npn_protocols == NULL) - return PyErr_NoMemory(); - memcpy(self->npn_protocols, protos->buf, protos->len); - self->npn_protocols_len = (int) protos->len; - - /* set both server and client callbacks, because the context can - * be used to create both types of sockets */ - SSL_CTX_set_next_protos_advertised_cb(self->ctx, - _advertiseNPN_cb, - self); - SSL_CTX_set_next_proto_select_cb(self->ctx, - _selectNPN_cb, - self); - - Py_RETURN_NONE; -#else - PyErr_SetString(PyExc_NotImplementedError, - "The NPN extension requires OpenSSL 1.0.1 or later."); - return NULL; -#endif -} - -#if HAVE_ALPN static int _selectALPN_cb(SSL *s, const unsigned char **out, unsigned char *outlen, @@ -3523,7 +3328,6 @@ _selectALPN_cb(SSL *s, ctx->alpn_protocols, ctx->alpn_protocols_len, client_protocols, client_protocols_len); } -#endif /*[clinic input] _ssl._SSLContext._set_alpn_protocols @@ -3536,14 +3340,13 @@ _ssl__SSLContext__set_alpn_protocols_impl(PySSLContext *self, Py_buffer *protos) /*[clinic end generated code: output=87599a7f76651a9b input=9bba964595d519be]*/ { -#if HAVE_ALPN if ((size_t)protos->len > UINT_MAX) { PyErr_Format(PyExc_OverflowError, "protocols longer than %u bytes", UINT_MAX); return NULL; } - PyMem_FREE(self->alpn_protocols); + PyMem_Free(self->alpn_protocols); self->alpn_protocols = PyMem_Malloc(protos->len); if (!self->alpn_protocols) return PyErr_NoMemory(); @@ -3555,11 +3358,6 @@ _ssl__SSLContext__set_alpn_protocols_impl(PySSLContext *self, SSL_CTX_set_alpn_select_cb(self->ctx, _selectALPN_cb, self); Py_RETURN_NONE; -#else - PyErr_SetString(PyExc_NotImplementedError, - "The ALPN extension requires OpenSSL 1.0.2 or later."); - return NULL; -#endif } static PyObject * @@ -3576,7 +3374,7 @@ get_verify_mode(PySSLContext *self, void *c) case SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT: return PyLong_FromLong(PY_SSL_CERT_REQUIRED); } - PyErr_SetString(PySSLErrorObject, + PyErr_SetString(get_state_ctx(self)->PySSLErrorObject, "invalid return value from SSL_CTX_get_verify_mode"); return NULL; } @@ -3621,13 +3419,13 @@ set_verify_flags(PySSLContext *self, PyObject *arg, void *c) set = ~flags & new_flags; if (clear) { if (!X509_VERIFY_PARAM_clear_flags(param, clear)) { - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(get_state_ctx(self), NULL, 0, __FILE__, __LINE__); return -1; } } if (set) { if (!X509_VERIFY_PARAM_set_flags(param, set)) { - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(get_state_ctx(self), NULL, 0, __FILE__, __LINE__); return -1; } } @@ -3635,9 +3433,6 @@ set_verify_flags(PySSLContext *self, PyObject *arg, void *c) } /* Getter and setter for protocol version */ -#if defined(SSL_CTRL_GET_MAX_PROTO_VERSION) - - static int set_min_max_proto_version(PySSLContext *self, PyObject *arg, int what) { @@ -3665,6 +3460,29 @@ set_min_max_proto_version(PySSLContext *self, PyObject *arg, int what) return -1; } + /* check for deprecations and supported values */ + switch(v) { + case PY_PROTO_SSLv3: + PY_SSL_DEPRECATED("ssl.TLSVersion.SSLv3 is deprecated", 2, -1); + break; + case PY_PROTO_TLSv1: + PY_SSL_DEPRECATED("ssl.TLSVersion.TLSv1 is deprecated", 2, -1); + break; + case PY_PROTO_TLSv1_1: + PY_SSL_DEPRECATED("ssl.TLSVersion.TLSv1_1 is deprecated", 2, -1); + break; + case PY_PROTO_MINIMUM_SUPPORTED: + case PY_PROTO_MAXIMUM_SUPPORTED: + case PY_PROTO_TLSv1_2: + case PY_PROTO_TLSv1_3: + /* ok */ + break; + default: + PyErr_Format(PyExc_ValueError, + "Unsupported TLS/SSL version 0x%x", v); + return -1; + } + if (what == 0) { switch(v) { case PY_PROTO_MINIMUM_SUPPORTED: @@ -3732,9 +3550,8 @@ set_maximum_version(PySSLContext *self, PyObject *arg, void *c) { return set_min_max_proto_version(self, arg, 1); } -#endif /* SSL_CTRL_GET_MAX_PROTO_VERSION */ -#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) && !defined(LIBRESSL_VERSION_NUMBER) +#ifdef TLS1_3_VERSION static PyObject * get_num_tickets(PySSLContext *self, void *c) { @@ -3765,7 +3582,14 @@ set_num_tickets(PySSLContext *self, PyObject *arg, void *c) PyDoc_STRVAR(PySSLContext_num_tickets_doc, "Control the number of TLSv1.3 session tickets"); -#endif /* OpenSSL 1.1.1 */ +#endif /* TLS1_3_VERSION */ + +static PyObject * +get_security_level(PySSLContext *self, void *c) +{ + return PyLong_FromLong(SSL_CTX_get_security_level(self->ctx)); +} +PyDoc_STRVAR(PySSLContext_security_level_doc, "The current security level"); static PyObject * get_options(PySSLContext *self, void *c) @@ -3777,19 +3601,25 @@ static int set_options(PySSLContext *self, PyObject *arg, void *c) { long new_opts, opts, set, clear; + long opt_no = ( + SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | + SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_3 + ); + if (!PyArg_Parse(arg, "l", &new_opts)) return -1; opts = SSL_CTX_get_options(self->ctx); clear = opts & ~new_opts; set = ~opts & new_opts; + + if ((set & opt_no) != 0) { + if (_ssl_deprecated("ssl.OP_NO_SSL*/ssl.OP_NO_TLS* options are " + "deprecated", 2) < 0) { + return -1; + } + } if (clear) { -#ifdef HAVE_SSL_CTX_CLEAR_OPTIONS SSL_CTX_clear_options(self->ctx, clear); -#else - PyErr_SetString(PyExc_ValueError, - "can't clear options before OpenSSL 0.9.8m"); - return -1; -#endif } if (set) SSL_CTX_set_options(self->ctx, set); @@ -4045,7 +3875,7 @@ _ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile, PyErr_SetFromErrno(PyExc_OSError); } else { - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(get_state_ctx(self), NULL, 0, __FILE__, __LINE__); } goto error; } @@ -4066,7 +3896,7 @@ _ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile, PyErr_SetFromErrno(PyExc_OSError); } else { - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(get_state_ctx(self), NULL, 0, __FILE__, __LINE__); } goto error; } @@ -4074,7 +3904,7 @@ _ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile, r = SSL_CTX_check_private_key(self->ctx); PySSL_END_ALLOW_THREADS_S(pw_info.thread_state); if (r != 1) { - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(get_state_ctx(self), NULL, 0, __FILE__, __LINE__); goto error; } SSL_CTX_set_default_passwd_cb(self->ctx, orig_passwd_cb); @@ -4115,7 +3945,7 @@ _add_ca_certs(PySSLContext *self, const void *data, Py_ssize_t len, biobuf = BIO_new_mem_buf(data, (int)len); if (biobuf == NULL) { - _setSSLError("Can't allocate buffer", 0, __FILE__, __LINE__); + _setSSLError(get_state_ctx(self), "Can't allocate buffer", 0, __FILE__, __LINE__); return -1; } @@ -4160,7 +3990,7 @@ _add_ca_certs(PySSLContext *self, const void *data, Py_ssize_t len, } else { msg = "not enough data: cadata does not contain a certificate"; } - _setSSLError(msg, 0, __FILE__, __LINE__); + _setSSLError(get_state_ctx(self), msg, 0, __FILE__, __LINE__); retval = -1; } else if ((filetype == SSL_FILETYPE_ASN1) && (ERR_GET_LIB(err) == ERR_LIB_ASN1) && @@ -4175,7 +4005,7 @@ _add_ca_certs(PySSLContext *self, const void *data, Py_ssize_t len, ERR_clear_error(); retval = 0; } else if (err != 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(get_state_ctx(self), NULL, 0, __FILE__, __LINE__); retval = -1; } else { retval = 0; @@ -4294,7 +4124,7 @@ _ssl__SSLContext_load_verify_locations_impl(PySSLContext *self, PyErr_SetFromErrno(PyExc_OSError); } else { - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(get_state_ctx(self), NULL, 0, __FILE__, __LINE__); } goto error; } @@ -4342,13 +4172,13 @@ _ssl__SSLContext_load_dh_params(PySSLContext *self, PyObject *filepath) PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, filepath); } else { - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(get_state_ctx(self), NULL, 0, __FILE__, __LINE__); } return NULL; } if (!SSL_CTX_set_tmp_dh(self->ctx, dh)) { DH_free(dh); - return _setSSLError(NULL, 0, __FILE__, __LINE__); + return _setSSLError(get_state_ctx(self), NULL, 0, __FILE__, __LINE__); } DH_free(dh); Py_RETURN_NONE; @@ -4356,7 +4186,7 @@ _ssl__SSLContext_load_dh_params(PySSLContext *self, PyObject *filepath) /*[clinic input] _ssl._SSLContext._wrap_socket - sock: object(subclass_of="PySocketModule.Sock_Type") + sock: object(subclass_of="get_state_ctx(self)->Sock_Type") server_side: int server_hostname as hostname_obj: object = None * @@ -4369,7 +4199,7 @@ static PyObject * _ssl__SSLContext__wrap_socket_impl(PySSLContext *self, PyObject *sock, int server_side, PyObject *hostname_obj, PyObject *owner, PyObject *session) -/*[clinic end generated code: output=f103f238633940b4 input=957d5006183d1894]*/ +/*[clinic end generated code: output=f103f238633940b4 input=f5916eadbc6eae81]*/ { char *hostname = NULL; PyObject *res; @@ -4392,8 +4222,8 @@ _ssl__SSLContext__wrap_socket_impl(PySSLContext *self, PyObject *sock, /*[clinic input] _ssl._SSLContext._wrap_bio - incoming: object(subclass_of="&PySSLMemoryBIO_Type", type="PySSLMemoryBIO *") - outgoing: object(subclass_of="&PySSLMemoryBIO_Type", type="PySSLMemoryBIO *") + incoming: object(subclass_of="get_state_ctx(self)->PySSLMemoryBIO_Type", type="PySSLMemoryBIO *") + outgoing: object(subclass_of="get_state_ctx(self)->PySSLMemoryBIO_Type", type="PySSLMemoryBIO *") server_side: int server_hostname as hostname_obj: object = None * @@ -4407,7 +4237,7 @@ _ssl__SSLContext__wrap_bio_impl(PySSLContext *self, PySSLMemoryBIO *incoming, PySSLMemoryBIO *outgoing, int server_side, PyObject *hostname_obj, PyObject *owner, PyObject *session) -/*[clinic end generated code: output=5c5d6d9b41f99332 input=8cf22f4d586ac56a]*/ +/*[clinic end generated code: output=5c5d6d9b41f99332 input=331edeec9c738382]*/ { char *hostname = NULL; PyObject *res; @@ -4480,13 +4310,12 @@ _ssl__SSLContext_set_default_verify_paths_impl(PySSLContext *self) /*[clinic end generated code: output=0bee74e6e09deaaa input=35f3408021463d74]*/ { if (!SSL_CTX_set_default_verify_paths(self->ctx)) { - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(get_state_ctx(self), NULL, 0, __FILE__, __LINE__); return NULL; } Py_RETURN_NONE; } -#ifndef OPENSSL_NO_ECDH /*[clinic input] _ssl._SSLContext.set_ecdh_curve name: object @@ -4514,21 +4343,19 @@ _ssl__SSLContext_set_ecdh_curve(PySSLContext *self, PyObject *name) } key = EC_KEY_new_by_curve_name(nid); if (key == NULL) { - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(get_state_ctx(self), NULL, 0, __FILE__, __LINE__); return NULL; } SSL_CTX_set_tmp_ecdh(self->ctx, key); EC_KEY_free(key); Py_RETURN_NONE; } -#endif -#if HAVE_SNI && !defined(OPENSSL_NO_TLSEXT) static int _servername_callback(SSL *s, int *al, void *args) { int ret; - PySSLContext *ssl_ctx = (PySSLContext *) args; + PySSLContext *sslctx = (PySSLContext *) args; PySSLSocket *ssl; PyObject *result; /* The high-level ssl.SSLSocket object */ @@ -4536,7 +4363,7 @@ _servername_callback(SSL *s, int *al, void *args) const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); PyGILState_STATE gstate = PyGILState_Ensure(); - if (ssl_ctx->set_sni_cb == NULL) { + if (sslctx->set_sni_cb == NULL) { /* remove race condition in this the call back while if removing the * callback is in progress */ PyGILState_Release(gstate); @@ -4544,7 +4371,7 @@ _servername_callback(SSL *s, int *al, void *args) } ssl = SSL_get_app_data(s); - assert(PySSLSocket_Check(ssl)); + assert(Py_IS_TYPE(ssl, get_state_ctx(sslctx)->PySSLSocket_Type)); /* The servername callback expects an argument that represents the current * SSL connection and that has a .context attribute that can be changed to @@ -4566,8 +4393,8 @@ _servername_callback(SSL *s, int *al, void *args) goto error; if (servername == NULL) { - result = PyObject_CallFunctionObjArgs(ssl_ctx->set_sni_cb, ssl_socket, - Py_None, ssl_ctx, NULL); + result = PyObject_CallFunctionObjArgs(sslctx->set_sni_cb, ssl_socket, + Py_None, sslctx, NULL); } else { PyObject *servername_bytes; @@ -4575,7 +4402,7 @@ _servername_callback(SSL *s, int *al, void *args) servername_bytes = PyBytes_FromString(servername); if (servername_bytes == NULL) { - PyErr_WriteUnraisable((PyObject *) ssl_ctx); + PyErr_WriteUnraisable((PyObject *) sslctx); goto error; } /* server_hostname was encoded to an A-label by our caller; put it @@ -4589,14 +4416,14 @@ _servername_callback(SSL *s, int *al, void *args) } Py_DECREF(servername_bytes); result = PyObject_CallFunctionObjArgs( - ssl_ctx->set_sni_cb, ssl_socket, servername_str, - ssl_ctx, NULL); + sslctx->set_sni_cb, ssl_socket, servername_str, + sslctx, NULL); Py_DECREF(servername_str); } Py_DECREF(ssl_socket); if (result == NULL) { - PyErr_WriteUnraisable(ssl_ctx->set_sni_cb); + PyErr_WriteUnraisable(sslctx->set_sni_cb); *al = SSL_AD_HANDSHAKE_FAILURE; ret = SSL_TLSEXT_ERR_ALERT_FATAL; } @@ -4627,7 +4454,6 @@ error: PyGILState_Release(gstate); return ret; } -#endif static PyObject * get_sni_callback(PySSLContext *self, void *c) @@ -4648,7 +4474,6 @@ set_sni_callback(PySSLContext *self, PyObject *arg, void *c) "sni_callback cannot be set on TLS_CLIENT context"); return -1; } -#if HAVE_SNI && !defined(OPENSSL_NO_TLSEXT) Py_CLEAR(self->set_sni_cb); if (arg == Py_None) { SSL_CTX_set_tlsext_servername_callback(self->ctx, NULL); @@ -4666,13 +4491,6 @@ set_sni_callback(PySSLContext *self, PyObject *arg, void *c) SSL_CTX_set_tlsext_servername_arg(self->ctx, self); } return 0; -#else - PyErr_SetString(PyExc_NotImplementedError, - "The TLS extension servername callback, " - "SSL_CTX_set_tlsext_servername_callback, " - "is not in the current OpenSSL library."); - return -1; -#endif } PyDoc_STRVAR(PySSLContext_sni_callback_doc, @@ -4771,9 +4589,9 @@ _ssl__SSLContext_get_ca_certs_impl(PySSLContext *self, int binary_form) continue; } if (binary_form) { - ci = _certificate_to_der(cert); + ci = _certificate_to_der(get_state_ctx(self), cert); } else { - ci = _decode_certificate(cert); + ci = _decode_certificate(get_state_ctx(self), cert); } if (ci == NULL) { goto error; @@ -4797,21 +4615,17 @@ static PyGetSetDef context_getsetlist[] = { (setter) set_check_hostname, NULL}, {"_host_flags", (getter) get_host_flags, (setter) set_host_flags, NULL}, -#if SSL_CTRL_GET_MAX_PROTO_VERSION {"minimum_version", (getter) get_minimum_version, (setter) set_minimum_version, NULL}, {"maximum_version", (getter) get_maximum_version, (setter) set_maximum_version, NULL}, -#endif -#ifdef HAVE_OPENSSL_KEYLOG {"keylog_filename", (getter) _PySSLContext_get_keylog_filename, (setter) _PySSLContext_set_keylog_filename, NULL}, -#endif {"_msg_callback", (getter) _PySSLContext_get_msg_callback, (setter) _PySSLContext_set_msg_callback, NULL}, {"sni_callback", (getter) get_sni_callback, (setter) set_sni_callback, PySSLContext_sni_callback_doc}, -#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) && !defined(LIBRESSL_VERSION_NUMBER) +#ifdef TLS1_3_VERSION {"num_tickets", (getter) get_num_tickets, (setter) set_num_tickets, PySSLContext_num_tickets_doc}, #endif @@ -4830,6 +4644,8 @@ static PyGetSetDef context_getsetlist[] = { (setter) set_verify_flags, NULL}, {"verify_mode", (getter) get_verify_mode, (setter) set_verify_mode, NULL}, + {"security_level", (getter) get_security_level, + NULL, PySSLContext_security_level_doc}, {NULL}, /* sentinel */ }; @@ -4838,7 +4654,6 @@ static struct PyMethodDef context_methods[] = { _SSL__SSLCONTEXT__WRAP_BIO_METHODDEF _SSL__SSLCONTEXT_SET_CIPHERS_METHODDEF _SSL__SSLCONTEXT__SET_ALPN_PROTOCOLS_METHODDEF - _SSL__SSLCONTEXT__SET_NPN_PROTOCOLS_METHODDEF _SSL__SSLCONTEXT_LOAD_CERT_CHAIN_METHODDEF _SSL__SSLCONTEXT_LOAD_DH_PARAMS_METHODDEF _SSL__SSLCONTEXT_LOAD_VERIFY_LOCATIONS_METHODDEF @@ -4851,45 +4666,22 @@ static struct PyMethodDef context_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject PySSLContext_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_ssl._SSLContext", /*tp_name*/ - sizeof(PySSLContext), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)context_dealloc, /*tp_dealloc*/ - 0, /*tp_vectorcall_offset*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_as_async*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ - 0, /*tp_doc*/ - (traverseproc) context_traverse, /*tp_traverse*/ - (inquiry) context_clear, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - context_methods, /*tp_methods*/ - 0, /*tp_members*/ - context_getsetlist, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - 0, /*tp_init*/ - 0, /*tp_alloc*/ - _ssl__SSLContext, /*tp_new*/ +static PyType_Slot PySSLContext_slots[] = { + {Py_tp_methods, context_methods}, + {Py_tp_getset, context_getsetlist}, + {Py_tp_new, _ssl__SSLContext}, + {Py_tp_dealloc, context_dealloc}, + {Py_tp_traverse, context_traverse}, + {Py_tp_clear, context_clear}, + {0, 0}, +}; + +static PyType_Spec PySSLContext_spec = { + .name = "_ssl._SSLContext", + .basicsize = sizeof(PySSLContext), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = PySSLContext_slots, }; @@ -4912,8 +4704,7 @@ _ssl_MemoryBIO_impl(PyTypeObject *type) bio = BIO_new(BIO_s_mem()); if (bio == NULL) { - PyErr_SetString(PySSLErrorObject, - "failed to allocate BIO"); + PyErr_SetString(PyExc_MemoryError, "failed to allocate BIO"); return NULL; } /* Since our BIO is non-blocking an empty read() does not indicate EOF, @@ -4934,11 +4725,21 @@ _ssl_MemoryBIO_impl(PyTypeObject *type) return (PyObject *) self; } +static int +memory_bio_traverse(PySSLMemoryBIO *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + return 0; +} + static void memory_bio_dealloc(PySSLMemoryBIO *self) { + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); BIO_free(self->bio); Py_TYPE(self)->tp_free(self); + Py_DECREF(tp); } static PyObject * @@ -4990,8 +4791,9 @@ _ssl_MemoryBIO_read_impl(PySSLMemoryBIO *self, int len) nbytes = BIO_read(self->bio, PyBytes_AS_STRING(result), len); if (nbytes < 0) { + _sslmodulestate *state = get_state_mbio(self); Py_DECREF(result); - _setSSLError(NULL, 0, __FILE__, __LINE__); + _setSSLError(state, NULL, 0, __FILE__, __LINE__); return NULL; } @@ -5026,14 +4828,18 @@ _ssl_MemoryBIO_write_impl(PySSLMemoryBIO *self, Py_buffer *b) } if (self->eof_written) { - PyErr_SetString(PySSLErrorObject, + PyObject *module = PyType_GetModule(Py_TYPE(self)); + if (module == NULL) + return NULL; + PyErr_SetString(get_ssl_state(module)->PySSLErrorObject, "cannot write() after write_eof()"); return NULL; } nbytes = BIO_write(self->bio, b->buf, (int)b->len); if (nbytes < 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); + _sslmodulestate *state = get_state_mbio(self); + _setSSLError(state, NULL, 0, __FILE__, __LINE__); return NULL; } @@ -5076,47 +4882,22 @@ static struct PyMethodDef memory_bio_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject PySSLMemoryBIO_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_ssl.MemoryBIO", /*tp_name*/ - sizeof(PySSLMemoryBIO), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)memory_bio_dealloc, /*tp_dealloc*/ - 0, /*tp_vectorcall_offset*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_as_async*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - memory_bio_methods, /*tp_methods*/ - 0, /*tp_members*/ - memory_bio_getsetlist, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - 0, /*tp_init*/ - 0, /*tp_alloc*/ - _ssl_MemoryBIO, /*tp_new*/ +static PyType_Slot PySSLMemoryBIO_slots[] = { + {Py_tp_methods, memory_bio_methods}, + {Py_tp_getset, memory_bio_getsetlist}, + {Py_tp_new, _ssl_MemoryBIO}, + {Py_tp_dealloc, memory_bio_dealloc}, + {Py_tp_traverse, memory_bio_traverse}, + {0, 0}, }; +static PyType_Spec PySSLMemoryBIO_spec = { + .name = "_ssl.MemoryBIO", + .basicsize = sizeof(PySSLMemoryBIO), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | + Py_TPFLAGS_HAVE_GC), + .slots = PySSLMemoryBIO_slots, +}; /* * SSL Session object @@ -5125,6 +4906,7 @@ static PyTypeObject PySSLMemoryBIO_Type = { static void PySSLSession_dealloc(PySSLSession *self) { + PyTypeObject *tp = Py_TYPE(self); /* bpo-31095: UnTrack is needed before calling any callbacks */ PyObject_GC_UnTrack(self); Py_XDECREF(self->ctx); @@ -5132,19 +4914,21 @@ PySSLSession_dealloc(PySSLSession *self) SSL_SESSION_free(self->session); } PyObject_GC_Del(self); + Py_DECREF(tp); } static PyObject * PySSLSession_richcompare(PyObject *left, PyObject *right, int op) { int result; + PyTypeObject *sesstype = ((PySSLSession*)left)->ctx->state->PySSLSession_Type; if (left == NULL || right == NULL) { PyErr_BadInternalCall(); return NULL; } - if (!PySSLSession_Check(left) || !PySSLSession_Check(right)) { + if (!Py_IS_TYPE(left, sesstype) || !Py_IS_TYPE(right, sesstype)) { Py_RETURN_NOTIMPLEMENTED; } @@ -5195,6 +4979,7 @@ static int PySSLSession_traverse(PySSLSession *self, visitproc visit, void *arg) { Py_VISIT(self->ctx); + Py_VISIT(Py_TYPE(self)); return 0; } @@ -5273,37 +5058,21 @@ static PyGetSetDef PySSLSession_getsetlist[] = { {NULL}, /* sentinel */ }; -static PyTypeObject PySSLSession_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_ssl.Session", /*tp_name*/ - sizeof(PySSLSession), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)PySSLSession_dealloc, /*tp_dealloc*/ - 0, /*tp_vectorcall_offset*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_as_async*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ - 0, /*tp_doc*/ - (traverseproc)PySSLSession_traverse, /*tp_traverse*/ - (inquiry)PySSLSession_clear, /*tp_clear*/ - PySSLSession_richcompare, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - 0, /*tp_methods*/ - 0, /*tp_members*/ - PySSLSession_getsetlist, /*tp_getset*/ +static PyType_Slot PySSLSession_slots[] = { + {Py_tp_getset,PySSLSession_getsetlist}, + {Py_tp_richcompare, PySSLSession_richcompare}, + {Py_tp_dealloc, PySSLSession_dealloc}, + {Py_tp_traverse, PySSLSession_traverse}, + {Py_tp_clear, PySSLSession_clear}, + {0, 0}, +}; + +static PyType_Spec PySSLSession_spec = { + .name = "_ssl.SSLSession", + .basicsize = sizeof(PySSLSession), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = PySSLSession_slots, }; @@ -5339,7 +5108,7 @@ _ssl_RAND_add_impl(PyObject *module, Py_buffer *view, double entropy) } static PyObject * -PySSL_RAND(int len, int pseudo) +PySSL_RAND(PyObject *module, int len, int pseudo) { int ok; PyObject *bytes; @@ -5356,11 +5125,7 @@ PySSL_RAND(int len, int pseudo) if (bytes == NULL) return NULL; if (pseudo) { -#ifdef PY_OPENSSL_1_1_API ok = RAND_bytes((unsigned char*)PyBytes_AS_STRING(bytes), len); -#else - ok = RAND_pseudo_bytes((unsigned char*)PyBytes_AS_STRING(bytes), len); -#endif if (ok == 0 || ok == 1) return Py_BuildValue("NO", bytes, ok == 1 ? Py_True : Py_False); } @@ -5375,7 +5140,7 @@ PySSL_RAND(int len, int pseudo) errstr = ERR_reason_error_string(err); v = Py_BuildValue("(ks)", err, errstr); if (v != NULL) { - PyErr_SetObject(PySSLErrorObject, v); + PyErr_SetObject(get_ssl_state(module)->PySSLErrorObject, v); Py_DECREF(v); } return NULL; @@ -5393,7 +5158,7 @@ static PyObject * _ssl_RAND_bytes_impl(PyObject *module, int n) /*[clinic end generated code: output=977da635e4838bc7 input=678ddf2872dfebfc]*/ { - return PySSL_RAND(n, 0); + return PySSL_RAND(module, n, 0); } /*[clinic input] @@ -5411,13 +5176,14 @@ static PyObject * _ssl_RAND_pseudo_bytes_impl(PyObject *module, int n) /*[clinic end generated code: output=b1509e937000e52d input=58312bd53f9bbdd0]*/ { - return PySSL_RAND(n, 1); + PY_SSL_DEPRECATED("ssl.RAND_pseudo_bytes() is deprecated", 1, NULL); + return PySSL_RAND(module, n, 1); } /*[clinic input] _ssl.RAND_status -Returns 1 if the OpenSSL PRNG has been seeded with enough data and 0 if not. +Returns True if the OpenSSL PRNG has been seeded with enough data and False if not. It is necessary to seed the PRNG with RAND_add() on some platforms before using the ssl() function. @@ -5425,42 +5191,10 @@ using the ssl() function. static PyObject * _ssl_RAND_status_impl(PyObject *module) -/*[clinic end generated code: output=7e0aaa2d39fdc1ad input=8a774b02d1dc81f3]*/ -{ - return PyLong_FromLong(RAND_status()); -} - -#ifndef OPENSSL_NO_EGD -/* LCOV_EXCL_START */ -/*[clinic input] -_ssl.RAND_egd - path: object(converter="PyUnicode_FSConverter") - / - -Queries the entropy gather daemon (EGD) on the socket named by 'path'. - -Returns number of bytes read. Raises SSLError if connection to EGD -fails or if it does not provide enough data to seed PRNG. -[clinic start generated code]*/ - -static PyObject * -_ssl_RAND_egd_impl(PyObject *module, PyObject *path) -/*[clinic end generated code: output=02a67c7c367f52fa input=1aeb7eb948312195]*/ +/*[clinic end generated code: output=7e0aaa2d39fdc1ad input=d5ae5aea52f36e01]*/ { - int bytes = RAND_egd(PyBytes_AsString(path)); - Py_DECREF(path); - if (bytes == -1) { - PyErr_SetString(PySSLErrorObject, - "EGD connection failed or EGD did not return " - "enough data to seed the PRNG"); - return NULL; - } - return PyLong_FromLong(bytes); + return PyBool_FromLong(RAND_status()); } -/* LCOV_EXCL_STOP */ -#endif /* OPENSSL_NO_EGD */ - - /*[clinic input] _ssl.get_default_verify_paths @@ -5505,7 +5239,7 @@ _ssl_get_default_verify_paths_impl(PyObject *module) } static PyObject* -asn1obj2py(ASN1_OBJECT *obj) +asn1obj2py(_sslmodulestate *state, ASN1_OBJECT *obj) { int nid; const char *ln, *sn; @@ -5517,7 +5251,7 @@ asn1obj2py(ASN1_OBJECT *obj) } sn = OBJ_nid2sn(nid); ln = OBJ_nid2ln(nid); - return Py_BuildValue("issN", nid, sn, ln, _asn1obj2py(obj, 1)); + return Py_BuildValue("issN", nid, sn, ln, _asn1obj2py(state, obj, 1)); } /*[clinic input] @@ -5543,7 +5277,7 @@ _ssl_txt2obj_impl(PyObject *module, const char *txt, int name) PyErr_Format(PyExc_ValueError, "unknown object '%.100s'", txt); return NULL; } - result = asn1obj2py(obj); + result = asn1obj2py(get_ssl_state(module), obj); ASN1_OBJECT_free(obj); return result; } @@ -5572,7 +5306,7 @@ _ssl_nid2obj_impl(PyObject *module, int nid) PyErr_Format(PyExc_ValueError, "unknown NID %i", nid); return NULL; } - result = asn1obj2py(obj); + result = asn1obj2py(get_ssl_state(module), obj); ASN1_OBJECT_free(obj); return result; } @@ -5904,7 +5638,6 @@ static PyMethodDef PySSL_methods[] = { _SSL_RAND_ADD_METHODDEF _SSL_RAND_BYTES_METHODDEF _SSL_RAND_PSEUDO_BYTES_METHODDEF - _SSL_RAND_EGD_METHODDEF _SSL_RAND_STATUS_METHODDEF _SSL_GET_DEFAULT_VERIFY_PATHS_METHODDEF _SSL_ENUM_CERTIFICATES_METHODDEF @@ -5915,233 +5648,104 @@ static PyMethodDef PySSL_methods[] = { }; -#ifdef HAVE_OPENSSL_CRYPTO_LOCK - -/* an implementation of OpenSSL threading operations in terms - * of the Python C thread library - * Only used up to 1.0.2. OpenSSL 1.1.0+ has its own locking code. - */ - -static PyThread_type_lock *_ssl_locks = NULL; - -#if OPENSSL_VERSION_NUMBER >= 0x10000000 -/* use new CRYPTO_THREADID API. */ -static void -_ssl_threadid_callback(CRYPTO_THREADID *id) -{ - CRYPTO_THREADID_set_numeric(id, PyThread_get_thread_ident()); -} -#else -/* deprecated CRYPTO_set_id_callback() API. */ -static unsigned long -_ssl_thread_id_function (void) { - return PyThread_get_thread_ident(); -} -#endif - -static void _ssl_thread_locking_function - (int mode, int n, const char *file, int line) { - /* this function is needed to perform locking on shared data - structures. (Note that OpenSSL uses a number of global data - structures that will be implicitly shared whenever multiple - threads use OpenSSL.) Multi-threaded applications will - crash at random if it is not set. - - locking_function() must be able to handle up to - CRYPTO_num_locks() different mutex locks. It sets the n-th - lock if mode & CRYPTO_LOCK, and releases it otherwise. - - file and line are the file number of the function setting the - lock. They can be useful for debugging. - */ - - if ((_ssl_locks == NULL) || - (n < 0) || ((unsigned)n >= _ssl_locks_count)) - return; - - if (mode & CRYPTO_LOCK) { - PyThread_acquire_lock(_ssl_locks[n], 1); - } else { - PyThread_release_lock(_ssl_locks[n]); - } -} - -static int _setup_ssl_threads(void) { - - unsigned int i; - - if (_ssl_locks == NULL) { - _ssl_locks_count = CRYPTO_num_locks(); - _ssl_locks = PyMem_Calloc(_ssl_locks_count, - sizeof(PyThread_type_lock)); - if (_ssl_locks == NULL) { - PyErr_NoMemory(); - return 0; - } - for (i = 0; i < _ssl_locks_count; i++) { - _ssl_locks[i] = PyThread_allocate_lock(); - if (_ssl_locks[i] == NULL) { - unsigned int j; - for (j = 0; j < i; j++) { - PyThread_free_lock(_ssl_locks[j]); - } - PyMem_Free(_ssl_locks); - return 0; - } - } - CRYPTO_set_locking_callback(_ssl_thread_locking_function); -#if OPENSSL_VERSION_NUMBER >= 0x10000000 - CRYPTO_THREADID_set_callback(_ssl_threadid_callback); -#else - CRYPTO_set_id_callback(_ssl_thread_id_function); -#endif - } - return 1; -} - -#endif /* HAVE_OPENSSL_CRYPTO_LOCK for OpenSSL < 1.1.0 */ - PyDoc_STRVAR(module_doc, "Implementation module for SSL socket operations. See the socket module\n\ for documentation."); +static int +sslmodule_init_exceptions(PyObject *module) +{ + _sslmodulestate *state = get_ssl_state(module); + PyObject *bases = NULL; + +#define add_exception(exc, name, doc, base) \ +do { \ + (exc) = PyErr_NewExceptionWithDoc("ssl." name, (doc), (base), NULL); \ + if ((state) == NULL) goto error; \ + if (PyModule_AddObjectRef(module, name, exc) < 0) goto error; \ +} while(0) + + state->PySSLErrorObject = PyType_FromSpecWithBases( + &sslerror_type_spec, PyExc_OSError); + if (state->PySSLErrorObject == NULL) { + goto error; + } + if (PyModule_AddObjectRef(module, "SSLError", state->PySSLErrorObject) < 0) { + goto error; + } -static struct PyModuleDef _sslmodule = { - PyModuleDef_HEAD_INIT, - "_ssl", - module_doc, - -1, - PySSL_methods, - NULL, - NULL, - NULL, - NULL -}; - + /* ssl.CertificateError used to be a subclass of ValueError */ + bases = PyTuple_Pack(2, state->PySSLErrorObject, PyExc_ValueError); + if (bases == NULL) { + goto error; + } + add_exception( + state->PySSLCertVerificationErrorObject, + "SSLCertVerificationError", + SSLCertVerificationError_doc, + bases + ); + Py_CLEAR(bases); + + add_exception( + state->PySSLZeroReturnErrorObject, + "SSLZeroReturnError", + SSLZeroReturnError_doc, + state->PySSLErrorObject + ); + + add_exception( + state->PySSLWantWriteErrorObject, + "SSLWantWriteError", + SSLWantWriteError_doc, + state->PySSLErrorObject + ); + + add_exception( + state->PySSLWantReadErrorObject, + "SSLWantReadError", + SSLWantReadError_doc, + state->PySSLErrorObject + ); + + add_exception( + state->PySSLSyscallErrorObject, + "SSLSyscallError", + SSLSyscallError_doc, + state->PySSLErrorObject + ); + + add_exception( + state->PySSLEOFErrorObject, + "SSLEOFError", + SSLEOFError_doc, + state->PySSLErrorObject + ); +#undef add_exception -static void -parse_openssl_version(unsigned long libver, - unsigned int *major, unsigned int *minor, - unsigned int *fix, unsigned int *patch, - unsigned int *status) -{ - *status = libver & 0xF; - libver >>= 4; - *patch = libver & 0xFF; - libver >>= 8; - *fix = libver & 0xFF; - libver >>= 8; - *minor = libver & 0xFF; - libver >>= 8; - *major = libver & 0xFF; + return 0; + error: + Py_XDECREF(bases); + return -1; } -PyMODINIT_FUNC -PyInit__ssl(void) +static int +sslmodule_init_socketapi(PyObject *module) { - PyObject *m, *d, *r, *bases; - unsigned long libver; - unsigned int major, minor, fix, patch, status; - PySocketModule_APIObject *socket_api; - struct py_ssl_error_code *errcode; - struct py_ssl_library_code *libcode; - - if (PyType_Ready(&PySSLContext_Type) < 0) - return NULL; - if (PyType_Ready(&PySSLSocket_Type) < 0) - return NULL; - if (PyType_Ready(&PySSLMemoryBIO_Type) < 0) - return NULL; - if (PyType_Ready(&PySSLSession_Type) < 0) - return NULL; - + _sslmodulestate *state = get_ssl_state(module); + PySocketModule_APIObject *sockmod = PySocketModule_ImportModuleAndAPI(); - m = PyModule_Create(&_sslmodule); - if (m == NULL) - return NULL; - d = PyModule_GetDict(m); - - /* Load _socket module and its C API */ - socket_api = PySocketModule_ImportModuleAndAPI(); - if (!socket_api) - return NULL; - PySocketModule = *socket_api; - -#ifndef OPENSSL_VERSION_1_1 - /* Load all algorithms and initialize cpuid */ - OPENSSL_add_all_algorithms_noconf(); - /* Init OpenSSL */ - SSL_load_error_strings(); - SSL_library_init(); -#endif - -#ifdef HAVE_OPENSSL_CRYPTO_LOCK - /* note that this will start threading if not already started */ - if (!_setup_ssl_threads()) { - return NULL; + if ((sockmod == NULL) || (sockmod->Sock_Type == NULL)) { + return -1; } -#elif OPENSSL_VERSION_1_1 - /* OpenSSL 1.1.0 builtin thread support is enabled */ - _ssl_locks_count++; -#endif - - /* Add symbols to module dict */ - sslerror_type_slots[0].pfunc = PyExc_OSError; - PySSLErrorObject = PyType_FromSpec(&sslerror_type_spec); - if (PySSLErrorObject == NULL) - return NULL; + state->Sock_Type = sockmod->Sock_Type; + Py_INCREF(state->Sock_Type); + return 0; +} - /* ssl.CertificateError used to be a subclass of ValueError */ - bases = Py_BuildValue("OO", PySSLErrorObject, PyExc_ValueError); - if (bases == NULL) - return NULL; - PySSLCertVerificationErrorObject = PyErr_NewExceptionWithDoc( - "ssl.SSLCertVerificationError", SSLCertVerificationError_doc, - bases, NULL); - Py_DECREF(bases); - PySSLZeroReturnErrorObject = PyErr_NewExceptionWithDoc( - "ssl.SSLZeroReturnError", SSLZeroReturnError_doc, - PySSLErrorObject, NULL); - PySSLWantReadErrorObject = PyErr_NewExceptionWithDoc( - "ssl.SSLWantReadError", SSLWantReadError_doc, - PySSLErrorObject, NULL); - PySSLWantWriteErrorObject = PyErr_NewExceptionWithDoc( - "ssl.SSLWantWriteError", SSLWantWriteError_doc, - PySSLErrorObject, NULL); - PySSLSyscallErrorObject = PyErr_NewExceptionWithDoc( - "ssl.SSLSyscallError", SSLSyscallError_doc, - PySSLErrorObject, NULL); - PySSLEOFErrorObject = PyErr_NewExceptionWithDoc( - "ssl.SSLEOFError", SSLEOFError_doc, - PySSLErrorObject, NULL); - if (PySSLCertVerificationErrorObject == NULL - || PySSLZeroReturnErrorObject == NULL - || PySSLWantReadErrorObject == NULL - || PySSLWantWriteErrorObject == NULL - || PySSLSyscallErrorObject == NULL - || PySSLEOFErrorObject == NULL) - return NULL; - if (PyDict_SetItemString(d, "SSLError", PySSLErrorObject) != 0 - || PyDict_SetItemString(d, "SSLCertVerificationError", - PySSLCertVerificationErrorObject) != 0 - || PyDict_SetItemString(d, "SSLZeroReturnError", PySSLZeroReturnErrorObject) != 0 - || PyDict_SetItemString(d, "SSLWantReadError", PySSLWantReadErrorObject) != 0 - || PyDict_SetItemString(d, "SSLWantWriteError", PySSLWantWriteErrorObject) != 0 - || PyDict_SetItemString(d, "SSLSyscallError", PySSLSyscallErrorObject) != 0 - || PyDict_SetItemString(d, "SSLEOFError", PySSLEOFErrorObject) != 0) - return NULL; - if (PyDict_SetItemString(d, "_SSLContext", - (PyObject *)&PySSLContext_Type) != 0) - return NULL; - if (PyDict_SetItemString(d, "_SSLSocket", - (PyObject *)&PySSLSocket_Type) != 0) - return NULL; - if (PyDict_SetItemString(d, "MemoryBIO", - (PyObject *)&PySSLMemoryBIO_Type) != 0) - return NULL; - if (PyDict_SetItemString(d, "SSLSession", - (PyObject *)&PySSLSession_Type) != 0) - return NULL; +static int +sslmodule_init_constants(PyObject *m) +{ PyModule_AddStringConstant(m, "_DEFAULT_CIPHERS", PY_SSL_DEFAULT_CIPHER_STRING); @@ -6181,9 +5785,14 @@ PyInit__ssl(void) X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); PyModule_AddIntConstant(m, "VERIFY_X509_STRICT", X509_V_FLAG_X509_STRICT); -#ifdef X509_V_FLAG_TRUSTED_FIRST + PyModule_AddIntConstant(m, "VERIFY_ALLOW_PROXY_CERTS", + X509_V_FLAG_ALLOW_PROXY_CERTS); PyModule_AddIntConstant(m, "VERIFY_X509_TRUSTED_FIRST", X509_V_FLAG_TRUSTED_FIRST); + +#ifdef X509_V_FLAG_PARTIAL_CHAIN + PyModule_AddIntConstant(m, "VERIFY_X509_PARTIAL_CHAIN", + X509_V_FLAG_PARTIAL_CHAIN); #endif /* Alert Descriptions from ssl.h */ @@ -6323,6 +5932,10 @@ PyInit__ssl(void) X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS); #endif + /* file types */ + PyModule_AddIntConstant(m, "ENCODING_PEM", PY_SSL_ENCODING_PEM); + PyModule_AddIntConstant(m, "ENCODING_DER", PY_SSL_ENCODING_DER); + /* protocol versions */ PyModule_AddIntConstant(m, "PROTO_MINIMUM_SUPPORTED", PY_PROTO_MINIMUM_SUPPORTED); @@ -6341,31 +5954,11 @@ PyInit__ssl(void) PyModule_AddObject((m), (key), bool_obj); \ } while (0) -#if HAVE_SNI addbool(m, "HAS_SNI", 1); -#else - addbool(m, "HAS_SNI", 0); -#endif - addbool(m, "HAS_TLS_UNIQUE", 1); - -#ifndef OPENSSL_NO_ECDH addbool(m, "HAS_ECDH", 1); -#else - addbool(m, "HAS_ECDH", 0); -#endif - -#if HAVE_NPN - addbool(m, "HAS_NPN", 1); -#else addbool(m, "HAS_NPN", 0); -#endif - -#if HAVE_ALPN addbool(m, "HAS_ALPN", 1); -#else - addbool(m, "HAS_ALPN", 0); -#endif #if defined(SSL2_VERSION) && !defined(OPENSSL_NO_SSL2) addbool(m, "HAS_SSLv2", 1); @@ -6403,49 +5996,91 @@ PyInit__ssl(void) addbool(m, "HAS_TLSv1_3", 0); #endif + return 0; +} + +static int +sslmodule_init_errorcodes(PyObject *module) +{ + _sslmodulestate *state = get_ssl_state(module); + + struct py_ssl_error_code *errcode; + struct py_ssl_library_code *libcode; + /* Mappings for error codes */ - err_codes_to_names = PyDict_New(); - err_names_to_codes = PyDict_New(); - if (err_codes_to_names == NULL || err_names_to_codes == NULL) - return NULL; + state->err_codes_to_names = PyDict_New(); + if (state->err_codes_to_names == NULL) + return -1; + state->err_names_to_codes = PyDict_New(); + if (state->err_names_to_codes == NULL) + return -1; + state->lib_codes_to_names = PyDict_New(); + if (state->lib_codes_to_names == NULL) + return -1; + errcode = error_codes; while (errcode->mnemonic != NULL) { PyObject *mnemo, *key; mnemo = PyUnicode_FromString(errcode->mnemonic); key = Py_BuildValue("ii", errcode->library, errcode->reason); if (mnemo == NULL || key == NULL) - return NULL; - if (PyDict_SetItem(err_codes_to_names, key, mnemo)) - return NULL; - if (PyDict_SetItem(err_names_to_codes, mnemo, key)) - return NULL; + return -1; + if (PyDict_SetItem(state->err_codes_to_names, key, mnemo)) + return -1; + if (PyDict_SetItem(state->err_names_to_codes, mnemo, key)) + return -1; Py_DECREF(key); Py_DECREF(mnemo); errcode++; } - if (PyModule_AddObject(m, "err_codes_to_names", err_codes_to_names)) - return NULL; - if (PyModule_AddObject(m, "err_names_to_codes", err_names_to_codes)) - return NULL; - lib_codes_to_names = PyDict_New(); - if (lib_codes_to_names == NULL) - return NULL; libcode = library_codes; while (libcode->library != NULL) { PyObject *mnemo, *key; key = PyLong_FromLong(libcode->code); mnemo = PyUnicode_FromString(libcode->library); if (key == NULL || mnemo == NULL) - return NULL; - if (PyDict_SetItem(lib_codes_to_names, key, mnemo)) - return NULL; + return -1; + if (PyDict_SetItem(state->lib_codes_to_names, key, mnemo)) + return -1; Py_DECREF(key); Py_DECREF(mnemo); libcode++; } - if (PyModule_AddObject(m, "lib_codes_to_names", lib_codes_to_names)) - return NULL; + + if (PyModule_AddObjectRef(module, "err_codes_to_names", state->err_codes_to_names)) + return -1; + if (PyModule_AddObjectRef(module, "err_names_to_codes", state->err_names_to_codes)) + return -1; + if (PyModule_AddObjectRef(module, "lib_codes_to_names", state->lib_codes_to_names)) + return -1; + + return 0; +} + +static void +parse_openssl_version(unsigned long libver, + unsigned int *major, unsigned int *minor, + unsigned int *fix, unsigned int *patch, + unsigned int *status) +{ + *status = libver & 0xF; + libver >>= 4; + *patch = libver & 0xFF; + libver >>= 8; + *fix = libver & 0xFF; + libver >>= 8; + *minor = libver & 0xFF; + libver >>= 8; + *major = libver & 0xFF; +} + +static int +sslmodule_init_versioninfo(PyObject *m) +{ + PyObject *r; + unsigned long libver; + unsigned int major, minor, fix, patch, status; /* OpenSSL version */ /* SSLeay() gives us the version of the library linked against, @@ -6453,23 +6088,155 @@ PyInit__ssl(void) */ libver = OpenSSL_version_num(); r = PyLong_FromUnsignedLong(libver); - if (r == NULL) - return NULL; - if (PyModule_AddObject(m, "OPENSSL_VERSION_NUMBER", r)) - return NULL; + if (r == NULL || PyModule_AddObject(m, "OPENSSL_VERSION_NUMBER", r)) + return -1; + parse_openssl_version(libver, &major, &minor, &fix, &patch, &status); r = Py_BuildValue("IIIII", major, minor, fix, patch, status); if (r == NULL || PyModule_AddObject(m, "OPENSSL_VERSION_INFO", r)) - return NULL; + return -1; + r = PyUnicode_FromString(OpenSSL_version(OPENSSL_VERSION)); if (r == NULL || PyModule_AddObject(m, "OPENSSL_VERSION", r)) - return NULL; + return -1; libver = OPENSSL_VERSION_NUMBER; parse_openssl_version(libver, &major, &minor, &fix, &patch, &status); r = Py_BuildValue("IIIII", major, minor, fix, patch, status); if (r == NULL || PyModule_AddObject(m, "_OPENSSL_API_VERSION", r)) - return NULL; + return -1; + + return 0; +} + +static int +sslmodule_init_types(PyObject *module) +{ + _sslmodulestate *state = get_ssl_state(module); - return m; + state->PySSLContext_Type = (PyTypeObject *)PyType_FromModuleAndSpec( + module, &PySSLContext_spec, NULL + ); + if (state->PySSLContext_Type == NULL) + return -1; + + state->PySSLSocket_Type = (PyTypeObject *)PyType_FromModuleAndSpec( + module, &PySSLSocket_spec, NULL + ); + if (state->PySSLSocket_Type == NULL) + return -1; + + state->PySSLMemoryBIO_Type = (PyTypeObject *)PyType_FromModuleAndSpec( + module, &PySSLMemoryBIO_spec, NULL + ); + if (state->PySSLMemoryBIO_Type == NULL) + return -1; + + state->PySSLSession_Type = (PyTypeObject *)PyType_FromModuleAndSpec( + module, &PySSLSession_spec, NULL + ); + if (state->PySSLSession_Type == NULL) + return -1; + + state->PySSLCertificate_Type = (PyTypeObject *)PyType_FromModuleAndSpec( + module, &PySSLCertificate_spec, NULL + ); + if (state->PySSLCertificate_Type == NULL) + return -1; + + if (PyModule_AddType(module, state->PySSLContext_Type)) + return -1; + if (PyModule_AddType(module, state->PySSLSocket_Type)) + return -1; + if (PyModule_AddType(module, state->PySSLMemoryBIO_Type)) + return -1; + if (PyModule_AddType(module, state->PySSLSession_Type)) + return -1; + if (PyModule_AddType(module, state->PySSLCertificate_Type)) + return -1; + return 0; +} + +static PyModuleDef_Slot sslmodule_slots[] = { + {Py_mod_exec, sslmodule_init_types}, + {Py_mod_exec, sslmodule_init_exceptions}, + {Py_mod_exec, sslmodule_init_socketapi}, + {Py_mod_exec, sslmodule_init_errorcodes}, + {Py_mod_exec, sslmodule_init_constants}, + {Py_mod_exec, sslmodule_init_versioninfo}, + {0, NULL} +}; + +static int +sslmodule_traverse(PyObject *m, visitproc visit, void *arg) +{ + _sslmodulestate *state = get_ssl_state(m); + + Py_VISIT(state->PySSLContext_Type); + Py_VISIT(state->PySSLSocket_Type); + Py_VISIT(state->PySSLMemoryBIO_Type); + Py_VISIT(state->PySSLSession_Type); + Py_VISIT(state->PySSLCertificate_Type); + Py_VISIT(state->PySSLErrorObject); + Py_VISIT(state->PySSLCertVerificationErrorObject); + Py_VISIT(state->PySSLZeroReturnErrorObject); + Py_VISIT(state->PySSLWantReadErrorObject); + Py_VISIT(state->PySSLWantWriteErrorObject); + Py_VISIT(state->PySSLSyscallErrorObject); + Py_VISIT(state->PySSLEOFErrorObject); + Py_VISIT(state->err_codes_to_names); + Py_VISIT(state->err_names_to_codes); + Py_VISIT(state->lib_codes_to_names); + Py_VISIT(state->Sock_Type); + + return 0; +} + +static int +sslmodule_clear(PyObject *m) +{ + _sslmodulestate *state = get_ssl_state(m); + + Py_CLEAR(state->PySSLContext_Type); + Py_CLEAR(state->PySSLSocket_Type); + Py_CLEAR(state->PySSLMemoryBIO_Type); + Py_CLEAR(state->PySSLSession_Type); + Py_CLEAR(state->PySSLCertificate_Type); + Py_CLEAR(state->PySSLErrorObject); + Py_CLEAR(state->PySSLCertVerificationErrorObject); + Py_CLEAR(state->PySSLZeroReturnErrorObject); + Py_CLEAR(state->PySSLWantReadErrorObject); + Py_CLEAR(state->PySSLWantWriteErrorObject); + Py_CLEAR(state->PySSLSyscallErrorObject); + Py_CLEAR(state->PySSLEOFErrorObject); + Py_CLEAR(state->err_codes_to_names); + Py_CLEAR(state->err_names_to_codes); + Py_CLEAR(state->lib_codes_to_names); + Py_CLEAR(state->Sock_Type); + + return 0; +} + +static void +sslmodule_free(void *m) +{ + sslmodule_clear((PyObject *)m); +} + +static struct PyModuleDef _sslmodule_def = { + PyModuleDef_HEAD_INIT, + .m_name = "_ssl", + .m_doc = module_doc, + .m_size = sizeof(_sslmodulestate), + .m_methods = PySSL_methods, + .m_slots = sslmodule_slots, + .m_traverse = sslmodule_traverse, + .m_clear = sslmodule_clear, + .m_free = sslmodule_free +}; + +PyMODINIT_FUNC +PyInit__ssl(void) +{ + return PyModuleDef_Init(&_sslmodule_def); } diff --git a/contrib/tools/python3/src/Modules/_ssl.h b/contrib/tools/python3/src/Modules/_ssl.h new file mode 100644 index 0000000000..5fe6504a9d --- /dev/null +++ b/contrib/tools/python3/src/Modules/_ssl.h @@ -0,0 +1,74 @@ +#ifndef Py_SSL_H +#define Py_SSL_H + +/* OpenSSL header files */ +#include "openssl/evp.h" +#include "openssl/x509.h" + +/* + * ssl module state + */ +typedef struct { + /* Types */ + PyTypeObject *PySSLContext_Type; + PyTypeObject *PySSLSocket_Type; + PyTypeObject *PySSLMemoryBIO_Type; + PyTypeObject *PySSLSession_Type; + PyTypeObject *PySSLCertificate_Type; + /* SSL error object */ + PyObject *PySSLErrorObject; + PyObject *PySSLCertVerificationErrorObject; + PyObject *PySSLZeroReturnErrorObject; + PyObject *PySSLWantReadErrorObject; + PyObject *PySSLWantWriteErrorObject; + PyObject *PySSLSyscallErrorObject; + PyObject *PySSLEOFErrorObject; + /* Error mappings */ + PyObject *err_codes_to_names; + PyObject *err_names_to_codes; + PyObject *lib_codes_to_names; + /* socket type from module CAPI */ + PyTypeObject *Sock_Type; +} _sslmodulestate; + +static struct PyModuleDef _sslmodule_def; + +Py_LOCAL_INLINE(_sslmodulestate*) +get_ssl_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (_sslmodulestate *)state; +} + +#define get_state_type(type) \ + (get_ssl_state(_PyType_GetModuleByDef(type, &_sslmodule_def))) +#define get_state_ctx(c) (((PySSLContext *)(c))->state) +#define get_state_sock(s) (((PySSLSocket *)(s))->ctx->state) +#define get_state_obj(o) ((_sslmodulestate *)PyType_GetModuleState(Py_TYPE(o))) +#define get_state_mbio(b) get_state_obj(b) +#define get_state_cert(c) get_state_obj(c) + +/* ************************************************************************ + * certificate + */ + +enum py_ssl_encoding { + PY_SSL_ENCODING_PEM=X509_FILETYPE_PEM, + PY_SSL_ENCODING_DER=X509_FILETYPE_ASN1, + PY_SSL_ENCODING_PEM_AUX=X509_FILETYPE_PEM + 0x100, +}; + +typedef struct { + PyObject_HEAD + X509 *cert; + Py_hash_t hash; +} PySSLCertificate; + +/* ************************************************************************ + * helpers and utils + */ +static PyObject *_PySSL_BytesFromBIO(_sslmodulestate *state, BIO *bio); +static PyObject *_PySSL_UnicodeFromBIO(_sslmodulestate *state, BIO *bio, const char *error); + +#endif /* Py_SSL_H */ diff --git a/contrib/tools/python3/src/Modules/_ssl/cert.c b/contrib/tools/python3/src/Modules/_ssl/cert.c new file mode 100644 index 0000000000..bda66dc4d9 --- /dev/null +++ b/contrib/tools/python3/src/Modules/_ssl/cert.c @@ -0,0 +1,245 @@ +#include "Python.h" +#include "../_ssl.h" + +#include "openssl/err.h" +#include "openssl/bio.h" +#include "openssl/pem.h" +#include "openssl/x509.h" + +/*[clinic input] +module _ssl +class _ssl.Certificate "PySSLCertificate *" "PySSLCertificate_Type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=780fc647948cfffc]*/ + +#include "clinic/cert.c.h" + +static PyObject * +newCertificate(PyTypeObject *type, X509 *cert, int upref) +{ + PySSLCertificate *self; + + assert(type != NULL && type->tp_alloc != NULL); + assert(cert != NULL); + + self = (PySSLCertificate *) type->tp_alloc(type, 0); + if (self == NULL) { + return NULL; + } + if (upref == 1) { + X509_up_ref(cert); + } + self->cert = cert; + self->hash = -1; + + return (PyObject *) self; +} + +static PyObject * +_PySSL_CertificateFromX509(_sslmodulestate *state, X509 *cert, int upref) +{ + return newCertificate(state->PySSLCertificate_Type, cert, upref); +} + +static PyObject* +_PySSL_CertificateFromX509Stack(_sslmodulestate *state, STACK_OF(X509) *stack, int upref) +{ + int len, i; + PyObject *result = NULL; + + len = sk_X509_num(stack); + result = PyList_New(len); + if (result == NULL) { + return NULL; + } + for (i = 0; i < len; i++) { + X509 *cert = sk_X509_value(stack, i); + PyObject *ocert = _PySSL_CertificateFromX509(state, cert, upref); + if (ocert == NULL) { + Py_DECREF(result); + return NULL; + } + PyList_SetItem(result, i, ocert); + } + return result; +} + +/*[clinic input] +_ssl.Certificate.public_bytes + format: int(c_default="PY_SSL_ENCODING_PEM") = Encoding.PEM + +[clinic start generated code]*/ + +static PyObject * +_ssl_Certificate_public_bytes_impl(PySSLCertificate *self, int format) +/*[clinic end generated code: output=c01ddbb697429e12 input=4d38c45e874b0e64]*/ +{ + BIO *bio; + int retcode; + PyObject *result; + _sslmodulestate *state = get_state_cert(self); + + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) { + PyErr_SetString(state->PySSLErrorObject, + "failed to allocate BIO"); + return NULL; + } + switch(format) { + case PY_SSL_ENCODING_PEM: + retcode = PEM_write_bio_X509(bio, self->cert); + break; + case PY_SSL_ENCODING_PEM_AUX: + retcode = PEM_write_bio_X509_AUX(bio, self->cert); + break; + case PY_SSL_ENCODING_DER: + retcode = i2d_X509_bio(bio, self->cert); + break; + default: + PyErr_SetString(PyExc_ValueError, "Unsupported format"); + BIO_free(bio); + return NULL; + } + if (retcode != 1) { + BIO_free(bio); + _setSSLError(state, NULL, 0, __FILE__, __LINE__); + return NULL; + } + if (format == PY_SSL_ENCODING_DER) { + result = _PySSL_BytesFromBIO(state, bio); + } else { + result = _PySSL_UnicodeFromBIO(state, bio, "error"); + } + BIO_free(bio); + return result; +} + + +/*[clinic input] +_ssl.Certificate.get_info + +[clinic start generated code]*/ + +static PyObject * +_ssl_Certificate_get_info_impl(PySSLCertificate *self) +/*[clinic end generated code: output=0f0deaac54f4408b input=ba2c1694b39d0778]*/ +{ + return _decode_certificate(get_state_cert(self), self->cert); +} + +static PyObject* +_x509name_print(_sslmodulestate *state, X509_NAME *name, int indent, unsigned long flags) +{ + PyObject *res; + BIO *biobuf; + + biobuf = BIO_new(BIO_s_mem()); + if (biobuf == NULL) { + PyErr_SetString(PyExc_MemoryError, "failed to allocate BIO"); + return NULL; + } + + if (X509_NAME_print_ex(biobuf, name, indent, flags) <= 0) { + _setSSLError(state, NULL, 0, __FILE__, __LINE__); + BIO_free(biobuf); + return NULL; + } + res = _PySSL_UnicodeFromBIO(state, biobuf, "strict"); + BIO_free(biobuf); + return res; +} + +/* ************************************************************************ + * PySSLCertificate_Type + */ + +static PyObject * +certificate_repr(PySSLCertificate *self) +{ + PyObject *osubject, *result; + + /* subject string is ASCII encoded, UTF-8 chars are quoted */ + osubject = _x509name_print( + get_state_cert(self), + X509_get_subject_name(self->cert), + 0, + XN_FLAG_RFC2253 + ); + if (osubject == NULL) + return NULL; + result = PyUnicode_FromFormat( + "<%s '%U'>", + Py_TYPE(self)->tp_name, osubject + ); + Py_DECREF(osubject); + return result; +} + +static Py_hash_t +certificate_hash(PySSLCertificate *self) +{ + if (self->hash == (Py_hash_t)-1) { + unsigned long hash; + hash = X509_subject_name_hash(self->cert); + if ((Py_hash_t)hash == (Py_hash_t)-1) { + self->hash = -2; + } else { + self->hash = (Py_hash_t)hash; + } + } + return self->hash; +} + +static PyObject * +certificate_richcompare(PySSLCertificate *self, PyObject *other, int op) +{ + int cmp; + _sslmodulestate *state = get_state_cert(self); + + if (Py_TYPE(other) != state->PySSLCertificate_Type) { + Py_RETURN_NOTIMPLEMENTED; + } + /* only support == and != */ + if ((op != Py_EQ) && (op != Py_NE)) { + Py_RETURN_NOTIMPLEMENTED; + } + cmp = X509_cmp(self->cert, ((PySSLCertificate*)other)->cert); + if (((op == Py_EQ) && (cmp == 0)) || ((op == Py_NE) && (cmp != 0))) { + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + +static void +certificate_dealloc(PySSLCertificate *self) +{ + PyTypeObject *tp = Py_TYPE(self); + X509_free(self->cert); + Py_TYPE(self)->tp_free(self); + Py_DECREF(tp); +} + +static PyMethodDef certificate_methods[] = { + /* methods */ + _SSL_CERTIFICATE_PUBLIC_BYTES_METHODDEF + _SSL_CERTIFICATE_GET_INFO_METHODDEF + {NULL, NULL} +}; + +static PyType_Slot PySSLCertificate_slots[] = { + {Py_tp_dealloc, certificate_dealloc}, + {Py_tp_repr, certificate_repr}, + {Py_tp_hash, certificate_hash}, + {Py_tp_richcompare, certificate_richcompare}, + {Py_tp_methods, certificate_methods}, + {0, 0}, +}; + +static PyType_Spec PySSLCertificate_spec = { + "_ssl.Certificate", + sizeof(PySSLCertificate), + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE, + PySSLCertificate_slots, +}; diff --git a/contrib/tools/python3/src/Modules/_ssl/clinic/cert.c.h b/contrib/tools/python3/src/Modules/_ssl/clinic/cert.c.h new file mode 100644 index 0000000000..c4377128b3 --- /dev/null +++ b/contrib/tools/python3/src/Modules/_ssl/clinic/cert.c.h @@ -0,0 +1,60 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(_ssl_Certificate_public_bytes__doc__, +"public_bytes($self, /, format=Encoding.PEM)\n" +"--\n" +"\n"); + +#define _SSL_CERTIFICATE_PUBLIC_BYTES_METHODDEF \ + {"public_bytes", (PyCFunction)(void(*)(void))_ssl_Certificate_public_bytes, METH_FASTCALL|METH_KEYWORDS, _ssl_Certificate_public_bytes__doc__}, + +static PyObject * +_ssl_Certificate_public_bytes_impl(PySSLCertificate *self, int format); + +static PyObject * +_ssl_Certificate_public_bytes(PySSLCertificate *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"format", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "public_bytes", 0}; + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + int format = PY_SSL_ENCODING_PEM; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + format = _PyLong_AsInt(args[0]); + if (format == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_pos: + return_value = _ssl_Certificate_public_bytes_impl(self, format); + +exit: + return return_value; +} + +PyDoc_STRVAR(_ssl_Certificate_get_info__doc__, +"get_info($self, /)\n" +"--\n" +"\n"); + +#define _SSL_CERTIFICATE_GET_INFO_METHODDEF \ + {"get_info", (PyCFunction)_ssl_Certificate_get_info, METH_NOARGS, _ssl_Certificate_get_info__doc__}, + +static PyObject * +_ssl_Certificate_get_info_impl(PySSLCertificate *self); + +static PyObject * +_ssl_Certificate_get_info(PySSLCertificate *self, PyObject *Py_UNUSED(ignored)) +{ + return _ssl_Certificate_get_info_impl(self); +} +/*[clinic end generated code: output=569d161749ead2da input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/_ssl/debughelpers.c b/contrib/tools/python3/src/Modules/_ssl/debughelpers.c index af56f9d28d..03c125eb44 100644 --- a/contrib/tools/python3/src/Modules/_ssl/debughelpers.c +++ b/contrib/tools/python3/src/Modules/_ssl/debughelpers.c @@ -21,7 +21,7 @@ _PySSL_msg_callback(int write_p, int version, int content_type, threadstate = PyGILState_Ensure(); ssl_obj = (PySSLSocket *)SSL_get_app_data(ssl); - assert(PySSLSocket_Check(ssl_obj)); + assert(Py_IS_TYPE(ssl_obj, get_state_sock(ssl_obj)->PySSLSocket_Type)); if (ssl_obj->ctx->msg_cb == NULL) { PyGILState_Release(threadstate); return; @@ -114,8 +114,6 @@ _PySSLContext_set_msg_callback(PySSLContext *self, PyObject *arg, void *c) { return 0; } -#ifdef HAVE_OPENSSL_KEYLOG - static void _PySSL_keylog_callback(const SSL *ssl, const char *line) { @@ -127,7 +125,7 @@ _PySSL_keylog_callback(const SSL *ssl, const char *line) threadstate = PyGILState_Ensure(); ssl_obj = (PySSLSocket *)SSL_get_app_data(ssl); - assert(PySSLSocket_Check(ssl_obj)); + assert(Py_IS_TYPE(ssl_obj, get_state_sock(ssl_obj)->PySSLSocket_Type)); if (ssl_obj->ctx->keylog_bio == NULL) { return; } @@ -201,7 +199,7 @@ _PySSLContext_set_keylog_filename(PySSLContext *self, PyObject *arg, void *c) { self->keylog_bio = BIO_new_fp(fp, BIO_CLOSE | BIO_FP_TEXT); if (self->keylog_bio == NULL) { - PyErr_SetString(PySSLErrorObject, + PyErr_SetString(get_state_ctx(self)->PySSLErrorObject, "Can't malloc memory for keylog file"); return -1; } @@ -219,5 +217,3 @@ _PySSLContext_set_keylog_filename(PySSLContext *self, PyObject *arg, void *c) { SSL_CTX_set_keylog_callback(self->ctx, _PySSL_keylog_callback); return 0; } - -#endif diff --git a/contrib/tools/python3/src/Modules/_ssl/misc.c b/contrib/tools/python3/src/Modules/_ssl/misc.c new file mode 100644 index 0000000000..4de091d57e --- /dev/null +++ b/contrib/tools/python3/src/Modules/_ssl/misc.c @@ -0,0 +1,34 @@ +#include "Python.h" +#include "../_ssl.h" + +#include "openssl/bio.h" + +/* BIO_s_mem() to PyBytes + */ +static PyObject * +_PySSL_BytesFromBIO(_sslmodulestate *state, BIO *bio) +{ + long size; + char *data = NULL; + size = BIO_get_mem_data(bio, &data); + if (data == NULL || size < 0) { + PyErr_SetString(PyExc_ValueError, "Not a memory BIO"); + return NULL; + } + return PyBytes_FromStringAndSize(data, size); +} + +/* BIO_s_mem() to PyUnicode + */ +static PyObject * +_PySSL_UnicodeFromBIO(_sslmodulestate *state, BIO *bio, const char *error) +{ + long size; + char *data = NULL; + size = BIO_get_mem_data(bio, &data); + if (data == NULL || size < 0) { + PyErr_SetString(PyExc_ValueError, "Not a memory BIO"); + return NULL; + } + return PyUnicode_DecodeUTF8(data, size, error); +} diff --git a/contrib/tools/python3/src/Modules/_struct.c b/contrib/tools/python3/src/Modules/_struct.c index f759f0b169..30ad9f2b79 100644 --- a/contrib/tools/python3/src/Modules/_struct.c +++ b/contrib/tools/python3/src/Modules/_struct.c @@ -6,6 +6,7 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" +#include "pycore_moduleobject.h" // _PyModule_GetState() #include "structmember.h" // PyMemberDef #include <ctype.h> @@ -15,6 +16,7 @@ class Struct "PyStructObject *" "&PyStructType" /*[clinic end generated code: output=da39a3ee5e6b4b0d input=9b032058a83ed7c3]*/ typedef struct { + PyObject *cache; PyObject *PyStructType; PyObject *unpackiter_type; PyObject *StructError; @@ -23,23 +25,26 @@ typedef struct { static inline _structmodulestate* get_struct_state(PyObject *module) { - void *state = PyModule_GetState(module); + void *state = _PyModule_GetState(module); assert(state != NULL); return (_structmodulestate *)state; } static struct PyModuleDef _structmodule; -#define _structmodulestate_global get_struct_state(PyState_FindModule(&_structmodule)) +#define get_struct_state_structinst(self) \ + (get_struct_state(_PyType_GetModuleByDef(Py_TYPE(self), &_structmodule))) +#define get_struct_state_iterinst(self) \ + (get_struct_state(PyType_GetModule(Py_TYPE(self)))) /* The translation function for each format character is table driven */ typedef struct _formatdef { char format; Py_ssize_t size; Py_ssize_t alignment; - PyObject* (*unpack)(const char *, + PyObject* (*unpack)(_structmodulestate *, const char *, const struct _formatdef *); - int (*pack)(char *, PyObject *, + int (*pack)(_structmodulestate *, char *, PyObject *, const struct _formatdef *); } formatdef; @@ -61,10 +66,7 @@ typedef struct { PyObject *weakreflist; /* List of weak references */ } PyStructObject; - -#define PyStruct_Check(op) PyObject_TypeCheck(op, (PyTypeObject *)_structmodulestate_global->PyStructType) -#define PyStruct_CheckExact(op) Py_IS_TYPE(op, (PyTypeObject *)_structmodulestate_global->PyStructType) - +#define PyStruct_Check(op, state) PyObject_TypeCheck(op, (PyTypeObject *)(state)->PyStructType) /* Define various structs to figure out the alignments of types */ @@ -102,12 +104,20 @@ class cache_struct_converter(CConverter): converter = 'cache_struct_converter' c_default = "NULL" + def parse_arg(self, argname, displayname): + return """ + if (!{converter}(module, {argname}, &{paramname})) {{{{ + goto exit; + }}}} + """.format(argname=argname, paramname=self.name, + converter=self.converter) + def cleanup(self): return "Py_XDECREF(%s);\n" % self.name [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=49957cca130ffb63]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=d6746621c2fb1a7d]*/ -static int cache_struct_converter(PyObject *, PyStructObject **); +static int cache_struct_converter(PyObject *, PyObject *, PyStructObject **); #include "clinic/_struct.c.h" @@ -115,18 +125,18 @@ static int cache_struct_converter(PyObject *, PyStructObject **); PyLongObject if possible, otherwise fails. Caller should decref. */ static PyObject * -get_pylong(PyObject *v) +get_pylong(_structmodulestate *state, PyObject *v) { assert(v != NULL); if (!PyLong_Check(v)) { /* Not an integer; try to use __index__ to convert. */ if (PyIndex_Check(v)) { - v = PyNumber_Index(v); + v = _PyNumber_Index(v); if (v == NULL) return NULL; } else { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "required argument is not an integer"); return NULL; } @@ -142,11 +152,11 @@ get_pylong(PyObject *v) one */ static int -get_long(PyObject *v, long *p) +get_long(_structmodulestate *state, PyObject *v, long *p) { long x; - v = get_pylong(v); + v = get_pylong(state, v); if (v == NULL) return -1; assert(PyLong_Check(v)); @@ -154,7 +164,7 @@ get_long(PyObject *v, long *p) Py_DECREF(v); if (x == (long)-1 && PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_OverflowError)) - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "argument out of range"); return -1; } @@ -166,11 +176,11 @@ get_long(PyObject *v, long *p) /* Same, but handling unsigned long */ static int -get_ulong(PyObject *v, unsigned long *p) +get_ulong(_structmodulestate *state, PyObject *v, unsigned long *p) { unsigned long x; - v = get_pylong(v); + v = get_pylong(state, v); if (v == NULL) return -1; assert(PyLong_Check(v)); @@ -178,7 +188,7 @@ get_ulong(PyObject *v, unsigned long *p) Py_DECREF(v); if (x == (unsigned long)-1 && PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_OverflowError)) - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "argument out of range"); return -1; } @@ -189,11 +199,11 @@ get_ulong(PyObject *v, unsigned long *p) /* Same, but handling native long long. */ static int -get_longlong(PyObject *v, long long *p) +get_longlong(_structmodulestate *state, PyObject *v, long long *p) { long long x; - v = get_pylong(v); + v = get_pylong(state, v); if (v == NULL) return -1; assert(PyLong_Check(v)); @@ -201,7 +211,7 @@ get_longlong(PyObject *v, long long *p) Py_DECREF(v); if (x == (long long)-1 && PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_OverflowError)) - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "argument out of range"); return -1; } @@ -212,11 +222,11 @@ get_longlong(PyObject *v, long long *p) /* Same, but handling native unsigned long long. */ static int -get_ulonglong(PyObject *v, unsigned long long *p) +get_ulonglong(_structmodulestate *state, PyObject *v, unsigned long long *p) { unsigned long long x; - v = get_pylong(v); + v = get_pylong(state, v); if (v == NULL) return -1; assert(PyLong_Check(v)); @@ -224,7 +234,7 @@ get_ulonglong(PyObject *v, unsigned long long *p) Py_DECREF(v); if (x == (unsigned long long)-1 && PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_OverflowError)) - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "argument out of range"); return -1; } @@ -235,11 +245,11 @@ get_ulonglong(PyObject *v, unsigned long long *p) /* Same, but handling Py_ssize_t */ static int -get_ssize_t(PyObject *v, Py_ssize_t *p) +get_ssize_t(_structmodulestate *state, PyObject *v, Py_ssize_t *p) { Py_ssize_t x; - v = get_pylong(v); + v = get_pylong(state, v); if (v == NULL) return -1; assert(PyLong_Check(v)); @@ -247,7 +257,7 @@ get_ssize_t(PyObject *v, Py_ssize_t *p) Py_DECREF(v); if (x == (Py_ssize_t)-1 && PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_OverflowError)) - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "argument out of range"); return -1; } @@ -258,11 +268,11 @@ get_ssize_t(PyObject *v, Py_ssize_t *p) /* Same, but handling size_t */ static int -get_size_t(PyObject *v, size_t *p) +get_size_t(_structmodulestate *state, PyObject *v, size_t *p) { size_t x; - v = get_pylong(v); + v = get_pylong(state, v); if (v == NULL) return -1; assert(PyLong_Check(v)); @@ -270,7 +280,7 @@ get_size_t(PyObject *v, size_t *p) Py_DECREF(v); if (x == (size_t)-1 && PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_OverflowError)) - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "argument out of range"); return -1; } @@ -279,7 +289,7 @@ get_size_t(PyObject *v, size_t *p) } -#define RANGE_ERROR(x, f, flag, mask) return _range_error(f, flag) +#define RANGE_ERROR(state, x, f, flag, mask) return _range_error(state, f, flag) /* Floating point helpers */ @@ -298,13 +308,14 @@ unpack_halffloat(const char *p, /* start of 2-byte string */ } static int -pack_halffloat(char *p, /* start of 2-byte string */ +pack_halffloat(_structmodulestate *state, + char *p, /* start of 2-byte string */ PyObject *v, /* value to pack */ int le) /* true for little-endian, false for big-endian */ { double x = PyFloat_AsDouble(v); if (x == -1.0 && PyErr_Occurred()) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "required argument is not a float"); return -1; } @@ -337,7 +348,7 @@ unpack_double(const char *p, /* start of 8-byte string */ /* Helper to format the range error exceptions */ static int -_range_error(const formatdef *f, int is_unsigned) +_range_error(_structmodulestate *state, const formatdef *f, int is_unsigned) { /* ulargest is the largest unsigned value with f->size bytes. * Note that the simpler: @@ -350,13 +361,13 @@ _range_error(const formatdef *f, int is_unsigned) const size_t ulargest = (size_t)-1 >> ((SIZEOF_SIZE_T - f->size)*8); assert(f->size >= 1 && f->size <= SIZEOF_SIZE_T); if (is_unsigned) - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "'%c' format requires 0 <= number <= %zu", f->format, ulargest); else { const Py_ssize_t largest = (Py_ssize_t)(ulargest >> 1); - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "'%c' format requires %zd <= number <= %zd", f->format, ~ largest, @@ -388,25 +399,25 @@ _range_error(const formatdef *f, int is_unsigned) does this). */ static PyObject * -nu_char(const char *p, const formatdef *f) +nu_char(_structmodulestate *state, const char *p, const formatdef *f) { return PyBytes_FromStringAndSize(p, 1); } static PyObject * -nu_byte(const char *p, const formatdef *f) +nu_byte(_structmodulestate *state, const char *p, const formatdef *f) { return PyLong_FromLong((long) *(signed char *)p); } static PyObject * -nu_ubyte(const char *p, const formatdef *f) +nu_ubyte(_structmodulestate *state, const char *p, const formatdef *f) { return PyLong_FromLong((long) *(unsigned char *)p); } static PyObject * -nu_short(const char *p, const formatdef *f) +nu_short(_structmodulestate *state, const char *p, const formatdef *f) { short x; memcpy((char *)&x, p, sizeof x); @@ -414,7 +425,7 @@ nu_short(const char *p, const formatdef *f) } static PyObject * -nu_ushort(const char *p, const formatdef *f) +nu_ushort(_structmodulestate *state, const char *p, const formatdef *f) { unsigned short x; memcpy((char *)&x, p, sizeof x); @@ -422,7 +433,7 @@ nu_ushort(const char *p, const formatdef *f) } static PyObject * -nu_int(const char *p, const formatdef *f) +nu_int(_structmodulestate *state, const char *p, const formatdef *f) { int x; memcpy((char *)&x, p, sizeof x); @@ -430,7 +441,7 @@ nu_int(const char *p, const formatdef *f) } static PyObject * -nu_uint(const char *p, const formatdef *f) +nu_uint(_structmodulestate *state, const char *p, const formatdef *f) { unsigned int x; memcpy((char *)&x, p, sizeof x); @@ -438,7 +449,7 @@ nu_uint(const char *p, const formatdef *f) } static PyObject * -nu_long(const char *p, const formatdef *f) +nu_long(_structmodulestate *state, const char *p, const formatdef *f) { long x; memcpy((char *)&x, p, sizeof x); @@ -446,7 +457,7 @@ nu_long(const char *p, const formatdef *f) } static PyObject * -nu_ulong(const char *p, const formatdef *f) +nu_ulong(_structmodulestate *state, const char *p, const formatdef *f) { unsigned long x; memcpy((char *)&x, p, sizeof x); @@ -454,7 +465,7 @@ nu_ulong(const char *p, const formatdef *f) } static PyObject * -nu_ssize_t(const char *p, const formatdef *f) +nu_ssize_t(_structmodulestate *state, const char *p, const formatdef *f) { Py_ssize_t x; memcpy((char *)&x, p, sizeof x); @@ -462,7 +473,7 @@ nu_ssize_t(const char *p, const formatdef *f) } static PyObject * -nu_size_t(const char *p, const formatdef *f) +nu_size_t(_structmodulestate *state, const char *p, const formatdef *f) { size_t x; memcpy((char *)&x, p, sizeof x); @@ -470,7 +481,7 @@ nu_size_t(const char *p, const formatdef *f) } static PyObject * -nu_longlong(const char *p, const formatdef *f) +nu_longlong(_structmodulestate *state, const char *p, const formatdef *f) { long long x; memcpy((char *)&x, p, sizeof x); @@ -478,7 +489,7 @@ nu_longlong(const char *p, const formatdef *f) } static PyObject * -nu_ulonglong(const char *p, const formatdef *f) +nu_ulonglong(_structmodulestate *state, const char *p, const formatdef *f) { unsigned long long x; memcpy((char *)&x, p, sizeof x); @@ -486,7 +497,7 @@ nu_ulonglong(const char *p, const formatdef *f) } static PyObject * -nu_bool(const char *p, const formatdef *f) +nu_bool(_structmodulestate *state, const char *p, const formatdef *f) { _Bool x; memcpy((char *)&x, p, sizeof x); @@ -495,7 +506,7 @@ nu_bool(const char *p, const formatdef *f) static PyObject * -nu_halffloat(const char *p, const formatdef *f) +nu_halffloat(_structmodulestate *state, const char *p, const formatdef *f) { #if PY_LITTLE_ENDIAN return unpack_halffloat(p, 1); @@ -505,7 +516,7 @@ nu_halffloat(const char *p, const formatdef *f) } static PyObject * -nu_float(const char *p, const formatdef *f) +nu_float(_structmodulestate *state, const char *p, const formatdef *f) { float x; memcpy((char *)&x, p, sizeof x); @@ -513,7 +524,7 @@ nu_float(const char *p, const formatdef *f) } static PyObject * -nu_double(const char *p, const formatdef *f) +nu_double(_structmodulestate *state, const char *p, const formatdef *f) { double x; memcpy((char *)&x, p, sizeof x); @@ -521,7 +532,7 @@ nu_double(const char *p, const formatdef *f) } static PyObject * -nu_void_p(const char *p, const formatdef *f) +nu_void_p(_structmodulestate *state, const char *p, const formatdef *f) { void *x; memcpy((char *)&x, p, sizeof x); @@ -529,13 +540,13 @@ nu_void_p(const char *p, const formatdef *f) } static int -np_byte(char *p, PyObject *v, const formatdef *f) +np_byte(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { long x; - if (get_long(v, &x) < 0) + if (get_long(state, v, &x) < 0) return -1; if (x < -128 || x > 127) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "byte format requires -128 <= number <= 127"); return -1; } @@ -544,13 +555,13 @@ np_byte(char *p, PyObject *v, const formatdef *f) } static int -np_ubyte(char *p, PyObject *v, const formatdef *f) +np_ubyte(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { long x; - if (get_long(v, &x) < 0) + if (get_long(state, v, &x) < 0) return -1; if (x < 0 || x > 255) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "ubyte format requires 0 <= number <= 255"); return -1; } @@ -559,10 +570,10 @@ np_ubyte(char *p, PyObject *v, const formatdef *f) } static int -np_char(char *p, PyObject *v, const formatdef *f) +np_char(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { if (!PyBytes_Check(v) || PyBytes_Size(v) != 1) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "char format requires a bytes object of length 1"); return -1; } @@ -571,14 +582,14 @@ np_char(char *p, PyObject *v, const formatdef *f) } static int -np_short(char *p, PyObject *v, const formatdef *f) +np_short(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { long x; short y; - if (get_long(v, &x) < 0) + if (get_long(state, v, &x) < 0) return -1; if (x < SHRT_MIN || x > SHRT_MAX) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "short format requires " Py_STRINGIFY(SHRT_MIN) " <= number <= " Py_STRINGIFY(SHRT_MAX)); return -1; @@ -589,14 +600,14 @@ np_short(char *p, PyObject *v, const formatdef *f) } static int -np_ushort(char *p, PyObject *v, const formatdef *f) +np_ushort(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { long x; unsigned short y; - if (get_long(v, &x) < 0) + if (get_long(state, v, &x) < 0) return -1; if (x < 0 || x > USHRT_MAX) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "ushort format requires 0 <= number <= " Py_STRINGIFY(USHRT_MAX)); return -1; @@ -607,15 +618,15 @@ np_ushort(char *p, PyObject *v, const formatdef *f) } static int -np_int(char *p, PyObject *v, const formatdef *f) +np_int(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { long x; int y; - if (get_long(v, &x) < 0) + if (get_long(state, v, &x) < 0) return -1; #if (SIZEOF_LONG > SIZEOF_INT) if ((x < ((long)INT_MIN)) || (x > ((long)INT_MAX))) - RANGE_ERROR(x, f, 0, -1); + RANGE_ERROR(state, x, f, 0, -1); #endif y = (int)x; memcpy(p, (char *)&y, sizeof y); @@ -623,76 +634,76 @@ np_int(char *p, PyObject *v, const formatdef *f) } static int -np_uint(char *p, PyObject *v, const formatdef *f) +np_uint(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { unsigned long x; unsigned int y; - if (get_ulong(v, &x) < 0) + if (get_ulong(state, v, &x) < 0) return -1; y = (unsigned int)x; #if (SIZEOF_LONG > SIZEOF_INT) if (x > ((unsigned long)UINT_MAX)) - RANGE_ERROR(y, f, 1, -1); + RANGE_ERROR(state, y, f, 1, -1); #endif memcpy(p, (char *)&y, sizeof y); return 0; } static int -np_long(char *p, PyObject *v, const formatdef *f) +np_long(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { long x; - if (get_long(v, &x) < 0) + if (get_long(state, v, &x) < 0) return -1; memcpy(p, (char *)&x, sizeof x); return 0; } static int -np_ulong(char *p, PyObject *v, const formatdef *f) +np_ulong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { unsigned long x; - if (get_ulong(v, &x) < 0) + if (get_ulong(state, v, &x) < 0) return -1; memcpy(p, (char *)&x, sizeof x); return 0; } static int -np_ssize_t(char *p, PyObject *v, const formatdef *f) +np_ssize_t(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { Py_ssize_t x; - if (get_ssize_t(v, &x) < 0) + if (get_ssize_t(state, v, &x) < 0) return -1; memcpy(p, (char *)&x, sizeof x); return 0; } static int -np_size_t(char *p, PyObject *v, const formatdef *f) +np_size_t(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { size_t x; - if (get_size_t(v, &x) < 0) + if (get_size_t(state, v, &x) < 0) return -1; memcpy(p, (char *)&x, sizeof x); return 0; } static int -np_longlong(char *p, PyObject *v, const formatdef *f) +np_longlong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { long long x; - if (get_longlong(v, &x) < 0) + if (get_longlong(state, v, &x) < 0) return -1; memcpy(p, (char *)&x, sizeof x); return 0; } static int -np_ulonglong(char *p, PyObject *v, const formatdef *f) +np_ulonglong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { unsigned long long x; - if (get_ulonglong(v, &x) < 0) + if (get_ulonglong(state, v, &x) < 0) return -1; memcpy(p, (char *)&x, sizeof x); return 0; @@ -700,7 +711,7 @@ np_ulonglong(char *p, PyObject *v, const formatdef *f) static int -np_bool(char *p, PyObject *v, const formatdef *f) +np_bool(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { int y; _Bool x; @@ -713,21 +724,21 @@ np_bool(char *p, PyObject *v, const formatdef *f) } static int -np_halffloat(char *p, PyObject *v, const formatdef *f) +np_halffloat(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { #if PY_LITTLE_ENDIAN - return pack_halffloat(p, v, 1); + return pack_halffloat(state, p, v, 1); #else - return pack_halffloat(p, v, 0); + return pack_halffloat(state, p, v, 0); #endif } static int -np_float(char *p, PyObject *v, const formatdef *f) +np_float(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { float x = (float)PyFloat_AsDouble(v); if (x == -1 && PyErr_Occurred()) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "required argument is not a float"); return -1; } @@ -736,11 +747,11 @@ np_float(char *p, PyObject *v, const formatdef *f) } static int -np_double(char *p, PyObject *v, const formatdef *f) +np_double(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { double x = PyFloat_AsDouble(v); if (x == -1 && PyErr_Occurred()) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "required argument is not a float"); return -1; } @@ -749,11 +760,11 @@ np_double(char *p, PyObject *v, const formatdef *f) } static int -np_void_p(char *p, PyObject *v, const formatdef *f) +np_void_p(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { void *x; - v = get_pylong(v); + v = get_pylong(state, v); if (v == NULL) return -1; assert(PyLong_Check(v)); @@ -793,7 +804,7 @@ static const formatdef native_table[] = { /* Big-endian routines. *****************************************************/ static PyObject * -bu_int(const char *p, const formatdef *f) +bu_int(_structmodulestate *state, const char *p, const formatdef *f) { long x = 0; Py_ssize_t i = f->size; @@ -808,7 +819,7 @@ bu_int(const char *p, const formatdef *f) } static PyObject * -bu_uint(const char *p, const formatdef *f) +bu_uint(_structmodulestate *state, const char *p, const formatdef *f) { unsigned long x = 0; Py_ssize_t i = f->size; @@ -820,7 +831,7 @@ bu_uint(const char *p, const formatdef *f) } static PyObject * -bu_longlong(const char *p, const formatdef *f) +bu_longlong(_structmodulestate *state, const char *p, const formatdef *f) { long long x = 0; Py_ssize_t i = f->size; @@ -835,7 +846,7 @@ bu_longlong(const char *p, const formatdef *f) } static PyObject * -bu_ulonglong(const char *p, const formatdef *f) +bu_ulonglong(_structmodulestate *state, const char *p, const formatdef *f) { unsigned long long x = 0; Py_ssize_t i = f->size; @@ -847,44 +858,44 @@ bu_ulonglong(const char *p, const formatdef *f) } static PyObject * -bu_halffloat(const char *p, const formatdef *f) +bu_halffloat(_structmodulestate *state, const char *p, const formatdef *f) { return unpack_halffloat(p, 0); } static PyObject * -bu_float(const char *p, const formatdef *f) +bu_float(_structmodulestate *state, const char *p, const formatdef *f) { return unpack_float(p, 0); } static PyObject * -bu_double(const char *p, const formatdef *f) +bu_double(_structmodulestate *state, const char *p, const formatdef *f) { return unpack_double(p, 0); } static PyObject * -bu_bool(const char *p, const formatdef *f) +bu_bool(_structmodulestate *state, const char *p, const formatdef *f) { return PyBool_FromLong(*p != 0); } static int -bp_int(char *p, PyObject *v, const formatdef *f) +bp_int(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { long x; Py_ssize_t i; unsigned char *q = (unsigned char *)p; - if (get_long(v, &x) < 0) + if (get_long(state, v, &x) < 0) return -1; i = f->size; if (i != SIZEOF_LONG) { if ((i == 2) && (x < -32768 || x > 32767)) - RANGE_ERROR(x, f, 0, 0xffffL); + RANGE_ERROR(state, x, f, 0, 0xffffL); #if (SIZEOF_LONG != 4) else if ((i == 4) && (x < -2147483648L || x > 2147483647L)) - RANGE_ERROR(x, f, 0, 0xffffffffL); + RANGE_ERROR(state, x, f, 0, 0xffffffffL); #endif } do { @@ -895,19 +906,19 @@ bp_int(char *p, PyObject *v, const formatdef *f) } static int -bp_uint(char *p, PyObject *v, const formatdef *f) +bp_uint(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { unsigned long x; Py_ssize_t i; unsigned char *q = (unsigned char *)p; - if (get_ulong(v, &x) < 0) + if (get_ulong(state, v, &x) < 0) return -1; i = f->size; if (i != SIZEOF_LONG) { unsigned long maxint = 1; maxint <<= (unsigned long)(i * 8); if (x >= maxint) - RANGE_ERROR(x, f, 1, maxint - 1); + RANGE_ERROR(state, x, f, 1, maxint - 1); } do { q[--i] = (unsigned char)(x & 0xffUL); @@ -917,10 +928,10 @@ bp_uint(char *p, PyObject *v, const formatdef *f) } static int -bp_longlong(char *p, PyObject *v, const formatdef *f) +bp_longlong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { int res; - v = get_pylong(v); + v = get_pylong(state, v); if (v == NULL) return -1; res = _PyLong_AsByteArray((PyLongObject *)v, @@ -933,10 +944,10 @@ bp_longlong(char *p, PyObject *v, const formatdef *f) } static int -bp_ulonglong(char *p, PyObject *v, const formatdef *f) +bp_ulonglong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { int res; - v = get_pylong(v); + v = get_pylong(state, v); if (v == NULL) return -1; res = _PyLong_AsByteArray((PyLongObject *)v, @@ -949,17 +960,17 @@ bp_ulonglong(char *p, PyObject *v, const formatdef *f) } static int -bp_halffloat(char *p, PyObject *v, const formatdef *f) +bp_halffloat(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { - return pack_halffloat(p, v, 0); + return pack_halffloat(state, p, v, 0); } static int -bp_float(char *p, PyObject *v, const formatdef *f) +bp_float(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { double x = PyFloat_AsDouble(v); if (x == -1 && PyErr_Occurred()) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "required argument is not a float"); return -1; } @@ -967,11 +978,11 @@ bp_float(char *p, PyObject *v, const formatdef *f) } static int -bp_double(char *p, PyObject *v, const formatdef *f) +bp_double(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { double x = PyFloat_AsDouble(v); if (x == -1 && PyErr_Occurred()) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "required argument is not a float"); return -1; } @@ -979,7 +990,7 @@ bp_double(char *p, PyObject *v, const formatdef *f) } static int -bp_bool(char *p, PyObject *v, const formatdef *f) +bp_bool(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { int y; y = PyObject_IsTrue(v); @@ -1014,7 +1025,7 @@ static formatdef bigendian_table[] = { /* Little-endian routines. *****************************************************/ static PyObject * -lu_int(const char *p, const formatdef *f) +lu_int(_structmodulestate *state, const char *p, const formatdef *f) { long x = 0; Py_ssize_t i = f->size; @@ -1029,7 +1040,7 @@ lu_int(const char *p, const formatdef *f) } static PyObject * -lu_uint(const char *p, const formatdef *f) +lu_uint(_structmodulestate *state, const char *p, const formatdef *f) { unsigned long x = 0; Py_ssize_t i = f->size; @@ -1041,7 +1052,7 @@ lu_uint(const char *p, const formatdef *f) } static PyObject * -lu_longlong(const char *p, const formatdef *f) +lu_longlong(_structmodulestate *state, const char *p, const formatdef *f) { long long x = 0; Py_ssize_t i = f->size; @@ -1056,7 +1067,7 @@ lu_longlong(const char *p, const formatdef *f) } static PyObject * -lu_ulonglong(const char *p, const formatdef *f) +lu_ulonglong(_structmodulestate *state, const char *p, const formatdef *f) { unsigned long long x = 0; Py_ssize_t i = f->size; @@ -1068,38 +1079,38 @@ lu_ulonglong(const char *p, const formatdef *f) } static PyObject * -lu_halffloat(const char *p, const formatdef *f) +lu_halffloat(_structmodulestate *state, const char *p, const formatdef *f) { return unpack_halffloat(p, 1); } static PyObject * -lu_float(const char *p, const formatdef *f) +lu_float(_structmodulestate *state, const char *p, const formatdef *f) { return unpack_float(p, 1); } static PyObject * -lu_double(const char *p, const formatdef *f) +lu_double(_structmodulestate *state, const char *p, const formatdef *f) { return unpack_double(p, 1); } static int -lp_int(char *p, PyObject *v, const formatdef *f) +lp_int(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { long x; Py_ssize_t i; unsigned char *q = (unsigned char *)p; - if (get_long(v, &x) < 0) + if (get_long(state, v, &x) < 0) return -1; i = f->size; if (i != SIZEOF_LONG) { if ((i == 2) && (x < -32768 || x > 32767)) - RANGE_ERROR(x, f, 0, 0xffffL); + RANGE_ERROR(state, x, f, 0, 0xffffL); #if (SIZEOF_LONG != 4) else if ((i == 4) && (x < -2147483648L || x > 2147483647L)) - RANGE_ERROR(x, f, 0, 0xffffffffL); + RANGE_ERROR(state, x, f, 0, 0xffffffffL); #endif } do { @@ -1110,19 +1121,19 @@ lp_int(char *p, PyObject *v, const formatdef *f) } static int -lp_uint(char *p, PyObject *v, const formatdef *f) +lp_uint(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { unsigned long x; Py_ssize_t i; unsigned char *q = (unsigned char *)p; - if (get_ulong(v, &x) < 0) + if (get_ulong(state, v, &x) < 0) return -1; i = f->size; if (i != SIZEOF_LONG) { unsigned long maxint = 1; maxint <<= (unsigned long)(i * 8); if (x >= maxint) - RANGE_ERROR(x, f, 1, maxint - 1); + RANGE_ERROR(state, x, f, 1, maxint - 1); } do { *q++ = (unsigned char)(x & 0xffUL); @@ -1132,10 +1143,10 @@ lp_uint(char *p, PyObject *v, const formatdef *f) } static int -lp_longlong(char *p, PyObject *v, const formatdef *f) +lp_longlong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { int res; - v = get_pylong(v); + v = get_pylong(state, v); if (v == NULL) return -1; res = _PyLong_AsByteArray((PyLongObject*)v, @@ -1148,10 +1159,10 @@ lp_longlong(char *p, PyObject *v, const formatdef *f) } static int -lp_ulonglong(char *p, PyObject *v, const formatdef *f) +lp_ulonglong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { int res; - v = get_pylong(v); + v = get_pylong(state, v); if (v == NULL) return -1; res = _PyLong_AsByteArray((PyLongObject*)v, @@ -1164,17 +1175,17 @@ lp_ulonglong(char *p, PyObject *v, const formatdef *f) } static int -lp_halffloat(char *p, PyObject *v, const formatdef *f) +lp_halffloat(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { - return pack_halffloat(p, v, 1); + return pack_halffloat(state, p, v, 1); } static int -lp_float(char *p, PyObject *v, const formatdef *f) +lp_float(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { double x = PyFloat_AsDouble(v); if (x == -1 && PyErr_Occurred()) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "required argument is not a float"); return -1; } @@ -1182,11 +1193,11 @@ lp_float(char *p, PyObject *v, const formatdef *f) } static int -lp_double(char *p, PyObject *v, const formatdef *f) +lp_double(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { double x = PyFloat_AsDouble(v); if (x == -1 && PyErr_Occurred()) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "required argument is not a float"); return -1; } @@ -1246,14 +1257,14 @@ whichtable(const char **pfmt) /* Get the table entry for a format code */ static const formatdef * -getentry(int c, const formatdef *f) +getentry(_structmodulestate *state, int c, const formatdef *f) { for (; f->format != '\0'; f++) { if (f->format == c) { return f; } } - PyErr_SetString(_structmodulestate_global->StructError, "bad char in struct format"); + PyErr_SetString(state->StructError, "bad char in struct format"); return NULL; } @@ -1295,9 +1306,11 @@ prepare_s(PyStructObject *self) Py_ssize_t size, len, num, itemsize; size_t ncodes; + _structmodulestate *state = get_struct_state_structinst(self); + fmt = PyBytes_AS_STRING(self->s_format); if (strlen(fmt) != (size_t)PyBytes_GET_SIZE(self->s_format)) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "embedded null character"); return -1; } @@ -1323,7 +1336,7 @@ prepare_s(PyStructObject *self) num = num*10 + (c - '0'); } if (c == '\0') { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "repeat count given without format specifier"); return -1; } @@ -1331,7 +1344,7 @@ prepare_s(PyStructObject *self) else num = 1; - e = getentry(c, f); + e = getentry(state, c, f); if (e == NULL) return -1; @@ -1361,14 +1374,14 @@ prepare_s(PyStructObject *self) self->s_size = size; self->s_len = len; - codes = PyMem_MALLOC((ncodes + 1) * sizeof(formatcode)); + codes = PyMem_Malloc((ncodes + 1) * sizeof(formatcode)); if (codes == NULL) { PyErr_NoMemory(); return -1; } /* Free any s_codes value left over from a previous initialization. */ if (self->s_codes != NULL) - PyMem_FREE(self->s_codes); + PyMem_Free(self->s_codes); self->s_codes = codes; s = fmt; @@ -1384,7 +1397,7 @@ prepare_s(PyStructObject *self) else num = 1; - e = getentry(c, f); + e = getentry(state, c, f); size = align(size, c, e); if (c == 's' || c == 'p') { @@ -1413,7 +1426,7 @@ prepare_s(PyStructObject *self) return 0; overflow: - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "total struct size too long"); return -1; } @@ -1430,8 +1443,7 @@ s_new(PyTypeObject *type, PyObject *args, PyObject *kwds) self = alloc_func(type, 0); if (self != NULL) { PyStructObject *s = (PyStructObject*)self; - Py_INCREF(Py_None); - s->s_format = Py_None; + s->s_format = Py_NewRef(Py_None); s->s_codes = NULL; s->s_size = -1; s->s_len = -1; @@ -1490,7 +1502,7 @@ s_dealloc(PyStructObject *s) if (s->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *)s); if (s->s_codes != NULL) { - PyMem_FREE(s->s_codes); + PyMem_Free(s->s_codes); } Py_XDECREF(s->s_format); freefunc free_func = PyType_GetSlot(Py_TYPE(s), Py_tp_free); @@ -1499,7 +1511,8 @@ s_dealloc(PyStructObject *s) } static PyObject * -s_unpack_internal(PyStructObject *soself, const char *startfrom) { +s_unpack_internal(PyStructObject *soself, const char *startfrom, + _structmodulestate *state) { formatcode *code; Py_ssize_t i = 0; PyObject *result = PyTuple_New(soself->s_len); @@ -1520,7 +1533,7 @@ s_unpack_internal(PyStructObject *soself, const char *startfrom) { n = code->size - 1; v = PyBytes_FromStringAndSize(res + 1, n); } else { - v = e->unpack(res, e); + v = e->unpack(state, res, e); } if (v == NULL) goto fail; @@ -1554,14 +1567,15 @@ static PyObject * Struct_unpack_impl(PyStructObject *self, Py_buffer *buffer) /*[clinic end generated code: output=873a24faf02e848a input=3113f8e7038b2f6c]*/ { + _structmodulestate *state = get_struct_state_structinst(self); assert(self->s_codes != NULL); if (buffer->len != self->s_size) { - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "unpack requires a buffer of %zd bytes", self->s_size); return NULL; } - return s_unpack_internal(self, buffer->buf); + return s_unpack_internal(self, buffer->buf, state); } /*[clinic input] @@ -1585,11 +1599,12 @@ Struct_unpack_from_impl(PyStructObject *self, Py_buffer *buffer, Py_ssize_t offset) /*[clinic end generated code: output=57fac875e0977316 input=cafd4851d473c894]*/ { + _structmodulestate *state = get_struct_state_structinst(self); assert(self->s_codes != NULL); if (offset < 0) { if (offset + self->s_size > 0) { - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "not enough data to unpack %zd bytes at offset %zd", self->s_size, offset); @@ -1597,7 +1612,7 @@ Struct_unpack_from_impl(PyStructObject *self, Py_buffer *buffer, } if (offset + buffer->len < 0) { - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "offset %zd out of range for %zd-byte buffer", offset, buffer->len); @@ -1607,7 +1622,7 @@ Struct_unpack_from_impl(PyStructObject *self, Py_buffer *buffer, } if ((buffer->len - offset) < self->s_size) { - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "unpack_from requires a buffer of at least %zu bytes for " "unpacking %zd bytes at offset %zd " "(actual buffer size is %zd)", @@ -1617,7 +1632,7 @@ Struct_unpack_from_impl(PyStructObject *self, Py_buffer *buffer, buffer->len); return NULL; } - return s_unpack_internal(self, (char*)buffer->buf + offset); + return s_unpack_internal(self, (char*)buffer->buf + offset, state); } @@ -1671,6 +1686,7 @@ static PyMethodDef unpackiter_methods[] = { static PyObject * unpackiter_iternext(unpackiterobject *self) { + _structmodulestate *state = get_struct_state_iterinst(self); PyObject *result; if (self->so == NULL) return NULL; @@ -1682,7 +1698,8 @@ unpackiter_iternext(unpackiterobject *self) } assert(self->index + self->so->s_size <= self->buf.len); result = s_unpack_internal(self->so, - (char*) self->buf.buf + self->index); + (char*) self->buf.buf + self->index, + state); self->index += self->so->s_size; return result; } @@ -1729,17 +1746,18 @@ static PyObject * Struct_iter_unpack(PyStructObject *self, PyObject *buffer) /*[clinic end generated code: output=172d83d0cd15dbab input=6d65b3f3107dbc99]*/ { + _structmodulestate *state = get_struct_state_structinst(self); unpackiterobject *iter; assert(self->s_codes != NULL); if (self->s_size == 0) { - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "cannot iteratively unpack with a struct of length 0"); return NULL; } - iter = (unpackiterobject *) PyType_GenericAlloc((PyTypeObject *)_structmodulestate_global->unpackiter_type, 0); + iter = (unpackiterobject *) PyType_GenericAlloc((PyTypeObject *)state->unpackiter_type, 0); if (iter == NULL) return NULL; @@ -1748,7 +1766,7 @@ Struct_iter_unpack(PyStructObject *self, PyObject *buffer) return NULL; } if (iter->buf.len % self->s_size != 0) { - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "iterative unpacking requires a buffer of " "a multiple of %zd bytes", self->s_size); @@ -1773,7 +1791,8 @@ Struct_iter_unpack(PyStructObject *self, PyObject *buffer) * */ static int -s_pack_internal(PyStructObject *soself, PyObject *const *args, int offset, char* buf) +s_pack_internal(PyStructObject *soself, PyObject *const *args, int offset, + char* buf, _structmodulestate *state) { formatcode *code; /* XXX(nnorwitz): why does i need to be a local? can we use @@ -1794,7 +1813,7 @@ s_pack_internal(PyStructObject *soself, PyObject *const *args, int offset, char* const void *p; isstring = PyBytes_Check(v); if (!isstring && !PyByteArray_Check(v)) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "argument for 's' must be a bytes object"); return -1; } @@ -1816,7 +1835,7 @@ s_pack_internal(PyStructObject *soself, PyObject *const *args, int offset, char* const void *p; isstring = PyBytes_Check(v); if (!isstring && !PyByteArray_Check(v)) { - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "argument for 'p' must be a bytes object"); return -1; } @@ -1836,9 +1855,9 @@ s_pack_internal(PyStructObject *soself, PyObject *const *args, int offset, char* n = 255; *res = Py_SAFE_DOWNCAST(n, Py_ssize_t, unsigned char); } else { - if (e->pack(res, v, e) < 0) { + if (e->pack(state, res, v, e) < 0) { if (PyLong_Check(v) && PyErr_ExceptionMatches(PyExc_OverflowError)) - PyErr_SetString(_structmodulestate_global->StructError, + PyErr_SetString(state->StructError, "int too large to convert"); return -1; } @@ -1864,14 +1883,15 @@ s_pack(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { char *buf; PyStructObject *soself; + _structmodulestate *state = get_struct_state_structinst(self); /* Validate arguments. */ soself = (PyStructObject *)self; - assert(PyStruct_Check(self)); + assert(PyStruct_Check(self, state)); assert(soself->s_codes != NULL); if (nargs != soself->s_len) { - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "pack expected %zd items for packing (got %zd)", soself->s_len, nargs); return NULL; } @@ -1886,7 +1906,7 @@ s_pack(PyObject *self, PyObject *const *args, Py_ssize_t nargs) } /* Call the guts */ - if ( s_pack_internal(soself, args, 0, buf) != 0 ) { + if ( s_pack_internal(soself, args, 0, buf, state) != 0 ) { _PyBytesWriter_Dealloc(&writer); return NULL; } @@ -1908,23 +1928,24 @@ s_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs) PyStructObject *soself; Py_buffer buffer; Py_ssize_t offset; + _structmodulestate *state = get_struct_state_structinst(self); /* Validate arguments. +1 is for the first arg as buffer. */ soself = (PyStructObject *)self; - assert(PyStruct_Check(self)); + assert(PyStruct_Check(self, state)); assert(soself->s_codes != NULL); if (nargs != (soself->s_len + 2)) { if (nargs == 0) { - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "pack_into expected buffer argument"); } else if (nargs == 1) { - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "pack_into expected offset argument"); } else { - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "pack_into expected %zd items for packing (got %zd)", soself->s_len, (nargs - 2)); } @@ -1947,7 +1968,7 @@ s_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs) if (offset < 0) { /* Check that negative offset is low enough to fit data */ if (offset + soself->s_size > 0) { - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "no space to pack %zd bytes at offset %zd", soself->s_size, offset); @@ -1957,7 +1978,7 @@ s_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs) /* Check that negative offset is not crossing buffer boundary */ if (offset + buffer.len < 0) { - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "offset %zd out of range for %zd-byte buffer", offset, buffer.len); @@ -1973,7 +1994,7 @@ s_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs) assert(offset >= 0); assert(soself->s_size >= 0); - PyErr_Format(_structmodulestate_global->StructError, + PyErr_Format(state->StructError, "pack_into requires a buffer of at least %zu bytes for " "packing %zd bytes at offset %zd " "(actual buffer size is %zd)", @@ -1986,7 +2007,7 @@ s_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs) } /* Call the guts */ - if (s_pack_internal(soself, args, 2, (char*)buffer.buf + offset) != 0) { + if (s_pack_internal(soself, args, 2, (char*)buffer.buf + offset, state) != 0) { PyBuffer_Release(&buffer); return NULL; } @@ -2080,12 +2101,12 @@ static PyType_Spec PyStructType_spec = { /* ---- Standalone functions ---- */ #define MAXCACHE 100 -static PyObject *cache = NULL; static int -cache_struct_converter(PyObject *fmt, PyStructObject **ptr) +cache_struct_converter(PyObject *module, PyObject *fmt, PyStructObject **ptr) { PyObject * s_object; + _structmodulestate *state = get_struct_state(module); if (fmt == NULL) { Py_DECREF(*ptr); @@ -2093,13 +2114,13 @@ cache_struct_converter(PyObject *fmt, PyStructObject **ptr) return 1; } - if (cache == NULL) { - cache = PyDict_New(); - if (cache == NULL) + if (state->cache == NULL) { + state->cache = PyDict_New(); + if (state->cache == NULL) return 0; } - s_object = PyDict_GetItemWithError(cache, fmt); + s_object = PyDict_GetItemWithError(state->cache, fmt); if (s_object != NULL) { Py_INCREF(s_object); *ptr = (PyStructObject *)s_object; @@ -2109,12 +2130,12 @@ cache_struct_converter(PyObject *fmt, PyStructObject **ptr) return 0; } - s_object = PyObject_CallOneArg(_structmodulestate_global->PyStructType, fmt); + s_object = PyObject_CallOneArg(state->PyStructType, fmt); if (s_object != NULL) { - if (PyDict_GET_SIZE(cache) >= MAXCACHE) - PyDict_Clear(cache); + if (PyDict_GET_SIZE(state->cache) >= MAXCACHE) + PyDict_Clear(state->cache); /* Attempt to cache the result */ - if (PyDict_SetItem(cache, fmt, s_object) == -1) + if (PyDict_SetItem(state->cache, fmt, s_object) == -1) PyErr_Clear(); *ptr = (PyStructObject *)s_object; return Py_CLEANUP_SUPPORTED; @@ -2132,7 +2153,7 @@ static PyObject * _clearcache_impl(PyObject *module) /*[clinic end generated code: output=ce4fb8a7bf7cb523 input=463eaae04bab3211]*/ { - Py_CLEAR(cache); + Py_CLEAR(get_struct_state(module)->cache); Py_RETURN_NONE; } @@ -2160,7 +2181,7 @@ Return a bytes object containing the values v1, v2, ... packed according\n\ to the format string. See help(struct) for more on format strings."); static PyObject * -pack(PyObject *self, PyObject *const *args, Py_ssize_t nargs) +pack(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *s_object = NULL; PyObject *format, *result; @@ -2171,7 +2192,7 @@ pack(PyObject *self, PyObject *const *args, Py_ssize_t nargs) } format = args[0]; - if (!cache_struct_converter(format, (PyStructObject **)&s_object)) { + if (!cache_struct_converter(module, format, (PyStructObject **)&s_object)) { return NULL; } result = s_pack(s_object, args + 1, nargs - 1); @@ -2188,7 +2209,7 @@ that the offset is a required argument. See help(struct) for more\n\ on format strings."); static PyObject * -pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs) +pack_into(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *s_object = NULL; PyObject *format, *result; @@ -2199,7 +2220,7 @@ pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs) } format = args[0]; - if (!cache_struct_converter(format, (PyStructObject **)&s_object)) { + if (!cache_struct_converter(module, format, (PyStructObject **)&s_object)) { return NULL; } result = s_pack_into(s_object, args + 1, nargs - 1); @@ -2322,8 +2343,9 @@ The variable struct.error is an exception raised on errors.\n"); static int _structmodule_traverse(PyObject *module, visitproc visit, void *arg) { - _structmodulestate *state = (_structmodulestate *)PyModule_GetState(module); + _structmodulestate *state = get_struct_state(module); if (state) { + Py_VISIT(state->cache); Py_VISIT(state->PyStructType); Py_VISIT(state->unpackiter_type); Py_VISIT(state->StructError); @@ -2334,8 +2356,9 @@ _structmodule_traverse(PyObject *module, visitproc visit, void *arg) static int _structmodule_clear(PyObject *module) { - _structmodulestate *state = (_structmodulestate *)PyModule_GetState(module); + _structmodulestate *state = get_struct_state(module); if (state) { + Py_CLEAR(state->cache); Py_CLEAR(state->PyStructType); Py_CLEAR(state->unpackiter_type); Py_CLEAR(state->StructError); @@ -2349,40 +2372,25 @@ _structmodule_free(void *module) _structmodule_clear((PyObject *)module); } -static struct PyModuleDef _structmodule = { - PyModuleDef_HEAD_INIT, - "_struct", - module_doc, - sizeof(_structmodulestate), - module_functions, - NULL, - _structmodule_traverse, - _structmodule_clear, - _structmodule_free, -}; - -PyMODINIT_FUNC -PyInit__struct(void) +static int +_structmodule_exec(PyObject *m) { - PyObject *m; + _structmodulestate *state = get_struct_state(m); - m = PyModule_Create(&_structmodule); - if (m == NULL) - return NULL; - - PyObject *PyStructType = PyType_FromSpec(&PyStructType_spec); - if (PyStructType == NULL) { - return NULL; + state->PyStructType = PyType_FromModuleAndSpec( + m, &PyStructType_spec, NULL); + if (state->PyStructType == NULL) { + return -1; + } + if (PyModule_AddType(m, (PyTypeObject *)state->PyStructType) < 0) { + return -1; } - Py_INCREF(PyStructType); - PyModule_AddObject(m, "Struct", PyStructType); - get_struct_state(m)->PyStructType = PyStructType; - PyObject *unpackiter_type = PyType_FromSpec(&unpackiter_type_spec); - if (unpackiter_type == NULL) { - return NULL; + state->unpackiter_type = PyType_FromModuleAndSpec( + m, &unpackiter_type_spec, NULL); + if (state->unpackiter_type == NULL) { + return -1; } - get_struct_state(m)->unpackiter_type = unpackiter_type; /* Check endian and swap in faster functions */ { @@ -2427,12 +2435,36 @@ PyInit__struct(void) } /* Add some symbolic constants to the module */ - PyObject *StructError = PyErr_NewException("struct.error", NULL, NULL); - if (StructError == NULL) - return NULL; - Py_INCREF(StructError); - PyModule_AddObject(m, "error", StructError); - get_struct_state(m)->StructError = StructError; + state->StructError = PyErr_NewException("struct.error", NULL, NULL); + if (state->StructError == NULL) { + return -1; + } + if (PyModule_AddObjectRef(m, "error", state->StructError) < 0) { + return -1; + } + + return 0; +} - return m; +static PyModuleDef_Slot _structmodule_slots[] = { + {Py_mod_exec, _structmodule_exec}, + {0, NULL} +}; + +static struct PyModuleDef _structmodule = { + PyModuleDef_HEAD_INIT, + .m_name = "_struct", + .m_doc = module_doc, + .m_size = sizeof(_structmodulestate), + .m_methods = module_functions, + .m_slots = _structmodule_slots, + .m_traverse = _structmodule_traverse, + .m_clear = _structmodule_clear, + .m_free = _structmodule_free, +}; + +PyMODINIT_FUNC +PyInit__struct(void) +{ + return PyModuleDef_Init(&_structmodule); } diff --git a/contrib/tools/python3/src/Modules/_threadmodule.c b/contrib/tools/python3/src/Modules/_threadmodule.c index a370352238..813d7ec232 100644 --- a/contrib/tools/python3/src/Modules/_threadmodule.c +++ b/contrib/tools/python3/src/Modules/_threadmodule.c @@ -3,17 +3,45 @@ /* Interface to Sjoerd's portable C thread library */ #include "Python.h" -#include "pycore_pylifecycle.h" #include "pycore_interp.h" // _PyInterpreterState.num_threads +#include "pycore_moduleobject.h" // _PyModule_GetState() +#include "pycore_pylifecycle.h" #include "pycore_pystate.h" // _PyThreadState_Init() #include <stddef.h> // offsetof() +#include "structmember.h" // PyMemberDef + +#ifdef HAVE_SIGNAL_H +# include <signal.h> // SIGINT +#endif -static PyObject *ThreadError; -static PyObject *str_dict; +// ThreadError is just an alias to PyExc_RuntimeError +#define ThreadError PyExc_RuntimeError + +_Py_IDENTIFIER(__dict__); _Py_IDENTIFIER(stderr); _Py_IDENTIFIER(flush); + +// Forward declarations +static struct PyModuleDef thread_module; + + +typedef struct { + PyTypeObject *lock_type; + PyTypeObject *local_type; + PyTypeObject *local_dummy_type; +} thread_module_state; + +static inline thread_module_state* +get_thread_state(PyObject *module) +{ + void *state = _PyModule_GetState(module); + assert(state != NULL); + return (thread_module_state *)state; +} + + /* Lock objects */ typedef struct { @@ -23,18 +51,28 @@ typedef struct { char locked; /* for sanity checking */ } lockobject; +static int +lock_traverse(lockobject *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + return 0; +} + static void lock_dealloc(lockobject *self) { - if (self->in_weakreflist != NULL) + if (self->in_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject *) self); + } if (self->lock_lock != NULL) { /* Unlock the lock so it's safe to free it */ if (self->locked) PyThread_release_lock(self->lock_lock); PyThread_free_lock(self->lock_lock); } - PyObject_Del(self); + PyTypeObject *tp = Py_TYPE(self); + tp->tp_free((PyObject*)self); + Py_DECREF(tp); } /* Helper to acquire an interruptible lock with a timeout. If the lock acquire @@ -48,12 +86,13 @@ acquire_timed(PyThread_type_lock lock, _PyTime_t timeout) { PyLockStatus r; _PyTime_t endtime = 0; - _PyTime_t microseconds; - if (timeout > 0) + if (timeout > 0) { endtime = _PyTime_GetMonotonicClock() + timeout; + } do { + _PyTime_t microseconds; microseconds = _PyTime_AsMicroseconds(timeout, _PyTime_ROUND_CEILING); /* first a simple non-blocking try without releasing the GIL */ @@ -138,12 +177,10 @@ static PyObject * lock_PyThread_acquire_lock(lockobject *self, PyObject *args, PyObject *kwds) { _PyTime_t timeout; - PyLockStatus r; - if (lock_acquire_parse_args(args, kwds, &timeout) < 0) return NULL; - r = acquire_timed(self->lock_lock, timeout); + PyLockStatus r = acquire_timed(self->lock_lock, timeout); if (r == PY_LOCK_INTR) { return NULL; } @@ -245,36 +282,39 @@ static PyMethodDef lock_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject Locktype = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "_thread.lock", /*tp_name*/ - sizeof(lockobject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)lock_dealloc, /*tp_dealloc*/ - 0, /*tp_vectorcall_offset*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_as_async*/ - (reprfunc)lock_repr, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - offsetof(lockobject, in_weakreflist), /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - lock_methods, /*tp_methods*/ +PyDoc_STRVAR(lock_doc, +"A lock object is a synchronization primitive. To create a lock,\n\ +call threading.Lock(). Methods are:\n\ +\n\ +acquire() -- lock the lock, possibly blocking until it can be obtained\n\ +release() -- unlock of the lock\n\ +locked() -- test whether the lock is currently locked\n\ +\n\ +A lock is not owned by the thread that locked it; another thread may\n\ +unlock it. A thread attempting to lock a lock that it has already locked\n\ +will block until another thread unlocks it. Deadlocks may ensue."); + +static PyMemberDef lock_type_members[] = { + {"__weaklistoffset__", T_PYSSIZET, offsetof(lockobject, in_weakreflist), READONLY}, + {NULL}, +}; + +static PyType_Slot lock_type_slots[] = { + {Py_tp_dealloc, (destructor)lock_dealloc}, + {Py_tp_repr, (reprfunc)lock_repr}, + {Py_tp_doc, (void *)lock_doc}, + {Py_tp_methods, lock_methods}, + {Py_tp_traverse, lock_traverse}, + {Py_tp_members, lock_type_members}, + {0, 0} +}; + +static PyType_Spec lock_type_spec = { + .name = "_thread.lock", + .basicsize = sizeof(lockobject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE), + .slots = lock_type_slots, }; /* Recursive lock objects */ @@ -287,6 +327,14 @@ typedef struct { PyObject *in_weakreflist; } rlockobject; +static int +rlock_traverse(rlockobject *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + return 0; +} + + static void rlock_dealloc(rlockobject *self) { @@ -301,7 +349,9 @@ rlock_dealloc(rlockobject *self) PyThread_free_lock(self->rlock_lock); } - Py_TYPE(self)->tp_free(self); + PyTypeObject *tp = Py_TYPE(self); + tp->tp_free(self); + Py_DECREF(tp); } static PyObject * @@ -525,58 +575,45 @@ static PyMethodDef rlock_methods[] = { }; -static PyTypeObject RLocktype = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "_thread.RLock", /*tp_name*/ - sizeof(rlockobject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)rlock_dealloc, /*tp_dealloc*/ - 0, /*tp_vectorcall_offset*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_as_async*/ - (reprfunc)rlock_repr, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - offsetof(rlockobject, in_weakreflist), /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - rlock_methods, /*tp_methods*/ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - rlock_new /* tp_new */ +static PyMemberDef rlock_type_members[] = { + {"__weaklistoffset__", T_PYSSIZET, offsetof(rlockobject, in_weakreflist), READONLY}, + {NULL}, +}; + +static PyType_Slot rlock_type_slots[] = { + {Py_tp_dealloc, (destructor)rlock_dealloc}, + {Py_tp_repr, (reprfunc)rlock_repr}, + {Py_tp_methods, rlock_methods}, + {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_new, rlock_new}, + {Py_tp_members, rlock_type_members}, + {Py_tp_traverse, rlock_traverse}, + {0, 0}, +}; + +static PyType_Spec rlock_type_spec = { + .name = "_thread.RLock", + .basicsize = sizeof(rlockobject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), + .slots = rlock_type_slots, }; static lockobject * -newlockobject(void) +newlockobject(PyObject *module) { - lockobject *self; - self = PyObject_New(lockobject, &Locktype); - if (self == NULL) + thread_module_state *state = get_thread_state(module); + + PyTypeObject *type = state->lock_type; + lockobject *self = (lockobject *)type->tp_alloc(type, 0); + if (self == NULL) { return NULL; + } + self->lock_lock = PyThread_allocate_lock(); self->locked = 0; self->in_weakreflist = NULL; + if (self->lock_lock == NULL) { Py_DECREF(self); PyErr_SetString(ThreadError, "can't allocate lock"); @@ -637,35 +674,29 @@ localdummy_dealloc(localdummyobject *self) { if (self->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) self); - Py_TYPE(self)->tp_free((PyObject*)self); + PyTypeObject *tp = Py_TYPE(self); + tp->tp_free((PyObject*)self); + Py_DECREF(tp); } -static PyTypeObject localdummytype = { - PyVarObject_HEAD_INIT(NULL, 0) - /* tp_name */ "_thread._localdummy", - /* tp_basicsize */ sizeof(localdummyobject), - /* tp_itemsize */ 0, - /* tp_dealloc */ (destructor)localdummy_dealloc, - /* tp_vectorcall_offset */ 0, - /* tp_getattr */ 0, - /* tp_setattr */ 0, - /* tp_as_async */ 0, - /* tp_repr */ 0, - /* tp_as_number */ 0, - /* tp_as_sequence */ 0, - /* tp_as_mapping */ 0, - /* tp_hash */ 0, - /* tp_call */ 0, - /* tp_str */ 0, - /* tp_getattro */ 0, - /* tp_setattro */ 0, - /* tp_as_buffer */ 0, - /* tp_flags */ Py_TPFLAGS_DEFAULT, - /* tp_doc */ "Thread-local dummy", - /* tp_traverse */ 0, - /* tp_clear */ 0, - /* tp_richcompare */ 0, - /* tp_weaklistoffset */ offsetof(localdummyobject, weakreflist) +static PyMemberDef local_dummy_type_members[] = { + {"__weaklistoffset__", T_PYSSIZET, offsetof(localdummyobject, weakreflist), READONLY}, + {NULL}, +}; + +static PyType_Slot local_dummy_type_slots[] = { + {Py_tp_dealloc, (destructor)localdummy_dealloc}, + {Py_tp_doc, "Thread-local dummy"}, + {Py_tp_members, local_dummy_type_members}, + {0, 0} +}; + +static PyType_Spec local_dummy_type_spec = { + .name = "_thread._localdummy", + .basicsize = sizeof(localdummyobject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = local_dummy_type_slots, }; @@ -682,19 +713,19 @@ typedef struct { } localobject; /* Forward declaration */ -static PyObject *_ldict(localobject *self); +static PyObject *_ldict(localobject *self, thread_module_state *state); static PyObject *_localdummy_destroyed(PyObject *meth_self, PyObject *dummyweakref); /* Create and register the dummy for the current thread. Returns a borrowed reference of the corresponding local dict */ static PyObject * -_local_create_dummy(localobject *self) +_local_create_dummy(localobject *self, thread_module_state *state) { - PyObject *tdict, *ldict = NULL, *wr = NULL; + PyObject *ldict = NULL, *wr = NULL; localdummyobject *dummy = NULL; - int r; + PyTypeObject *type = state->local_dummy_type; - tdict = PyThreadState_GetDict(); + PyObject *tdict = PyThreadState_GetDict(); if (tdict == NULL) { PyErr_SetString(PyExc_SystemError, "Couldn't get thread-state dictionary"); @@ -702,25 +733,30 @@ _local_create_dummy(localobject *self) } ldict = PyDict_New(); - if (ldict == NULL) + if (ldict == NULL) { goto err; - dummy = (localdummyobject *) localdummytype.tp_alloc(&localdummytype, 0); - if (dummy == NULL) + } + dummy = (localdummyobject *) type->tp_alloc(type, 0); + if (dummy == NULL) { goto err; + } dummy->localdict = ldict; wr = PyWeakref_NewRef((PyObject *) dummy, self->wr_callback); - if (wr == NULL) + if (wr == NULL) { goto err; + } /* As a side-effect, this will cache the weakref's hash before the dummy gets deleted */ - r = PyDict_SetItem(self->dummies, wr, ldict); - if (r < 0) + int r = PyDict_SetItem(self->dummies, wr, ldict); + if (r < 0) { goto err; + } Py_CLEAR(wr); r = PyDict_SetItem(tdict, self->key, (PyObject *) dummy); - if (r < 0) + if (r < 0) { goto err; + } Py_CLEAR(dummy); Py_DECREF(ldict); @@ -736,8 +772,6 @@ err: static PyObject * local_new(PyTypeObject *type, PyObject *args, PyObject *kw) { - localobject *self; - PyObject *wr; static PyMethodDef wr_callback_def = { "_localdummy_destroyed", (PyCFunction) _localdummy_destroyed, METH_O }; @@ -749,42 +783,48 @@ local_new(PyTypeObject *type, PyObject *args, PyObject *kw) if (rc == 0 && kw != NULL) rc = PyObject_IsTrue(kw); if (rc != 0) { - if (rc > 0) + if (rc > 0) { PyErr_SetString(PyExc_TypeError, "Initialization arguments are not supported"); + } return NULL; } } - self = (localobject *)type->tp_alloc(type, 0); - if (self == NULL) + PyObject *module = _PyType_GetModuleByDef(type, &thread_module); + thread_module_state *state = get_thread_state(module); + + localobject *self = (localobject *)type->tp_alloc(type, 0); + if (self == NULL) { return NULL; + } - Py_XINCREF(args); - self->args = args; - Py_XINCREF(kw); - self->kw = kw; + self->args = Py_XNewRef(args); + self->kw = Py_XNewRef(kw); self->key = PyUnicode_FromFormat("thread.local.%p", self); - if (self->key == NULL) + if (self->key == NULL) { goto err; + } self->dummies = PyDict_New(); - if (self->dummies == NULL) + if (self->dummies == NULL) { goto err; + } /* We use a weak reference to self in the callback closure in order to avoid spurious reference cycles */ - wr = PyWeakref_NewRef((PyObject *) self, NULL); - if (wr == NULL) + PyObject *wr = PyWeakref_NewRef((PyObject *) self, NULL); + if (wr == NULL) { goto err; + } self->wr_callback = PyCFunction_NewEx(&wr_callback_def, wr, NULL); Py_DECREF(wr); - if (self->wr_callback == NULL) + if (self->wr_callback == NULL) { goto err; - - if (_local_create_dummy(self) == NULL) + } + if (_local_create_dummy(self, state) == NULL) { goto err; - + } return (PyObject *)self; err: @@ -795,6 +835,7 @@ local_new(PyTypeObject *type, PyObject *args, PyObject *kw) static int local_traverse(localobject *self, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(self)); Py_VISIT(self->args); Py_VISIT(self->kw); Py_VISIT(self->dummies); @@ -804,23 +845,26 @@ local_traverse(localobject *self, visitproc visit, void *arg) static int local_clear(localobject *self) { - PyThreadState *tstate; Py_CLEAR(self->args); Py_CLEAR(self->kw); Py_CLEAR(self->dummies); Py_CLEAR(self->wr_callback); /* Remove all strong references to dummies from the thread states */ - if (self->key - && (tstate = PyThreadState_Get()) - && tstate->interp) { - for(tstate = PyInterpreterState_ThreadHead(tstate->interp); - tstate; - tstate = PyThreadState_Next(tstate)) - if (tstate->dict && PyDict_GetItem(tstate->dict, self->key)) { - if (PyDict_DelItem(tstate->dict, self->key)) { - PyErr_Clear(); - } + if (self->key) { + PyInterpreterState *interp = _PyInterpreterState_GET(); + PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); + for(; tstate; tstate = PyThreadState_Next(tstate)) { + if (tstate->dict == NULL) { + continue; + } + PyObject *v = _PyDict_Pop(tstate->dict, self->key, Py_None); + if (v != NULL) { + Py_DECREF(v); + } + else { + PyErr_Clear(); } + } } return 0; } @@ -830,35 +874,38 @@ local_dealloc(localobject *self) { /* Weakrefs must be invalidated right now, otherwise they can be used from code called below, which is very dangerous since Py_REFCNT(self) == 0 */ - if (self->weakreflist != NULL) + if (self->weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject *) self); + } PyObject_GC_UnTrack(self); local_clear(self); Py_XDECREF(self->key); - Py_TYPE(self)->tp_free((PyObject*)self); + + PyTypeObject *tp = Py_TYPE(self); + tp->tp_free((PyObject*)self); + Py_DECREF(tp); } /* Returns a borrowed reference to the local dict, creating it if necessary */ static PyObject * -_ldict(localobject *self) +_ldict(localobject *self, thread_module_state *state) { - PyObject *tdict, *ldict, *dummy; - - tdict = PyThreadState_GetDict(); + PyObject *tdict = PyThreadState_GetDict(); if (tdict == NULL) { PyErr_SetString(PyExc_SystemError, "Couldn't get thread-state dictionary"); return NULL; } - dummy = PyDict_GetItemWithError(tdict, self->key); + PyObject *ldict; + PyObject *dummy = PyDict_GetItemWithError(tdict, self->key); if (dummy == NULL) { if (PyErr_Occurred()) { return NULL; } - ldict = _local_create_dummy(self); + ldict = _local_create_dummy(self, state); if (ldict == NULL) return NULL; @@ -873,7 +920,7 @@ _ldict(localobject *self) } } else { - assert(Py_IS_TYPE(dummy, &localdummytype)); + assert(Py_IS_TYPE(dummy, state->local_dummy_type)); ldict = ((localdummyobject *) dummy)->localdict; } @@ -883,104 +930,98 @@ _ldict(localobject *self) static int local_setattro(localobject *self, PyObject *name, PyObject *v) { - PyObject *ldict; - int r; + PyObject *module = _PyType_GetModuleByDef(Py_TYPE(self), &thread_module); + thread_module_state *state = get_thread_state(module); - ldict = _ldict(self); - if (ldict == NULL) + PyObject *ldict = _ldict(self, state); + if (ldict == NULL) { return -1; + } - r = PyObject_RichCompareBool(name, str_dict, Py_EQ); + PyObject *str_dict = _PyUnicode_FromId(&PyId___dict__); // borrowed ref + if (str_dict == NULL) { + return -1; + } + + int r = PyObject_RichCompareBool(name, str_dict, Py_EQ); + if (r == -1) { + return -1; + } if (r == 1) { PyErr_Format(PyExc_AttributeError, "'%.50s' object attribute '%U' is read-only", Py_TYPE(self)->tp_name, name); return -1; } - if (r == -1) - return -1; return _PyObject_GenericSetAttrWithDict((PyObject *)self, name, v, ldict); } static PyObject *local_getattro(localobject *, PyObject *); -static PyTypeObject localtype = { - PyVarObject_HEAD_INIT(NULL, 0) - /* tp_name */ "_thread._local", - /* tp_basicsize */ sizeof(localobject), - /* tp_itemsize */ 0, - /* tp_dealloc */ (destructor)local_dealloc, - /* tp_vectorcall_offset */ 0, - /* tp_getattr */ 0, - /* tp_setattr */ 0, - /* tp_as_async */ 0, - /* tp_repr */ 0, - /* tp_as_number */ 0, - /* tp_as_sequence */ 0, - /* tp_as_mapping */ 0, - /* tp_hash */ 0, - /* tp_call */ 0, - /* tp_str */ 0, - /* tp_getattro */ (getattrofunc)local_getattro, - /* tp_setattro */ (setattrofunc)local_setattro, - /* tp_as_buffer */ 0, - /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE - | Py_TPFLAGS_HAVE_GC, - /* tp_doc */ "Thread-local data", - /* tp_traverse */ (traverseproc)local_traverse, - /* tp_clear */ (inquiry)local_clear, - /* tp_richcompare */ 0, - /* tp_weaklistoffset */ offsetof(localobject, weakreflist), - /* tp_iter */ 0, - /* tp_iternext */ 0, - /* tp_methods */ 0, - /* tp_members */ 0, - /* tp_getset */ 0, - /* tp_base */ 0, - /* tp_dict */ 0, /* internal use */ - /* tp_descr_get */ 0, - /* tp_descr_set */ 0, - /* tp_dictoffset */ 0, - /* tp_init */ 0, - /* tp_alloc */ 0, - /* tp_new */ local_new, - /* tp_free */ 0, /* Low-level free-mem routine */ - /* tp_is_gc */ 0, /* For PyObject_IS_GC */ +static PyMemberDef local_type_members[] = { + {"__weaklistoffset__", T_PYSSIZET, offsetof(localobject, weakreflist), READONLY}, + {NULL}, +}; + +static PyType_Slot local_type_slots[] = { + {Py_tp_dealloc, (destructor)local_dealloc}, + {Py_tp_getattro, (getattrofunc)local_getattro}, + {Py_tp_setattro, (setattrofunc)local_setattro}, + {Py_tp_doc, "Thread-local data"}, + {Py_tp_traverse, (traverseproc)local_traverse}, + {Py_tp_clear, (inquiry)local_clear}, + {Py_tp_new, local_new}, + {Py_tp_members, local_type_members}, + {0, 0} +}; + +static PyType_Spec local_type_spec = { + .name = "_thread._local", + .basicsize = sizeof(localobject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = local_type_slots, }; static PyObject * local_getattro(localobject *self, PyObject *name) { - PyObject *ldict, *value; - int r; + PyObject *module = _PyType_GetModuleByDef(Py_TYPE(self), &thread_module); + thread_module_state *state = get_thread_state(module); - ldict = _ldict(self); + PyObject *ldict = _ldict(self, state); if (ldict == NULL) return NULL; - r = PyObject_RichCompareBool(name, str_dict, Py_EQ); + PyObject *str_dict = _PyUnicode_FromId(&PyId___dict__); // borrowed ref + if (str_dict == NULL) { + return NULL; + } + + int r = PyObject_RichCompareBool(name, str_dict, Py_EQ); if (r == 1) { - Py_INCREF(ldict); - return ldict; + return Py_NewRef(ldict); } - if (r == -1) + if (r == -1) { return NULL; + } - if (!Py_IS_TYPE(self, &localtype)) + if (!Py_IS_TYPE(self, state->local_type)) { /* use generic lookup for subtypes */ - return _PyObject_GenericGetAttrWithDict( - (PyObject *)self, name, ldict, 0); + return _PyObject_GenericGetAttrWithDict((PyObject *)self, name, + ldict, 0); + } /* Optimization: just look in dict ourselves */ - value = PyDict_GetItemWithError(ldict, name); + PyObject *value = PyDict_GetItemWithError(ldict, name); if (value != NULL) { - Py_INCREF(value); - return value; + return Py_NewRef(value); } - else if (PyErr_Occurred()) { + if (PyErr_Occurred()) { return NULL; } + /* Fall back on generic to get __class__ and __dict__ */ return _PyObject_GenericGetAttrWithDict( (PyObject *)self, name, ldict, 0); @@ -990,17 +1031,15 @@ local_getattro(localobject *self, PyObject *name) static PyObject * _localdummy_destroyed(PyObject *localweakref, PyObject *dummyweakref) { - PyObject *obj; - localobject *self; assert(PyWeakref_CheckRef(localweakref)); - obj = PyWeakref_GET_OBJECT(localweakref); - if (obj == Py_None) + PyObject *obj = PyWeakref_GET_OBJECT(localweakref); + if (obj == Py_None) { Py_RETURN_NONE; - Py_INCREF(obj); - assert(PyObject_TypeCheck(obj, &localtype)); + } + /* If the thread-local object is still alive and not being cleared, remove the corresponding local dict */ - self = (localobject *) obj; + localobject *self = (localobject *)Py_NewRef(obj); if (self->dummies != NULL) { PyObject *ldict; ldict = PyDict_GetItemWithError(self->dummies, dummyweakref); @@ -1020,24 +1059,35 @@ struct bootstate { PyInterpreterState *interp; PyObject *func; PyObject *args; - PyObject *keyw; + PyObject *kwargs; PyThreadState *tstate; _PyRuntimeState *runtime; }; + +static void +thread_bootstate_free(struct bootstate *boot) +{ + Py_DECREF(boot->func); + Py_DECREF(boot->args); + Py_XDECREF(boot->kwargs); + PyMem_Free(boot); +} + + static void -t_bootstrap(void *boot_raw) +thread_run(void *boot_raw) { struct bootstate *boot = (struct bootstate *) boot_raw; PyThreadState *tstate; - PyObject *res; tstate = boot->tstate; tstate->thread_id = PyThread_get_thread_ident(); _PyThreadState_Init(tstate); PyEval_AcquireThread(tstate); tstate->interp->num_threads++; - res = PyObject_Call(boot->func, boot->args, boot->keyw); + + PyObject *res = PyObject_Call(boot->func, boot->args, boot->kwargs); if (res == NULL) { if (PyErr_ExceptionMatches(PyExc_SystemExit)) /* SystemExit is ignored silently */ @@ -1049,10 +1099,8 @@ t_bootstrap(void *boot_raw) else { Py_DECREF(res); } - Py_DECREF(boot->func); - Py_DECREF(boot->args); - Py_XDECREF(boot->keyw); - PyMem_DEL(boot_raw); + + thread_bootstate_free(boot); tstate->interp->num_threads--; PyThreadState_Clear(tstate); _PyThreadState_DeleteCurrent(tstate); @@ -1066,12 +1114,10 @@ static PyObject * thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs) { _PyRuntimeState *runtime = &_PyRuntime; - PyObject *func, *args, *keyw = NULL; - struct bootstate *boot; - unsigned long ident; + PyObject *func, *args, *kwargs = NULL; if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3, - &func, &args, &keyw)) + &func, &args, &kwargs)) return NULL; if (!PyCallable_Check(func)) { PyErr_SetString(PyExc_TypeError, @@ -1083,7 +1129,7 @@ thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs) "2nd arg must be a tuple"); return NULL; } - if (keyw != NULL && !PyDict_Check(keyw)) { + if (kwargs != NULL && !PyDict_Check(kwargs)) { PyErr_SetString(PyExc_TypeError, "optional 3rd arg must be a dictionary"); return NULL; @@ -1096,31 +1142,26 @@ thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs) return NULL; } - boot = PyMem_NEW(struct bootstate, 1); - if (boot == NULL) + struct bootstate *boot = PyMem_NEW(struct bootstate, 1); + if (boot == NULL) { return PyErr_NoMemory(); + } boot->interp = _PyInterpreterState_GET(); - boot->func = func; - boot->args = args; - boot->keyw = keyw; boot->tstate = _PyThreadState_Prealloc(boot->interp); - boot->runtime = runtime; if (boot->tstate == NULL) { - PyMem_DEL(boot); + PyMem_Free(boot); return PyErr_NoMemory(); } - Py_INCREF(func); - Py_INCREF(args); - Py_XINCREF(keyw); + boot->runtime = runtime; + boot->func = Py_NewRef(func); + boot->args = Py_NewRef(args); + boot->kwargs = Py_XNewRef(kwargs); - ident = PyThread_start_new_thread(t_bootstrap, (void*) boot); + unsigned long ident = PyThread_start_new_thread(thread_run, (void*) boot); if (ident == PYTHREAD_INVALID_THREAD_ID) { PyErr_SetString(ThreadError, "can't start new thread"); - Py_DECREF(func); - Py_DECREF(args); - Py_XDECREF(keyw); PyThreadState_Clear(boot->tstate); - PyMem_DEL(boot); + thread_bootstate_free(boot); return NULL; } return PyLong_FromUnsignedLong(ident); @@ -1152,25 +1193,37 @@ This is synonymous to ``raise SystemExit''. It will cause the current\n\ thread to exit silently unless the exception is caught."); static PyObject * -thread_PyThread_interrupt_main(PyObject * self, PyObject *Py_UNUSED(ignored)) +thread_PyThread_interrupt_main(PyObject *self, PyObject *args) { - PyErr_SetInterrupt(); + int signum = SIGINT; + if (!PyArg_ParseTuple(args, "|i:signum", &signum)) { + return NULL; + } + + if (PyErr_SetInterruptEx(signum)) { + PyErr_SetString(PyExc_ValueError, "signal number out of range"); + return NULL; + } Py_RETURN_NONE; } PyDoc_STRVAR(interrupt_doc, -"interrupt_main()\n\ +"interrupt_main(signum=signal.SIGINT, /)\n\ \n\ -Raise a KeyboardInterrupt in the main thread.\n\ -A subthread can use this function to interrupt the main thread." +Simulate the arrival of the given signal in the main thread,\n\ +where the corresponding signal handler will be executed.\n\ +If *signum* is omitted, SIGINT is assumed.\n\ +A subthread can use this function to interrupt the main thread.\n\ +\n\ +Note: the default signal handler for SIGINT raises ``KeyboardInterrupt``." ); -static lockobject *newlockobject(void); +static lockobject *newlockobject(PyObject *module); static PyObject * -thread_PyThread_allocate_lock(PyObject *self, PyObject *Py_UNUSED(ignored)) +thread_PyThread_allocate_lock(PyObject *module, PyObject *Py_UNUSED(ignored)) { - return (PyObject *) newlockobject(); + return (PyObject *) newlockobject(module); } PyDoc_STRVAR(allocate_doc, @@ -1247,7 +1300,6 @@ release_sentinel(void *wr_raw) PyObject *obj = PyWeakref_GET_OBJECT(wr); lockobject *lock; if (obj != Py_None) { - assert(Py_IS_TYPE(obj, &Locktype)); lock = (lockobject *) obj; if (lock->locked) { PyThread_release_lock(lock->lock_lock); @@ -1260,7 +1312,7 @@ release_sentinel(void *wr_raw) } static PyObject * -thread__set_sentinel(PyObject *self, PyObject *Py_UNUSED(ignored)) +thread__set_sentinel(PyObject *module, PyObject *Py_UNUSED(ignored)) { PyObject *wr; PyThreadState *tstate = PyThreadState_Get(); @@ -1275,7 +1327,7 @@ thread__set_sentinel(PyObject *self, PyObject *Py_UNUSED(ignored)) tstate->on_delete_data = NULL; Py_DECREF(wr); } - lock = newlockobject(); + lock = newlockobject(module); if (lock == NULL) return NULL; /* The lock is owned by whoever called _set_sentinel(), but the weakref @@ -1428,7 +1480,7 @@ static PyStructSequence_Field ExceptHookArgs_fields[] = { }; static PyStructSequence_Desc ExceptHookArgs_desc = { - .name = "_thread.ExceptHookArgs", + .name = "_thread._ExceptHookArgs", .doc = ExceptHookArgs__doc__, .fields = ExceptHookArgs_fields, .n_in_sequence = 4 @@ -1507,8 +1559,8 @@ static PyMethodDef thread_methods[] = { METH_NOARGS, exit_doc}, {"exit", thread_PyThread_exit_thread, METH_NOARGS, exit_doc}, - {"interrupt_main", thread_PyThread_interrupt_main, - METH_NOARGS, interrupt_doc}, + {"interrupt_main", (PyCFunction)thread_PyThread_interrupt_main, + METH_VARARGS, interrupt_doc}, {"get_ident", thread_get_ident, METH_NOARGS, get_ident_doc}, #ifdef PY_HAVE_THREAD_NATIVE_ID @@ -1529,106 +1581,132 @@ static PyMethodDef thread_methods[] = { /* Initialization function */ -PyDoc_STRVAR(thread_doc, -"This module provides primitive operations to write multi-threaded programs.\n\ -The 'threading' module provides a more convenient interface."); +static int +thread_module_exec(PyObject *module) +{ + thread_module_state *state = get_thread_state(module); + PyObject *d = PyModule_GetDict(module); -PyDoc_STRVAR(lock_doc, -"A lock object is a synchronization primitive. To create a lock,\n\ -call threading.Lock(). Methods are:\n\ -\n\ -acquire() -- lock the lock, possibly blocking until it can be obtained\n\ -release() -- unlock of the lock\n\ -locked() -- test whether the lock is currently locked\n\ -\n\ -A lock is not owned by the thread that locked it; another thread may\n\ -unlock it. A thread attempting to lock a lock that it has already locked\n\ -will block until another thread unlocks it. Deadlocks may ensue."); + // Initialize the C thread library + PyThread_init_thread(); -static struct PyModuleDef threadmodule = { - PyModuleDef_HEAD_INIT, - "_thread", - thread_doc, - -1, - thread_methods, - NULL, - NULL, - NULL, - NULL -}; + // Lock + state->lock_type = (PyTypeObject *)PyType_FromSpec(&lock_type_spec); + if (state->lock_type == NULL) { + return -1; + } + if (PyDict_SetItemString(d, "LockType", (PyObject *)state->lock_type) < 0) { + return -1; + } + // RLock + PyTypeObject *rlock_type = (PyTypeObject *)PyType_FromSpec(&rlock_type_spec); + if (rlock_type == NULL) { + return -1; + } + if (PyModule_AddType(module, rlock_type) < 0) { + Py_DECREF(rlock_type); + return -1; + } + Py_DECREF(rlock_type); -PyMODINIT_FUNC -PyInit__thread(void) -{ - PyObject *m, *d, *v; - double time_max; - double timeout_max; - PyInterpreterState *interp = _PyInterpreterState_GET(); + // Local dummy + state->local_dummy_type = (PyTypeObject *)PyType_FromSpec(&local_dummy_type_spec); + if (state->local_dummy_type == NULL) { + return -1; + } + + // Local + state->local_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &local_type_spec, NULL); + if (state->local_type == NULL) { + return -1; + } + if (PyModule_AddType(module, state->local_type) < 0) { + return -1; + } - /* Initialize types: */ - if (PyType_Ready(&localdummytype) < 0) - return NULL; - if (PyType_Ready(&localtype) < 0) - return NULL; - if (PyType_Ready(&Locktype) < 0) - return NULL; - if (PyType_Ready(&RLocktype) < 0) - return NULL; if (ExceptHookArgsType.tp_name == NULL) { if (PyStructSequence_InitType2(&ExceptHookArgsType, &ExceptHookArgs_desc) < 0) { - return NULL; + return -1; } } - /* Create the module and add the functions */ - m = PyModule_Create(&threadmodule); - if (m == NULL) - return NULL; + // Add module attributes + if (PyDict_SetItemString(d, "error", ThreadError) < 0) { + return -1; + } + if (PyModule_AddType(module, &ExceptHookArgsType) < 0) { + return -1; + } - timeout_max = (_PyTime_t)PY_TIMEOUT_MAX * 1e-6; - time_max = _PyTime_AsSecondsDouble(_PyTime_MAX); + // TIMEOUT_MAX + double timeout_max = (_PyTime_t)PY_TIMEOUT_MAX * 1e-6; + double time_max = _PyTime_AsSecondsDouble(_PyTime_MAX); timeout_max = Py_MIN(timeout_max, time_max); - /* Round towards minus infinity */ + // Round towards minus infinity timeout_max = floor(timeout_max); - v = PyFloat_FromDouble(timeout_max); - if (!v) - return NULL; - if (PyModule_AddObject(m, "TIMEOUT_MAX", v) < 0) - return NULL; + if (PyModule_AddObject(module, "TIMEOUT_MAX", + PyFloat_FromDouble(timeout_max)) < 0) { + return -1; + } - /* Add a symbolic constant */ - d = PyModule_GetDict(m); - ThreadError = PyExc_RuntimeError; - Py_INCREF(ThreadError); + return 0; +} - PyDict_SetItemString(d, "error", ThreadError); - Locktype.tp_doc = lock_doc; - Py_INCREF(&Locktype); - PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype); - Py_INCREF(&RLocktype); - if (PyModule_AddObject(m, "RLock", (PyObject *)&RLocktype) < 0) - return NULL; +static int +thread_module_traverse(PyObject *module, visitproc visit, void *arg) +{ + thread_module_state *state = get_thread_state(module); + Py_VISIT(state->lock_type); + Py_VISIT(state->local_type); + Py_VISIT(state->local_dummy_type); + return 0; +} - Py_INCREF(&localtype); - if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0) - return NULL; +static int +thread_module_clear(PyObject *module) +{ + thread_module_state *state = get_thread_state(module); + Py_CLEAR(state->lock_type); + Py_CLEAR(state->local_type); + Py_CLEAR(state->local_dummy_type); + return 0; +} - Py_INCREF(&ExceptHookArgsType); - if (PyModule_AddObject(m, "_ExceptHookArgs", - (PyObject *)&ExceptHookArgsType) < 0) - return NULL; +static void +thread_module_free(void *module) +{ + thread_module_clear((PyObject *)module); +} - interp->num_threads = 0; - str_dict = PyUnicode_InternFromString("__dict__"); - if (str_dict == NULL) - return NULL; - /* Initialize the C thread library */ - PyThread_init_thread(); - return m; +PyDoc_STRVAR(thread_doc, +"This module provides primitive operations to write multi-threaded programs.\n\ +The 'threading' module provides a more convenient interface."); + +static PyModuleDef_Slot thread_module_slots[] = { + {Py_mod_exec, thread_module_exec}, + {0, NULL} +}; + +static struct PyModuleDef thread_module = { + PyModuleDef_HEAD_INIT, + .m_name = "_thread", + .m_doc = thread_doc, + .m_size = sizeof(thread_module_state), + .m_methods = thread_methods, + .m_traverse = thread_module_traverse, + .m_clear = thread_module_clear, + .m_free = thread_module_free, + .m_slots = thread_module_slots, +}; + +PyMODINIT_FUNC +PyInit__thread(void) +{ + return PyModuleDef_Init(&thread_module); } diff --git a/contrib/tools/python3/src/Modules/_winapi.c b/contrib/tools/python3/src/Modules/_winapi.c index 5b7f075722..a44a300c0c 100644 --- a/contrib/tools/python3/src/Modules/_winapi.c +++ b/contrib/tools/python3/src/Modules/_winapi.c @@ -35,8 +35,10 @@ /* See https://www.python.org/2.4/license for licensing details. */ #include "Python.h" +#include "pycore_moduleobject.h" // _PyModule_GetState() #include "structmember.h" // PyMemberDef + #define WINDOWS_LEAN_AND_MEAN #include "windows.h" #include <winioctl.h> @@ -79,6 +81,17 @@ check_CancelIoEx() return has_CancelIoEx; } +typedef struct { + PyTypeObject *overlapped_type; +} WinApiState; + +static inline WinApiState* +winapi_get_state(PyObject *module) +{ + void *state = _PyModule_GetState(module); + assert(state != NULL); + return (WinApiState *)state; +} /* * A Python object wrapping an OVERLAPPED structure and other useful data @@ -100,12 +113,27 @@ typedef struct { Py_buffer write_buffer; } OverlappedObject; +/* +Note: tp_clear (overlapped_clear) is not implemented because it +requires cancelling the IO operation if it's pending and the cancellation is +quite complex and can fail (see: overlapped_dealloc). +*/ +static int +overlapped_traverse(OverlappedObject *self, visitproc visit, void *arg) +{ + Py_VISIT(self->read_buffer); + Py_VISIT(self->write_buffer.obj); + Py_VISIT(Py_TYPE(self)); + return 0; +} + static void overlapped_dealloc(OverlappedObject *self) { DWORD bytes; int err = GetLastError(); + PyObject_GC_UnTrack(self); if (self->pending) { if (check_CancelIoEx() && Py_CancelIoEx(self->handle, &self->overlapped) && @@ -141,12 +169,14 @@ overlapped_dealloc(OverlappedObject *self) if (self->write_buffer.obj) PyBuffer_Release(&self->write_buffer); Py_CLEAR(self->read_buffer); - PyObject_Del(self); + PyTypeObject *tp = Py_TYPE(self); + tp->tp_free(self); + Py_DECREF(tp); } /*[clinic input] module _winapi -class _winapi.Overlapped "OverlappedObject *" "&WinApiOverlappedType" +class _winapi.Overlapped "OverlappedObject *" "&OverlappedType" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=c13d3f5fd1dabb84]*/ @@ -165,10 +195,11 @@ create_converter('LPCVOID', '" F_POINTER "') create_converter('BOOL', 'i') # F_BOOL used previously (always 'i') create_converter('DWORD', 'k') # F_DWORD is always "k" (which is much shorter) create_converter('LPCTSTR', 's') -create_converter('LPCWSTR', 'u') -create_converter('LPWSTR', 'u') create_converter('UINT', 'I') # F_UINT used previously (always 'I') +class LPCWSTR_converter(Py_UNICODE_converter): + type = 'LPCWSTR' + class HANDLE_return_converter(CReturnConverter): type = 'HANDLE' @@ -198,7 +229,7 @@ class LPVOID_return_converter(CReturnConverter): data.return_conversion.append( 'return_value = HANDLE_TO_PYNUM(_return_value);\n') [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=79464c61a31ae932]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=011ee0c3a2244bfe]*/ #include "clinic/_winapi.c.h" @@ -305,55 +336,31 @@ static PyMemberDef overlapped_members[] = { {NULL} }; -PyTypeObject WinApiOverlappedType = { - PyVarObject_HEAD_INIT(NULL, 0) - /* tp_name */ "_winapi.Overlapped", - /* tp_basicsize */ sizeof(OverlappedObject), - /* tp_itemsize */ 0, - /* tp_dealloc */ (destructor) overlapped_dealloc, - /* tp_vectorcall_offset */ 0, - /* tp_getattr */ 0, - /* tp_setattr */ 0, - /* tp_as_async */ 0, - /* tp_repr */ 0, - /* tp_as_number */ 0, - /* tp_as_sequence */ 0, - /* tp_as_mapping */ 0, - /* tp_hash */ 0, - /* tp_call */ 0, - /* tp_str */ 0, - /* tp_getattro */ 0, - /* tp_setattro */ 0, - /* tp_as_buffer */ 0, - /* tp_flags */ Py_TPFLAGS_DEFAULT, - /* tp_doc */ "OVERLAPPED structure wrapper", - /* tp_traverse */ 0, - /* tp_clear */ 0, - /* tp_richcompare */ 0, - /* tp_weaklistoffset */ 0, - /* tp_iter */ 0, - /* tp_iternext */ 0, - /* tp_methods */ overlapped_methods, - /* tp_members */ overlapped_members, - /* tp_getset */ 0, - /* tp_base */ 0, - /* tp_dict */ 0, - /* tp_descr_get */ 0, - /* tp_descr_set */ 0, - /* tp_dictoffset */ 0, - /* tp_init */ 0, - /* tp_alloc */ 0, - /* tp_new */ 0, +static PyType_Slot winapi_overlapped_type_slots[] = { + {Py_tp_traverse, overlapped_traverse}, + {Py_tp_dealloc, overlapped_dealloc}, + {Py_tp_doc, "OVERLAPPED structure wrapper"}, + {Py_tp_methods, overlapped_methods}, + {Py_tp_members, overlapped_members}, + {0,0} +}; + +static PyType_Spec winapi_overlapped_type_spec = { + .name = "_winapi.Overlapped", + .basicsize = sizeof(OverlappedObject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), + .slots = winapi_overlapped_type_slots, }; static OverlappedObject * -new_overlapped(HANDLE handle) +new_overlapped(PyObject *module, HANDLE handle) { - OverlappedObject *self; - - self = PyObject_New(OverlappedObject, &WinApiOverlappedType); + WinApiState *st = winapi_get_state(module); + OverlappedObject *self = PyObject_GC_New(OverlappedObject, st->overlapped_type); if (!self) return NULL; + self->handle = handle; self->read_buffer = NULL; self->pending = 0; @@ -362,6 +369,8 @@ new_overlapped(HANDLE handle) memset(&self->write_buffer, 0, sizeof(Py_buffer)); /* Manual reset, initially non-signalled */ self->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + PyObject_GC_Track(self); return self; } @@ -409,7 +418,7 @@ _winapi_ConnectNamedPipe_impl(PyObject *module, HANDLE handle, OverlappedObject *overlapped = NULL; if (use_overlapped) { - overlapped = new_overlapped(handle); + overlapped = new_overlapped(module, handle); if (!overlapped) return NULL; } @@ -521,15 +530,15 @@ _winapi_CreateFileMapping_impl(PyObject *module, HANDLE file_handle, /*[clinic input] _winapi.CreateJunction - src_path: LPWSTR - dst_path: LPWSTR + src_path: LPCWSTR + dst_path: LPCWSTR / [clinic start generated code]*/ static PyObject * -_winapi_CreateJunction_impl(PyObject *module, LPWSTR src_path, - LPWSTR dst_path) -/*[clinic end generated code: output=66b7eb746e1dfa25 input=8cd1f9964b6e3d36]*/ +_winapi_CreateJunction_impl(PyObject *module, LPCWSTR src_path, + LPCWSTR dst_path) +/*[clinic end generated code: output=44b3f5e9bbcc4271 input=963d29b44b9384a7]*/ { /* Privilege adjustment */ HANDLE token = NULL; @@ -1527,7 +1536,7 @@ _winapi_ReadFile_impl(PyObject *module, HANDLE handle, DWORD size, if (!buf) return NULL; if (use_overlapped) { - overlapped = new_overlapped(handle); + overlapped = new_overlapped(module, handle); if (!overlapped) { Py_DECREF(buf); return NULL; @@ -1810,7 +1819,7 @@ _winapi_WriteFile_impl(PyObject *module, HANDLE handle, PyObject *buffer, OverlappedObject *overlapped = NULL; if (use_overlapped) { - overlapped = new_overlapped(handle); + overlapped = new_overlapped(module, handle); if (!overlapped) return NULL; buf = &overlapped->write_buffer; @@ -1886,6 +1895,113 @@ _winapi_GetFileType_impl(PyObject *module, HANDLE handle) return result; } +/*[clinic input] +_winapi._mimetypes_read_windows_registry + + on_type_read: object + +Optimized function for reading all known MIME types from the registry. + +*on_type_read* is a callable taking *type* and *ext* arguments, as for +MimeTypes.add_type. +[clinic start generated code]*/ + +static PyObject * +_winapi__mimetypes_read_windows_registry_impl(PyObject *module, + PyObject *on_type_read) +/*[clinic end generated code: output=20829f00bebce55b input=cd357896d6501f68]*/ +{ +#define CCH_EXT 128 +#define CB_TYPE 510 + struct { + wchar_t ext[CCH_EXT]; + wchar_t type[CB_TYPE / sizeof(wchar_t) + 1]; + } entries[64]; + int entry = 0; + HKEY hkcr = NULL; + LRESULT err; + + Py_BEGIN_ALLOW_THREADS + err = RegOpenKeyExW(HKEY_CLASSES_ROOT, NULL, 0, KEY_READ, &hkcr); + for (DWORD i = 0; err == ERROR_SUCCESS || err == ERROR_MORE_DATA; ++i) { + LPWSTR ext = entries[entry].ext; + LPWSTR type = entries[entry].type; + DWORD cchExt = CCH_EXT; + DWORD cbType = CB_TYPE; + HKEY subkey; + DWORD regType; + + err = RegEnumKeyExW(hkcr, i, ext, &cchExt, NULL, NULL, NULL, NULL); + if (err != ERROR_SUCCESS || (cchExt && ext[0] != L'.')) { + continue; + } + + err = RegOpenKeyExW(hkcr, ext, 0, KEY_READ, &subkey); + if (err == ERROR_FILE_NOT_FOUND) { + err = ERROR_SUCCESS; + continue; + } else if (err != ERROR_SUCCESS) { + continue; + } + + err = RegQueryValueExW(subkey, L"Content Type", NULL, + ®Type, (LPBYTE)type, &cbType); + RegCloseKey(subkey); + if (err == ERROR_FILE_NOT_FOUND) { + err = ERROR_SUCCESS; + continue; + } else if (err != ERROR_SUCCESS) { + continue; + } else if (regType != REG_SZ || !cbType) { + continue; + } + type[cbType / sizeof(wchar_t)] = L'\0'; + + entry += 1; + + /* Flush our cached entries if we are full */ + if (entry == sizeof(entries) / sizeof(entries[0])) { + Py_BLOCK_THREADS + for (int j = 0; j < entry; ++j) { + PyObject *r = PyObject_CallFunction( + on_type_read, "uu", entries[j].type, entries[j].ext + ); + if (!r) { + /* We blocked threads, so safe to return from here */ + RegCloseKey(hkcr); + return NULL; + } + Py_DECREF(r); + } + Py_UNBLOCK_THREADS + entry = 0; + } + } + if (hkcr) { + RegCloseKey(hkcr); + } + Py_END_ALLOW_THREADS + + if (err != ERROR_SUCCESS && err != ERROR_NO_MORE_ITEMS) { + PyErr_SetFromWindowsErr((int)err); + return NULL; + } + + for (int j = 0; j < entry; ++j) { + PyObject *r = PyObject_CallFunction( + on_type_read, "uu", entries[j].type, entries[j].ext + ); + if (!r) { + return NULL; + } + Py_DECREF(r); + } + + Py_RETURN_NONE; +#undef CCH_EXT +#undef CB_TYPE +} + static PyMethodDef winapi_functions[] = { _WINAPI_CLOSEHANDLE_METHODDEF @@ -1918,39 +2034,37 @@ static PyMethodDef winapi_functions[] = { _WINAPI_WRITEFILE_METHODDEF _WINAPI_GETACP_METHODDEF _WINAPI_GETFILETYPE_METHODDEF + _WINAPI__MIMETYPES_READ_WINDOWS_REGISTRY_METHODDEF {NULL, NULL} }; -static struct PyModuleDef winapi_module = { - PyModuleDef_HEAD_INIT, - "_winapi", - NULL, - -1, - winapi_functions, - NULL, - NULL, - NULL, - NULL -}; - #define WINAPI_CONSTANT(fmt, con) \ - PyDict_SetItemString(d, #con, Py_BuildValue(fmt, con)) - -PyMODINIT_FUNC -PyInit__winapi(void) + do { \ + PyObject *value = Py_BuildValue(fmt, con); \ + if (value == NULL) { \ + return -1; \ + } \ + if (PyDict_SetItemString(d, #con, value) < 0) { \ + Py_DECREF(value); \ + return -1; \ + } \ + Py_DECREF(value); \ + } while (0) + +static int winapi_exec(PyObject *m) { - PyObject *d; - PyObject *m; + WinApiState *st = winapi_get_state(m); - if (PyType_Ready(&WinApiOverlappedType) < 0) - return NULL; + st->overlapped_type = (PyTypeObject *)PyType_FromModuleAndSpec(m, &winapi_overlapped_type_spec, NULL); + if (st->overlapped_type == NULL) { + return -1; + } - m = PyModule_Create(&winapi_module); - if (m == NULL) - return NULL; - d = PyModule_GetDict(m); + if (PyModule_AddType(m, st->overlapped_type) < 0) { + return -1; + } - PyDict_SetItemString(d, "Overlapped", (PyObject *) &WinApiOverlappedType); + PyObject *d = PyModule_GetDict(m); /* constants */ WINAPI_CONSTANT(F_DWORD, CREATE_NEW_CONSOLE); @@ -2049,5 +2163,49 @@ PyInit__winapi(void) WINAPI_CONSTANT("i", NULL); - return m; + return 0; +} + +static PyModuleDef_Slot winapi_slots[] = { + {Py_mod_exec, winapi_exec}, + {0, NULL} +}; + +static int +winapi_traverse(PyObject *module, visitproc visit, void *arg) +{ + WinApiState *st = winapi_get_state(module); + Py_VISIT(st->overlapped_type); + return 0; +} + +static int +winapi_clear(PyObject *module) +{ + WinApiState *st = winapi_get_state(module); + Py_CLEAR(st->overlapped_type); + return 0; +} + +static void +winapi_free(void *module) +{ + winapi_clear((PyObject *)module); +} + +static struct PyModuleDef winapi_module = { + PyModuleDef_HEAD_INIT, + .m_name = "_winapi", + .m_size = sizeof(WinApiState), + .m_methods = winapi_functions, + .m_slots = winapi_slots, + .m_traverse = winapi_traverse, + .m_clear = winapi_clear, + .m_free = winapi_free, +}; + +PyMODINIT_FUNC +PyInit__winapi(void) +{ + return PyModuleDef_Init(&winapi_module); } diff --git a/contrib/tools/python3/src/Modules/_xxsubinterpretersmodule.c b/contrib/tools/python3/src/Modules/_xxsubinterpretersmodule.c index 314059d108..9290255c66 100644 --- a/contrib/tools/python3/src/Modules/_xxsubinterpretersmodule.c +++ b/contrib/tools/python3/src/Modules/_xxsubinterpretersmodule.c @@ -1780,7 +1780,12 @@ static PyTypeObject ChannelIDtype = { 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + // Use Py_TPFLAGS_DISALLOW_INSTANTIATION so the type cannot be instantiated + // from Python code. We do this because there is a strong relationship + // between channel IDs and the channel lifecycle, so this limitation avoids + // related complications. Use the _channel_id() function instead. + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE + | Py_TPFLAGS_DISALLOW_INSTANTIATION, /* tp_flags */ channelid_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ @@ -1791,19 +1796,6 @@ static PyTypeObject ChannelIDtype = { 0, /* tp_methods */ 0, /* tp_members */ channelid_getsets, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - // Note that we do not set tp_new to channelid_new. Instead we - // set it to NULL, meaning it cannot be instantiated from Python - // code. We do this because there is a strong relationship between - // channel IDs and the channel lifecycle, so this limitation avoids - // related complications. - NULL, /* tp_new */ }; @@ -1847,7 +1839,7 @@ _is_running(PyInterpreterState *interp) return 0; } - int executing = (int)(frame->f_executing); + int executing = _PyFrame_IsExecuting(frame); Py_DECREF(frame); return executing; @@ -1939,6 +1931,20 @@ _run_script_in_interpreter(PyInterpreterState *interp, const char *codestr, return -1; } +#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS + // Switch to interpreter. + PyThreadState *new_tstate = PyInterpreterState_ThreadHead(interp); + PyThreadState *save1 = PyEval_SaveThread(); + + (void)PyThreadState_Swap(new_tstate); + + // Run the script. + _sharedexception *exc = NULL; + int result = _run_script(interp, codestr, shared, &exc); + + // Switch back. + PyEval_RestoreThread(save1); +#else // Switch to interpreter. PyThreadState *save_tstate = NULL; if (interp != PyInterpreterState_Get()) { @@ -1956,6 +1962,7 @@ _run_script_in_interpreter(PyInterpreterState *interp, const char *codestr, if (save_tstate != NULL) { PyThreadState_Swap(save_tstate); } +#endif // Propagate any exception out to the caller. if (exc != NULL) { diff --git a/contrib/tools/python3/src/Modules/_xxtestfuzz/fuzzer.c b/contrib/tools/python3/src/Modules/_xxtestfuzz/fuzzer.c index 6bd2c3aedc..acbf068637 100644 --- a/contrib/tools/python3/src/Modules/_xxtestfuzz/fuzzer.c +++ b/contrib/tools/python3/src/Modules/_xxtestfuzz/fuzzer.c @@ -83,7 +83,7 @@ static int fuzz_builtin_unicode(const char* data, size_t size) { PyObject* struct_unpack_method = NULL; PyObject* struct_error = NULL; /* Called by LLVMFuzzerTestOneInput for initialization */ -static int init_struct_unpack() { +static int init_struct_unpack(void) { /* Import struct.unpack */ PyObject* struct_module = PyImport_ImportModule("struct"); if (struct_module == NULL) { @@ -146,7 +146,7 @@ static int fuzz_struct_unpack(const char* data, size_t size) { PyObject* json_loads_method = NULL; /* Called by LLVMFuzzerTestOneInput for initialization */ -static int init_json_loads() { +static int init_json_loads(void) { /* Import json.loads */ PyObject* json_module = PyImport_ImportModule("json"); if (json_module == NULL) { @@ -192,7 +192,7 @@ PyObject* sre_compile_method = NULL; PyObject* sre_error_exception = NULL; int SRE_FLAG_DEBUG = 0; /* Called by LLVMFuzzerTestOneInput for initialization */ -static int init_sre_compile() { +static int init_sre_compile(void) { /* Import sre_compile.compile and sre.error */ PyObject* sre_compile_module = PyImport_ImportModule("sre_compile"); if (sre_compile_module == NULL) { @@ -284,7 +284,7 @@ static const char* regex_patterns[] = { const size_t NUM_PATTERNS = sizeof(regex_patterns) / sizeof(regex_patterns[0]); PyObject** compiled_patterns = NULL; /* Called by LLVMFuzzerTestOneInput for initialization */ -static int init_sre_match() { +static int init_sre_match(void) { PyObject* re_module = PyImport_ImportModule("re"); if (re_module == NULL) { return 0; @@ -339,7 +339,7 @@ static int fuzz_sre_match(const char* data, size_t size) { PyObject* csv_module = NULL; PyObject* csv_error = NULL; /* Called by LLVMFuzzerTestOneInput for initialization */ -static int init_csv_reader() { +static int init_csv_reader(void) { /* Import csv and csv.Error */ csv_module = PyImport_ImportModule("csv"); if (csv_module == NULL) { @@ -354,7 +354,7 @@ static int fuzz_csv_reader(const char* data, size_t size) { return 0; } /* Ignore non null-terminated strings since _csv can't handle - embeded nulls */ + embedded nulls */ if (memchr(data, '\0', size) == NULL) { return 0; } @@ -383,7 +383,7 @@ static int fuzz_csv_reader(const char* data, size_t size) { } /* Ignore csv.Error because we're probably going to generate - some bad files (embeded new-lines, unterminated quotes etc) */ + some bad files (embedded new-lines, unterminated quotes etc) */ if (PyErr_ExceptionMatches(csv_error)) { PyErr_Clear(); } diff --git a/contrib/tools/python3/src/Modules/_zoneinfo.c b/contrib/tools/python3/src/Modules/_zoneinfo.c index cd147aedb4..0388d27ce1 100644 --- a/contrib/tools/python3/src/Modules/_zoneinfo.c +++ b/contrib/tools/python3/src/Modules/_zoneinfo.c @@ -1,4 +1,5 @@ #include "Python.h" +#include "pycore_long.h" // _PyLong_GetOne() #include "structmember.h" #include <ctype.h> @@ -487,9 +488,7 @@ zoneinfo_tzname(PyObject *self, PyObject *dt) return tti->tzname; } -#define HASTZINFO(p) (((_PyDateTime_BaseTZInfo *)(p))->hastzinfo) -#define GET_DT_TZINFO(p) \ - (HASTZINFO(p) ? ((PyDateTime_DateTime *)(p))->tzinfo : Py_None) +#define GET_DT_TZINFO PyDateTime_DATE_GET_TZINFO static PyObject * zoneinfo_fromutc(PyObject *obj_self, PyObject *dt) @@ -590,7 +589,7 @@ zoneinfo_fromutc(PyObject *obj_self, PyObject *dt) } dt = NULL; - if (!PyDict_SetItemString(kwargs, "fold", _PyLong_One)) { + if (!PyDict_SetItemString(kwargs, "fold", _PyLong_GetOne())) { dt = PyObject_Call(replace, args, kwargs); } @@ -727,17 +726,16 @@ zoneinfo__unpickle(PyTypeObject *cls, PyObject *args) static PyObject * load_timedelta(long seconds) { - PyObject *rv = NULL; + PyObject *rv; PyObject *pyoffset = PyLong_FromLong(seconds); if (pyoffset == NULL) { return NULL; } - int contains = PyDict_Contains(TIMEDELTA_CACHE, pyoffset); - if (contains == -1) { - goto error; - } - - if (!contains) { + rv = PyDict_GetItemWithError(TIMEDELTA_CACHE, pyoffset); + if (rv == NULL) { + if (PyErr_Occurred()) { + goto error; + } PyObject *tmp = PyDateTimeAPI->Delta_FromDelta( 0, seconds, 0, 1, PyDateTimeAPI->DeltaType); @@ -748,12 +746,9 @@ load_timedelta(long seconds) rv = PyDict_SetDefault(TIMEDELTA_CACHE, pyoffset, tmp); Py_DECREF(tmp); } - else { - rv = PyDict_GetItem(TIMEDELTA_CACHE, pyoffset); - } + Py_XINCREF(rv); Py_DECREF(pyoffset); - Py_INCREF(rv); return rv; error: Py_DECREF(pyoffset); @@ -1473,11 +1468,11 @@ parse_tz_str(PyObject *tz_str_obj, _tzrule *out) long std_offset = 1 << 20; long dst_offset = 1 << 20; - char *tz_str = PyBytes_AsString(tz_str_obj); + const char *tz_str = PyBytes_AsString(tz_str_obj); if (tz_str == NULL) { return -1; } - char *p = tz_str; + const char *p = tz_str; // Read the `std` abbreviation, which must be at least 3 characters long. Py_ssize_t num_chars = parse_abbr(p, &std_abbr); diff --git a/contrib/tools/python3/src/Modules/arraymodule.c b/contrib/tools/python3/src/Modules/arraymodule.c index 7c7fc91745..72b90111a8 100644 --- a/contrib/tools/python3/src/Modules/arraymodule.c +++ b/contrib/tools/python3/src/Modules/arraymodule.c @@ -5,6 +5,8 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" +#include "pycore_moduleobject.h" // _PyModule_GetState() +#include "structmember.h" // PyMemberDef #include <stddef.h> // offsetof() #ifdef STDC_HEADERS @@ -21,6 +23,7 @@ module array /*[clinic end generated code: output=da39a3ee5e6b4b0d input=7d1b8d7f5958fd83]*/ struct arrayobject; /* Forward */ +static struct PyModuleDef arraymodule; /* All possible arraydescr values are defined in the vector "descriptors" * below. That's defined later because the appropriate get and set @@ -46,8 +49,6 @@ typedef struct arrayobject { Py_ssize_t ob_exports; /* Number of exported buffers */ } arrayobject; -static PyTypeObject Arraytype; - typedef struct { PyObject_HEAD Py_ssize_t index; @@ -55,9 +56,21 @@ typedef struct { PyObject* (*getitem)(struct arrayobject *, Py_ssize_t); } arrayiterobject; -static PyTypeObject PyArrayIter_Type; +typedef struct { + PyTypeObject *ArrayType; + PyTypeObject *ArrayIterType; +} array_state; + +static array_state * +get_array_state(PyObject *module) +{ + return (array_state *)_PyModule_GetState(module); +} -#define PyArrayIter_Check(op) PyObject_TypeCheck(op, &PyArrayIter_Type) +#define find_array_state_by_type(tp) \ + (get_array_state(_PyType_GetModuleByDef(tp, &arraymodule))) +#define get_array_state_by_class(cls) \ + (get_array_state(PyType_GetModule(cls))) enum machine_format_code { UNKNOWN_FORMAT = -1, @@ -105,8 +118,7 @@ enum machine_format_code { */ #include "clinic/arraymodule.c.h" -#define array_Check(op) PyObject_TypeCheck(op, &Arraytype) -#define array_CheckExact(op) Py_IS_TYPE(op, &Arraytype) +#define array_Check(op, state) PyObject_TypeCheck(op, state->ArrayType) static int array_resize(arrayobject *self, Py_ssize_t newsize) @@ -133,7 +145,7 @@ array_resize(arrayobject *self, Py_ssize_t newsize) } if (newsize == 0) { - PyMem_FREE(self->ob_item); + PyMem_Free(self->ob_item); self->ob_item = NULL; Py_SET_SIZE(self, 0); self->allocated = 0; @@ -337,17 +349,6 @@ II_getitem(arrayobject *ap, Py_ssize_t i) (unsigned long) ((unsigned int *)ap->ob_item)[i]); } -static PyObject * -get_int_unless_float(PyObject *v) -{ - if (PyFloat_Check(v)) { - PyErr_SetString(PyExc_TypeError, - "array item must be integer"); - return NULL; - } - return _PyLong_FromNbIndexOrNbInt(v); -} - static int II_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) { @@ -355,7 +356,7 @@ II_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) int do_decref = 0; /* if nb_int was called */ if (!PyLong_Check(v)) { - v = get_int_unless_float(v); + v = _PyNumber_Index(v); if (NULL == v) { return -1; } @@ -415,7 +416,7 @@ LL_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) int do_decref = 0; /* if nb_int was called */ if (!PyLong_Check(v)) { - v = get_int_unless_float(v); + v = _PyNumber_Index(v); if (NULL == v) { return -1; } @@ -468,7 +469,7 @@ QQ_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) int do_decref = 0; /* if nb_int was called */ if (!PyLong_Check(v)) { - v = get_int_unless_float(v); + v = _PyNumber_Index(v); if (NULL == v) { return -1; } @@ -573,9 +574,9 @@ static const struct arraydescr descriptors[] = { Implementations of array object methods. ****************************************************************************/ /*[clinic input] -class array.array "arrayobject *" "&Arraytype" +class array.array "arrayobject *" "ArrayType" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ad43d37e942a8854]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=a5c29edf59f176a3]*/ static PyObject * newarrayobject(PyTypeObject *type, Py_ssize_t size, const struct arraydescr *descr) @@ -618,8 +619,11 @@ newarrayobject(PyTypeObject *type, Py_ssize_t size, const struct arraydescr *des static PyObject * getarrayitem(PyObject *op, Py_ssize_t i) { +#ifndef NDEBUG + array_state *state = find_array_state_by_type(Py_TYPE(op)); + assert(array_Check(op, state)); +#endif arrayobject *ap; - assert(array_Check(op)); ap = (arrayobject *)op; assert(i>=0 && i<Py_SIZE(ap)); return (*ap->ob_descr->getitem)(ap, i); @@ -657,26 +661,38 @@ ins1(arrayobject *self, Py_ssize_t where, PyObject *v) /* Methods */ +static int +array_tp_traverse(arrayobject *op, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(op)); + return 0; +} + static void array_dealloc(arrayobject *op) { + PyTypeObject *tp = Py_TYPE(op); + PyObject_GC_UnTrack(op); + if (op->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) op); if (op->ob_item != NULL) - PyMem_DEL(op->ob_item); - Py_TYPE(op)->tp_free((PyObject *)op); + PyMem_Free(op->ob_item); + tp->tp_free(op); + Py_DECREF(tp); } static PyObject * array_richcompare(PyObject *v, PyObject *w, int op) { + array_state *state = find_array_state_by_type(Py_TYPE(v)); arrayobject *va, *wa; PyObject *vi = NULL; PyObject *wi = NULL; Py_ssize_t i, k; PyObject *res; - if (!array_Check(v) || !array_Check(w)) + if (!array_Check(v, state) || !array_Check(w, state)) Py_RETURN_NOTIMPLEMENTED; va = (arrayobject *)v; @@ -798,7 +814,9 @@ array_item(arrayobject *a, Py_ssize_t i) static PyObject * array_slice(arrayobject *a, Py_ssize_t ilow, Py_ssize_t ihigh) { + array_state *state = find_array_state_by_type(Py_TYPE(a)); arrayobject *np; + if (ilow < 0) ilow = 0; else if (ilow > Py_SIZE(a)) @@ -809,7 +827,7 @@ array_slice(arrayobject *a, Py_ssize_t ilow, Py_ssize_t ihigh) ihigh = ilow; else if (ihigh > Py_SIZE(a)) ihigh = Py_SIZE(a); - np = (arrayobject *) newarrayobject(&Arraytype, ihigh - ilow, a->ob_descr); + np = (arrayobject *) newarrayobject(state->ArrayType, ihigh - ilow, a->ob_descr); if (np == NULL) return NULL; if (ihigh > ilow) { @@ -852,9 +870,10 @@ array_array___deepcopy__(arrayobject *self, PyObject *unused) static PyObject * array_concat(arrayobject *a, PyObject *bb) { + array_state *state = find_array_state_by_type(Py_TYPE(a)); Py_ssize_t size; arrayobject *np; - if (!array_Check(bb)) { + if (!array_Check(bb, state)) { PyErr_Format(PyExc_TypeError, "can only append array (not \"%.200s\") to array", Py_TYPE(bb)->tp_name); @@ -869,7 +888,7 @@ array_concat(arrayobject *a, PyObject *bb) return PyErr_NoMemory(); } size = Py_SIZE(a) + Py_SIZE(b); - np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr); + np = (arrayobject *) newarrayobject(state->ArrayType, size, a->ob_descr); if (np == NULL) { return NULL; } @@ -887,6 +906,7 @@ array_concat(arrayobject *a, PyObject *bb) static PyObject * array_repeat(arrayobject *a, Py_ssize_t n) { + array_state *state = find_array_state_by_type(Py_TYPE(a)); Py_ssize_t size; arrayobject *np; Py_ssize_t oldbytes, newbytes; @@ -896,7 +916,7 @@ array_repeat(arrayobject *a, Py_ssize_t n) return PyErr_NoMemory(); } size = Py_SIZE(a) * n; - np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr); + np = (arrayobject *) newarrayobject(state->ArrayType, size, a->ob_descr); if (np == NULL) return NULL; if (size == 0) @@ -969,7 +989,10 @@ array_ass_item(arrayobject *a, Py_ssize_t i, PyObject *v) static int setarrayitem(PyObject *a, Py_ssize_t i, PyObject *v) { - assert(array_Check(a)); +#ifndef NDEBUG + array_state *state = find_array_state_by_type(Py_TYPE(a)); + assert(array_Check(a, state)); +#endif return array_ass_item((arrayobject *)a, i, v); } @@ -997,11 +1020,11 @@ array_iter_extend(arrayobject *self, PyObject *bb) } static int -array_do_extend(arrayobject *self, PyObject *bb) +array_do_extend(array_state *state, arrayobject *self, PyObject *bb) { Py_ssize_t size, oldsize, bbsize; - if (!array_Check(bb)) + if (!array_Check(bb, state)) return array_iter_extend(self, bb); #define b ((arrayobject *)bb) if (self->ob_descr != b->ob_descr) { @@ -1032,13 +1055,15 @@ array_do_extend(arrayobject *self, PyObject *bb) static PyObject * array_inplace_concat(arrayobject *self, PyObject *bb) { - if (!array_Check(bb)) { + array_state *state = find_array_state_by_type(Py_TYPE(self)); + + if (!array_Check(bb, state)) { PyErr_Format(PyExc_TypeError, "can only extend array with array (not \"%.200s\")", Py_TYPE(bb)->tp_name); return NULL; } - if (array_do_extend(self, bb) == -1) + if (array_do_extend(state, self, bb) == -1) return NULL; Py_INCREF(self); return (PyObject *)self; @@ -1120,18 +1145,32 @@ array_array_count(arrayobject *self, PyObject *v) array.array.index v: object + start: slice_index(accept={int}) = 0 + stop: slice_index(accept={int}, c_default="PY_SSIZE_T_MAX") = sys.maxsize / Return index of first occurrence of v in the array. + +Raise ValueError if the value is not present. [clinic start generated code]*/ static PyObject * -array_array_index(arrayobject *self, PyObject *v) -/*[clinic end generated code: output=d48498d325602167 input=cf619898c6649d08]*/ -{ - Py_ssize_t i; - - for (i = 0; i < Py_SIZE(self); i++) { +array_array_index_impl(arrayobject *self, PyObject *v, Py_ssize_t start, + Py_ssize_t stop) +/*[clinic end generated code: output=c45e777880c99f52 input=089dff7baa7e5a7e]*/ +{ + if (start < 0) { + start += Py_SIZE(self); + if (start < 0) { + start = 0; + } + } + if (stop < 0) { + stop += Py_SIZE(self); + } + // Use Py_SIZE() for every iteration in case the array is mutated + // during PyObject_RichCompareBool() + for (Py_ssize_t i = start; i < stop && i < Py_SIZE(self); i++) { PyObject *selfi; int cmp; @@ -1243,6 +1282,7 @@ array_array_pop_impl(arrayobject *self, Py_ssize_t i) /*[clinic input] array.array.extend + cls: defining_class bb: object / @@ -1250,10 +1290,12 @@ Append items to the end of the array. [clinic start generated code]*/ static PyObject * -array_array_extend(arrayobject *self, PyObject *bb) -/*[clinic end generated code: output=bbddbc8e8bef871d input=43be86aba5c31e44]*/ +array_array_extend_impl(arrayobject *self, PyTypeObject *cls, PyObject *bb) +/*[clinic end generated code: output=e65eb7588f0bc266 input=8eb6817ec4d2cb62]*/ { - if (array_do_extend(self, bb) == -1) + array_state *state = get_array_state_by_class(cls); + + if (array_do_extend(state, self, bb) == -1) return NULL; Py_RETURN_NONE; } @@ -1939,6 +1981,7 @@ array__array_reconstructor_impl(PyObject *module, PyTypeObject *arraytype, PyObject *items) /*[clinic end generated code: output=e05263141ba28365 input=2464dc8f4c7736b5]*/ { + array_state *state = get_array_state(module); PyObject *converted_items; PyObject *result; const struct arraydescr *descr; @@ -1949,10 +1992,10 @@ array__array_reconstructor_impl(PyObject *module, PyTypeObject *arraytype, Py_TYPE(arraytype)->tp_name); return NULL; } - if (!PyType_IsSubtype(arraytype, &Arraytype)) { + if (!PyType_IsSubtype(arraytype, state->ArrayType)) { PyErr_Format(PyExc_TypeError, "%.200s is not a subtype of %.200s", - arraytype->tp_name, Arraytype.tp_name); + arraytype->tp_name, state->ArrayType->tp_name); return NULL; } for (descr = descriptors; descr->typecode != '\0'; descr++) { @@ -2298,6 +2341,8 @@ array_repr(arrayobject *a) static PyObject* array_subscr(arrayobject* self, PyObject* item) { + array_state *state = find_array_state_by_type(Py_TYPE(self)); + if (PyIndex_Check(item)) { Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); if (i==-1 && PyErr_Occurred()) { @@ -2321,10 +2366,10 @@ array_subscr(arrayobject* self, PyObject* item) step); if (slicelength <= 0) { - return newarrayobject(&Arraytype, 0, self->ob_descr); + return newarrayobject(state->ArrayType, 0, self->ob_descr); } else if (step == 1) { - PyObject *result = newarrayobject(&Arraytype, + PyObject *result = newarrayobject(state->ArrayType, slicelength, self->ob_descr); if (result == NULL) return NULL; @@ -2334,7 +2379,7 @@ array_subscr(arrayobject* self, PyObject* item) return result; } else { - result = newarrayobject(&Arraytype, slicelength, self->ob_descr); + result = newarrayobject(state->ArrayType, slicelength, self->ob_descr); if (!result) return NULL; ar = (arrayobject*)result; @@ -2360,6 +2405,7 @@ static int array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value) { Py_ssize_t start, stop, step, slicelength, needed; + array_state* state = find_array_state_by_type(Py_TYPE(self)); arrayobject* other; int itemsize; @@ -2401,7 +2447,7 @@ array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value) other = NULL; needed = 0; } - else if (array_Check(value)) { + else if (array_Check(value, state)) { other = (arrayobject *)value; needed = Py_SIZE(other); if (self == other) { @@ -2513,12 +2559,6 @@ array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value) } } -static PyMappingMethods array_as_mapping = { - (lenfunc)array_length, - (binaryfunc)array_subscr, - (objobjargproc)array_ass_subscr -}; - static const void *emptybuf = ""; @@ -2536,14 +2576,14 @@ array_buffer_getbuf(arrayobject *self, Py_buffer *view, int flags) Py_INCREF(self); if (view->buf == NULL) view->buf = (void *)emptybuf; - view->len = (Py_SIZE(self)) * self->ob_descr->itemsize; + view->len = Py_SIZE(self) * self->ob_descr->itemsize; view->readonly = 0; view->ndim = 1; view->itemsize = self->ob_descr->itemsize; view->suboffsets = NULL; view->shape = NULL; if ((flags & PyBUF_ND)==PyBUF_ND) { - view->shape = &((Py_SIZE(self))); + view->shape = &((PyVarObject*)self)->ob_size; } view->strides = NULL; if ((flags & PyBUF_STRIDES)==PyBUF_STRIDES) @@ -2569,32 +2609,15 @@ array_buffer_relbuf(arrayobject *self, Py_buffer *view) self->ob_exports--; } -static PySequenceMethods array_as_sequence = { - (lenfunc)array_length, /*sq_length*/ - (binaryfunc)array_concat, /*sq_concat*/ - (ssizeargfunc)array_repeat, /*sq_repeat*/ - (ssizeargfunc)array_item, /*sq_item*/ - 0, /*sq_slice*/ - (ssizeobjargproc)array_ass_item, /*sq_ass_item*/ - 0, /*sq_ass_slice*/ - (objobjproc)array_contains, /*sq_contains*/ - (binaryfunc)array_inplace_concat, /*sq_inplace_concat*/ - (ssizeargfunc)array_inplace_repeat /*sq_inplace_repeat*/ -}; - -static PyBufferProcs array_as_buffer = { - (getbufferproc)array_buffer_getbuf, - (releasebufferproc)array_buffer_relbuf -}; - static PyObject * array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { + array_state *state = find_array_state_by_type(type); int c; PyObject *initial = NULL, *it = NULL; const struct arraydescr *descr; - if (type == &Arraytype && !_PyArg_NoKeywords("array.array", kwds)) + if (type == state->ArrayType && !_PyArg_NoKeywords("array.array", kwds)) return NULL; if (!PyArg_ParseTuple(args, "C|O:array", &c, &initial)) @@ -2611,7 +2634,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) "an array with typecode '%c'", c); return NULL; } - else if (array_Check(initial) && + else if (array_Check(initial, state) && ((arrayobject*)initial)->ob_descr->typecode == 'u') { PyErr_Format(PyExc_TypeError, "cannot use a unicode array to " "initialize an array with typecode '%c'", c); @@ -2624,7 +2647,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) || PyBytes_Check(initial) || PyTuple_Check(initial) || ((c=='u') && PyUnicode_Check(initial)) - || (array_Check(initial) + || (array_Check(initial, state) && c == ((arrayobject*)initial)->ob_descr->typecode))) { it = PyObject_GetIter(initial); if (it == NULL) @@ -2645,7 +2668,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) len = 0; else if (PyList_Check(initial)) len = PyList_GET_SIZE(initial); - else if (PyTuple_Check(initial) || array_Check(initial)) + else if (PyTuple_Check(initial) || array_Check(initial, state)) len = Py_SIZE(initial); else len = 0; @@ -2654,7 +2677,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (a == NULL) return NULL; - if (len > 0 && !array_Check(initial)) { + if (len > 0 && !array_Check(initial, state)) { Py_ssize_t i; for (i = 0; i < len; i++) { PyObject *v = @@ -2699,7 +2722,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) self->allocated = n; } } - else if (initial != NULL && array_Check(initial) && len > 0) { + else if (initial != NULL && array_Check(initial, state) && len > 0) { arrayobject *self = (arrayobject *)a; arrayobject *other = (arrayobject *)initial; memcpy(self->ob_item, other->ob_item, len * other->ob_descr->itemsize); @@ -2788,67 +2811,75 @@ itemsize -- the length in bytes of one array item\n\ static PyObject *array_iter(arrayobject *ao); -static PyTypeObject Arraytype = { - PyVarObject_HEAD_INIT(NULL, 0) - "array.array", - sizeof(arrayobject), - 0, - (destructor)array_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)array_repr, /* tp_repr */ - 0, /* tp_as_number*/ - &array_as_sequence, /* tp_as_sequence*/ - &array_as_mapping, /* tp_as_mapping*/ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - &array_as_buffer, /* tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - arraytype_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - array_richcompare, /* tp_richcompare */ - offsetof(arrayobject, weakreflist), /* tp_weaklistoffset */ - (getiterfunc)array_iter, /* tp_iter */ - 0, /* tp_iternext */ - array_methods, /* tp_methods */ - 0, /* tp_members */ - array_getsets, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - array_new, /* tp_new */ - PyObject_Del, /* tp_free */ +static struct PyMemberDef array_members[] = { + {"__weaklistoffset__", T_PYSSIZET, offsetof(arrayobject, weakreflist), READONLY}, + {NULL}, }; +static PyType_Slot array_slots[] = { + {Py_tp_dealloc, array_dealloc}, + {Py_tp_repr, array_repr}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, (void *)arraytype_doc}, + {Py_tp_richcompare, array_richcompare}, + {Py_tp_iter, array_iter}, + {Py_tp_methods, array_methods}, + {Py_tp_members, array_members}, + {Py_tp_getset, array_getsets}, + {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_new, array_new}, + {Py_tp_traverse, array_tp_traverse}, + + /* as sequence */ + {Py_sq_length, array_length}, + {Py_sq_concat, array_concat}, + {Py_sq_repeat, array_repeat}, + {Py_sq_item, array_item}, + {Py_sq_ass_item, array_ass_item}, + {Py_sq_contains, array_contains}, + {Py_sq_inplace_concat, array_inplace_concat}, + {Py_sq_inplace_repeat, array_inplace_repeat}, + + /* as mapping */ + {Py_mp_length, array_length}, + {Py_mp_subscript, array_subscr}, + {Py_mp_ass_subscript, array_ass_subscr}, + + /* as buffer */ + {Py_bf_getbuffer, array_buffer_getbuf}, + {Py_bf_releasebuffer, array_buffer_relbuf}, + + {0, NULL}, +}; + +static PyType_Spec array_spec = { + .name = "array.array", + .basicsize = sizeof(arrayobject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_SEQUENCE), + .slots = array_slots, +}; /*********************** Array Iterator **************************/ /*[clinic input] -class array.arrayiterator "arrayiterobject *" "&PyArrayIter_Type" +class array.arrayiterator "arrayiterobject *" "find_array_state_by_type(type)->ArrayIterType" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=5aefd2d74d8c8e30]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=fb46d5ef98dd95ff]*/ static PyObject * array_iter(arrayobject *ao) { + array_state *state = find_array_state_by_type(Py_TYPE(ao)); arrayiterobject *it; - if (!array_Check(ao)) { + if (!array_Check(ao, state)) { PyErr_BadInternalCall(); return NULL; } - it = PyObject_GC_New(arrayiterobject, &PyArrayIter_Type); + it = PyObject_GC_New(arrayiterobject, state->ArrayIterType); if (it == NULL) return NULL; @@ -2866,12 +2897,17 @@ arrayiter_next(arrayiterobject *it) arrayobject *ao; assert(it != NULL); - assert(PyArrayIter_Check(it)); +#ifndef NDEBUG + array_state *state = find_array_state_by_type(Py_TYPE(it)); + assert(PyObject_TypeCheck(it, state->ArrayIterType)); +#endif ao = it->ao; if (ao == NULL) { return NULL; } - assert(array_Check(ao)); +#ifndef NDEBUG + assert(array_Check(ao, state)); +#endif if (it->index < Py_SIZE(ao)) { return (*it->getitem)(ao, it->index++); } @@ -2883,14 +2919,18 @@ arrayiter_next(arrayiterobject *it) static void arrayiter_dealloc(arrayiterobject *it) { + PyTypeObject *tp = Py_TYPE(it); + PyObject_GC_UnTrack(it); Py_XDECREF(it->ao); PyObject_GC_Del(it); + Py_DECREF(tp); } static int arrayiter_traverse(arrayiterobject *it, visitproc visit, void *arg) { + Py_VISIT(Py_TYPE(it)); Py_VISIT(it->ao); return 0; } @@ -2943,66 +2983,104 @@ static PyMethodDef arrayiter_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject PyArrayIter_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "arrayiterator", /* tp_name */ - sizeof(arrayiterobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)arrayiter_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ - 0, /* tp_doc */ - (traverseproc)arrayiter_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)arrayiter_next, /* tp_iternext */ - arrayiter_methods, /* tp_methods */ +static PyType_Slot arrayiter_slots[] = { + {Py_tp_dealloc, arrayiter_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_traverse, arrayiter_traverse}, + {Py_tp_iter, PyObject_SelfIter}, + {Py_tp_iternext, arrayiter_next}, + {Py_tp_methods, arrayiter_methods}, + {0, NULL}, +}; + +static PyType_Spec arrayiter_spec = { + .name = "array.arrayiterator", + .basicsize = sizeof(arrayiterobject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE), + .slots = arrayiter_slots, }; /*********************** Install Module **************************/ +static int +array_traverse(PyObject *module, visitproc visit, void *arg) +{ + array_state *state = get_array_state(module); + Py_VISIT(state->ArrayType); + Py_VISIT(state->ArrayIterType); + return 0; +} + +static int +array_clear(PyObject *module) +{ + array_state *state = get_array_state(module); + Py_CLEAR(state->ArrayType); + Py_CLEAR(state->ArrayIterType); + return 0; +} + +static void +array_free(void *module) +{ + array_clear((PyObject *)module); +} + /* No functions in array module. */ static PyMethodDef a_methods[] = { ARRAY__ARRAY_RECONSTRUCTOR_METHODDEF {NULL, NULL, 0, NULL} /* Sentinel */ }; +#define CREATE_TYPE(module, type, spec) \ +do { \ + type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, NULL); \ + if (type == NULL) { \ + return -1; \ + } \ +} while (0) + static int array_modexec(PyObject *m) { + array_state *state = get_array_state(m); char buffer[Py_ARRAY_LENGTH(descriptors)], *p; PyObject *typecodes; const struct arraydescr *descr; - if (PyType_Ready(&Arraytype) < 0) + CREATE_TYPE(m, state->ArrayType, &array_spec); + CREATE_TYPE(m, state->ArrayIterType, &arrayiter_spec); + Py_SET_TYPE(state->ArrayIterType, &PyType_Type); + + Py_INCREF((PyObject *)state->ArrayType); + if (PyModule_AddObject(m, "ArrayType", (PyObject *)state->ArrayType) < 0) { + Py_DECREF((PyObject *)state->ArrayType); return -1; - Py_SET_TYPE(&PyArrayIter_Type, &PyType_Type); + } - Py_INCREF((PyObject *)&Arraytype); - if (PyModule_AddObject(m, "ArrayType", (PyObject *)&Arraytype) < 0) { - Py_DECREF((PyObject *)&Arraytype); + PyObject *abc_mod = PyImport_ImportModule("collections.abc"); + if (!abc_mod) { + Py_DECREF((PyObject *)state->ArrayType); + return -1; + } + PyObject *mutablesequence = PyObject_GetAttrString(abc_mod, "MutableSequence"); + Py_DECREF(abc_mod); + if (!mutablesequence) { + Py_DECREF((PyObject *)state->ArrayType); + return -1; + } + PyObject *res = PyObject_CallMethod(mutablesequence, "register", "O", + (PyObject *)state->ArrayType); + Py_DECREF(mutablesequence); + if (!res) { + Py_DECREF((PyObject *)state->ArrayType); return -1; } - Py_INCREF((PyObject *)&Arraytype); - if (PyModule_AddObject(m, "array", (PyObject *)&Arraytype) < 0) { - Py_DECREF((PyObject *)&Arraytype); + Py_DECREF(res); + + if (PyModule_AddType(m, state->ArrayType) < 0) { return -1; } @@ -3026,15 +3104,15 @@ static PyModuleDef_Slot arrayslots[] = { static struct PyModuleDef arraymodule = { - PyModuleDef_HEAD_INIT, - "array", - module_doc, - 0, - a_methods, - arrayslots, - NULL, - NULL, - NULL + .m_base = PyModuleDef_HEAD_INIT, + .m_name = "array", + .m_size = sizeof(array_state), + .m_doc = module_doc, + .m_methods = a_methods, + .m_slots = arrayslots, + .m_traverse = array_traverse, + .m_clear = array_clear, + .m_free = array_free, }; diff --git a/contrib/tools/python3/src/Modules/atexitmodule.c b/contrib/tools/python3/src/Modules/atexitmodule.c index 8cef64ceb9..95c653cf47 100644 --- a/contrib/tools/python3/src/Modules/atexitmodule.c +++ b/contrib/tools/python3/src/Modules/atexitmodule.c @@ -7,117 +7,122 @@ */ #include "Python.h" - -/* Forward declaration (for atexit_cleanup) */ -static PyObject *atexit_clear(PyObject*, PyObject*); -/* Forward declaration of module object */ -static struct PyModuleDef atexitmodule; +#include "pycore_initconfig.h" // _PyStatus_NO_MEMORY +#include "pycore_interp.h" // PyInterpreterState.atexit +#include "pycore_pystate.h" // _PyInterpreterState_GET /* ===================================================================== */ /* Callback machinery. */ -typedef struct { - PyObject *func; - PyObject *args; - PyObject *kwargs; -} atexit_callback; - -typedef struct { - atexit_callback **atexit_callbacks; - int ncallbacks; - int callback_len; -} atexitmodule_state; - -static inline atexitmodule_state* -get_atexit_state(PyObject *module) +static inline struct atexit_state* +get_atexit_state(void) { - void *state = PyModule_GetState(module); - assert(state != NULL); - return (atexitmodule_state *)state; + PyInterpreterState *interp = _PyInterpreterState_GET(); + return &interp->atexit; } static void -atexit_delete_cb(atexitmodule_state *modstate, int i) +atexit_delete_cb(struct atexit_state *state, int i) { - atexit_callback *cb; + atexit_callback *cb = state->callbacks[i]; + state->callbacks[i] = NULL; - cb = modstate->atexit_callbacks[i]; - modstate->atexit_callbacks[i] = NULL; Py_DECREF(cb->func); Py_DECREF(cb->args); Py_XDECREF(cb->kwargs); PyMem_Free(cb); } + /* Clear all callbacks without calling them */ static void -atexit_cleanup(atexitmodule_state *modstate) +atexit_cleanup(struct atexit_state *state) { atexit_callback *cb; - int i; - for (i = 0; i < modstate->ncallbacks; i++) { - cb = modstate->atexit_callbacks[i]; + for (int i = 0; i < state->ncallbacks; i++) { + cb = state->callbacks[i]; if (cb == NULL) continue; - atexit_delete_cb(modstate, i); + atexit_delete_cb(state, i); } - modstate->ncallbacks = 0; + state->ncallbacks = 0; } -/* Installed into pylifecycle.c's atexit mechanism */ -static void -atexit_callfuncs(PyObject *module) +PyStatus +_PyAtExit_Init(PyInterpreterState *interp) { - PyObject *exc_type = NULL, *exc_value, *exc_tb, *r; - atexit_callback *cb; - atexitmodule_state *modstate; - int i; + struct atexit_state *state = &interp->atexit; + // _PyAtExit_Init() must only be called once + assert(state->callbacks == NULL); + + state->callback_len = 32; + state->ncallbacks = 0; + state->callbacks = PyMem_New(atexit_callback*, state->callback_len); + if (state->callbacks == NULL) { + return _PyStatus_NO_MEMORY(); + } + return _PyStatus_OK(); +} - if (module == NULL) - return; - modstate = get_atexit_state(module); - if (modstate->ncallbacks == 0) - return; +void +_PyAtExit_Fini(PyInterpreterState *interp) +{ + struct atexit_state *state = &interp->atexit; + atexit_cleanup(state); + PyMem_Free(state->callbacks); + state->callbacks = NULL; +} - for (i = modstate->ncallbacks - 1; i >= 0; i--) - { - cb = modstate->atexit_callbacks[i]; - if (cb == NULL) +static void +atexit_callfuncs(struct atexit_state *state) +{ + assert(!PyErr_Occurred()); + + if (state->ncallbacks == 0) { + return; + } + + for (int i = state->ncallbacks - 1; i >= 0; i--) { + atexit_callback *cb = state->callbacks[i]; + if (cb == NULL) { continue; + } - r = PyObject_Call(cb->func, cb->args, cb->kwargs); - Py_XDECREF(r); - if (r == NULL) { - /* Maintain the last exception, but don't leak if there are - multiple exceptions. */ - if (exc_type) { - Py_DECREF(exc_type); - Py_XDECREF(exc_value); - Py_XDECREF(exc_tb); - } - PyErr_Fetch(&exc_type, &exc_value, &exc_tb); - if (!PyErr_GivenExceptionMatches(exc_type, PyExc_SystemExit)) { - PySys_WriteStderr("Error in atexit._run_exitfuncs:\n"); - PyErr_NormalizeException(&exc_type, &exc_value, &exc_tb); - PyErr_Display(exc_type, exc_value, exc_tb); - } + // bpo-46025: Increment the refcount of cb->func as the call itself may unregister it + PyObject* the_func = Py_NewRef(cb->func); + PyObject *res = PyObject_Call(cb->func, cb->args, cb->kwargs); + if (res == NULL) { + _PyErr_WriteUnraisableMsg("in atexit callback", the_func); } + else { + Py_DECREF(res); + } + Py_DECREF(the_func); } - atexit_cleanup(modstate); + atexit_cleanup(state); + + assert(!PyErr_Occurred()); +} + - if (exc_type) - PyErr_Restore(exc_type, exc_value, exc_tb); +void +_PyAtExit_Call(PyInterpreterState *interp) +{ + struct atexit_state *state = &interp->atexit; + atexit_callfuncs(state); } + /* ===================================================================== */ /* Module methods. */ + PyDoc_STRVAR(atexit_register__doc__, "register(func, *args, **kwargs) -> func\n\ \n\ @@ -130,68 +135,63 @@ Register a function to be executed upon normal program termination\n\ func is returned to facilitate usage as a decorator."); static PyObject * -atexit_register(PyObject *self, PyObject *args, PyObject *kwargs) +atexit_register(PyObject *module, PyObject *args, PyObject *kwargs) { - atexitmodule_state *modstate; - atexit_callback *new_callback; - PyObject *func = NULL; - - modstate = get_atexit_state(self); - - if (modstate->ncallbacks >= modstate->callback_len) { - atexit_callback **r; - modstate->callback_len += 16; - r = (atexit_callback**)PyMem_Realloc(modstate->atexit_callbacks, - sizeof(atexit_callback*) * modstate->callback_len); - if (r == NULL) - return PyErr_NoMemory(); - modstate->atexit_callbacks = r; - } - if (PyTuple_GET_SIZE(args) == 0) { PyErr_SetString(PyExc_TypeError, "register() takes at least 1 argument (0 given)"); return NULL; } - func = PyTuple_GET_ITEM(args, 0); + PyObject *func = PyTuple_GET_ITEM(args, 0); if (!PyCallable_Check(func)) { PyErr_SetString(PyExc_TypeError, "the first argument must be callable"); return NULL; } - new_callback = PyMem_Malloc(sizeof(atexit_callback)); - if (new_callback == NULL) + struct atexit_state *state = get_atexit_state(); + if (state->ncallbacks >= state->callback_len) { + atexit_callback **r; + state->callback_len += 16; + size_t size = sizeof(atexit_callback*) * (size_t)state->callback_len; + r = (atexit_callback**)PyMem_Realloc(state->callbacks, size); + if (r == NULL) { + return PyErr_NoMemory(); + } + state->callbacks = r; + } + + atexit_callback *callback = PyMem_Malloc(sizeof(atexit_callback)); + if (callback == NULL) { return PyErr_NoMemory(); + } - new_callback->args = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args)); - if (new_callback->args == NULL) { - PyMem_Free(new_callback); + callback->args = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args)); + if (callback->args == NULL) { + PyMem_Free(callback); return NULL; } - new_callback->func = func; - new_callback->kwargs = kwargs; - Py_INCREF(func); - Py_XINCREF(kwargs); + callback->func = Py_NewRef(func); + callback->kwargs = Py_XNewRef(kwargs); - modstate->atexit_callbacks[modstate->ncallbacks++] = new_callback; + state->callbacks[state->ncallbacks++] = callback; - Py_INCREF(func); - return func; + return Py_NewRef(func); } PyDoc_STRVAR(atexit_run_exitfuncs__doc__, "_run_exitfuncs() -> None\n\ \n\ -Run all registered exit functions."); +Run all registered exit functions.\n\ +\n\ +If a callaback raises an exception, it is logged with sys.unraisablehook."); static PyObject * -atexit_run_exitfuncs(PyObject *self, PyObject *unused) +atexit_run_exitfuncs(PyObject *module, PyObject *unused) { - atexit_callfuncs(self); - if (PyErr_Occurred()) - return NULL; + struct atexit_state *state = get_atexit_state(); + atexit_callfuncs(state); Py_RETURN_NONE; } @@ -201,9 +201,9 @@ PyDoc_STRVAR(atexit_clear__doc__, Clear the list of previously registered exit functions."); static PyObject * -atexit_clear(PyObject *self, PyObject *unused) +atexit_clear(PyObject *module, PyObject *unused) { - atexit_cleanup(get_atexit_state(self)); + atexit_cleanup(get_atexit_state()); Py_RETURN_NONE; } @@ -213,50 +213,10 @@ PyDoc_STRVAR(atexit_ncallbacks__doc__, Return the number of registered exit functions."); static PyObject * -atexit_ncallbacks(PyObject *self, PyObject *unused) -{ - atexitmodule_state *modstate; - - modstate = get_atexit_state(self); - - return PyLong_FromSsize_t(modstate->ncallbacks); -} - -static int -atexit_m_traverse(PyObject *self, visitproc visit, void *arg) -{ - int i; - atexitmodule_state *modstate; - - modstate = (atexitmodule_state *)PyModule_GetState(self); - - for (i = 0; i < modstate->ncallbacks; i++) { - atexit_callback *cb = modstate->atexit_callbacks[i]; - if (cb == NULL) - continue; - Py_VISIT(cb->func); - Py_VISIT(cb->args); - Py_VISIT(cb->kwargs); - } - return 0; -} - -static int -atexit_m_clear(PyObject *self) +atexit_ncallbacks(PyObject *module, PyObject *unused) { - atexitmodule_state *modstate; - modstate = (atexitmodule_state *)PyModule_GetState(self); - atexit_cleanup(modstate); - return 0; -} - -static void -atexit_free(PyObject *m) -{ - atexitmodule_state *modstate; - modstate = (atexitmodule_state *)PyModule_GetState(m); - atexit_cleanup(modstate); - PyMem_Free(modstate->atexit_callbacks); + struct atexit_state *state = get_atexit_state(); + return PyLong_FromSsize_t(state->ncallbacks); } PyDoc_STRVAR(atexit_unregister__doc__, @@ -268,29 +228,28 @@ atexit.register\n\ func - function to be unregistered"); static PyObject * -atexit_unregister(PyObject *self, PyObject *func) +atexit_unregister(PyObject *module, PyObject *func) { - atexitmodule_state *modstate; - atexit_callback *cb; - int i, eq; - - modstate = get_atexit_state(self); - - for (i = 0; i < modstate->ncallbacks; i++) + struct atexit_state *state = get_atexit_state(); + for (int i = 0; i < state->ncallbacks; i++) { - cb = modstate->atexit_callbacks[i]; - if (cb == NULL) + atexit_callback *cb = state->callbacks[i]; + if (cb == NULL) { continue; + } - eq = PyObject_RichCompareBool(cb->func, func, Py_EQ); - if (eq < 0) + int eq = PyObject_RichCompareBool(cb->func, func, Py_EQ); + if (eq < 0) { return NULL; - if (eq) - atexit_delete_cb(modstate, i); + } + if (eq) { + atexit_delete_cb(state, i); + } } Py_RETURN_NONE; } + static PyMethodDef atexit_methods[] = { {"register", (PyCFunction)(void(*)(void)) atexit_register, METH_VARARGS|METH_KEYWORDS, atexit_register__doc__}, @@ -305,47 +264,23 @@ static PyMethodDef atexit_methods[] = { {NULL, NULL} /* sentinel */ }; + /* ===================================================================== */ /* Initialization function. */ PyDoc_STRVAR(atexit__doc__, -"allow programmer to define multiple exit functions to be executed\ +"allow programmer to define multiple exit functions to be executed\n\ upon normal program termination.\n\ \n\ Two public functions, register and unregister, are defined.\n\ "); -static int -atexit_exec(PyObject *m) { - atexitmodule_state *modstate; - - modstate = get_atexit_state(m); - modstate->callback_len = 32; - modstate->ncallbacks = 0; - modstate->atexit_callbacks = PyMem_New(atexit_callback*, - modstate->callback_len); - if (modstate->atexit_callbacks == NULL) - return -1; - - _Py_PyAtExit(atexit_callfuncs, m); - return 0; -} - -static PyModuleDef_Slot atexit_slots[] = { - {Py_mod_exec, atexit_exec}, - {0, NULL} -}; - static struct PyModuleDef atexitmodule = { PyModuleDef_HEAD_INIT, - "atexit", - atexit__doc__, - sizeof(atexitmodule_state), - atexit_methods, - atexit_slots, - atexit_m_traverse, - atexit_m_clear, - (freefunc)atexit_free + .m_name = "atexit", + .m_doc = atexit__doc__, + .m_size = 0, + .m_methods = atexit_methods, }; PyMODINIT_FUNC diff --git a/contrib/tools/python3/src/Modules/cjkcodecs/cjkcodecs.h b/contrib/tools/python3/src/Modules/cjkcodecs/cjkcodecs.h index e41755b197..ba8fad2605 100644 --- a/contrib/tools/python3/src/Modules/cjkcodecs/cjkcodecs.h +++ b/contrib/tools/python3/src/Modules/cjkcodecs/cjkcodecs.h @@ -245,15 +245,13 @@ static const struct dbcs_map *mapping_list; static PyObject * getmultibytecodec(void) { - static PyObject *cofunc = NULL; - - if (cofunc == NULL) { - PyObject *mod = PyImport_ImportModuleNoBlock("_multibytecodec"); - if (mod == NULL) - return NULL; - cofunc = PyObject_GetAttrString(mod, "__create_codec"); - Py_DECREF(mod); + PyObject *mod = PyImport_ImportModuleNoBlock("_multibytecodec"); + if (mod == NULL) { + return NULL; } + + PyObject *cofunc = PyObject_GetAttrString(mod, "__create_codec"); + Py_DECREF(mod); return cofunc; } @@ -293,14 +291,11 @@ getcodec(PyObject *self, PyObject *encoding) r = PyObject_CallOneArg(cofunc, codecobj); Py_DECREF(codecobj); + Py_DECREF(cofunc); return r; } -static struct PyMethodDef __methods[] = { - {"getcodec", (PyCFunction)getcodec, METH_O, ""}, - {NULL, NULL}, -}; static int register_maps(PyObject *module) @@ -309,12 +304,17 @@ register_maps(PyObject *module) for (h = mapping_list; h->charset[0] != '\0'; h++) { char mhname[256] = "__map_"; - int r; strcpy(mhname + sizeof("__map_") - 1, h->charset); - r = PyModule_AddObject(module, mhname, - PyCapsule_New((void *)h, PyMultibyteCodec_CAPSULE_NAME, NULL)); - if (r == -1) + + PyObject *capsule = PyCapsule_New((void *)h, + PyMultibyteCodec_CAPSULE_NAME, NULL); + if (capsule == NULL) { + return -1; + } + if (PyModule_AddObject(module, mhname, capsule) < 0) { + Py_DECREF(capsule); return -1; + } } return 0; } @@ -395,25 +395,36 @@ errorexit: } #endif +static int +_cjk_exec(PyObject *module) +{ + return register_maps(module); +} + + +static struct PyMethodDef _cjk_methods[] = { + {"getcodec", (PyCFunction)getcodec, METH_O, ""}, + {NULL, NULL}, +}; + +static PyModuleDef_Slot _cjk_slots[] = { + {Py_mod_exec, _cjk_exec}, + {0, NULL} +}; + #define I_AM_A_MODULE_FOR(loc) \ - static struct PyModuleDef __module = { \ + static struct PyModuleDef _cjk_module = { \ PyModuleDef_HEAD_INIT, \ - "_codecs_"#loc, \ - NULL, \ - 0, \ - __methods, \ - NULL, \ - NULL, \ - NULL, \ - NULL \ + .m_name = "_codecs_"#loc, \ + .m_size = 0, \ + .m_methods = _cjk_methods, \ + .m_slots = _cjk_slots, \ }; \ + \ PyMODINIT_FUNC \ PyInit__codecs_##loc(void) \ { \ - PyObject *m = PyModule_Create(&__module); \ - if (m != NULL) \ - (void)register_maps(m); \ - return m; \ + return PyModuleDef_Init(&_cjk_module); \ } #endif diff --git a/contrib/tools/python3/src/Modules/cjkcodecs/clinic/multibytecodec.c.h b/contrib/tools/python3/src/Modules/cjkcodecs/clinic/multibytecodec.c.h index 5ddbbe221b..563888370d 100644 --- a/contrib/tools/python3/src/Modules/cjkcodecs/clinic/multibytecodec.c.h +++ b/contrib/tools/python3/src/Modules/cjkcodecs/clinic/multibytecodec.c.h @@ -171,11 +171,6 @@ _multibytecodec_MultibyteIncrementalEncoder_encode(MultibyteIncrementalEncoderOb if (!noptargs) { goto skip_optional_pos; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } final = _PyLong_AsInt(args[1]); if (final == -1 && PyErr_Occurred()) { goto exit; @@ -288,11 +283,6 @@ _multibytecodec_MultibyteIncrementalDecoder_decode(MultibyteIncrementalDecoderOb if (!noptargs) { goto skip_optional_pos; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } final = _PyLong_AsInt(args[1]); if (final == -1 && PyErr_Occurred()) { goto exit; @@ -525,4 +515,4 @@ PyDoc_STRVAR(_multibytecodec___create_codec__doc__, #define _MULTIBYTECODEC___CREATE_CODEC_METHODDEF \ {"__create_codec", (PyCFunction)_multibytecodec___create_codec, METH_O, _multibytecodec___create_codec__doc__}, -/*[clinic end generated code: output=5ce6fd4ca1f95620 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5c0f74129db07c87 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/cjkcodecs/multibytecodec.c b/contrib/tools/python3/src/Modules/cjkcodecs/multibytecodec.c index 86402768b6..ba558d0dbf 100644 --- a/contrib/tools/python3/src/Modules/cjkcodecs/multibytecodec.c +++ b/contrib/tools/python3/src/Modules/cjkcodecs/multibytecodec.c @@ -10,11 +10,44 @@ #include "multibytecodec.h" #include "clinic/multibytecodec.c.h" +#define MODULE_NAME "_multibytecodec" + +typedef struct { + PyTypeObject *encoder_type; + PyTypeObject *decoder_type; + PyTypeObject *reader_type; + PyTypeObject *writer_type; + PyTypeObject *multibytecodec_type; +} _multibytecodec_state; + +static _multibytecodec_state * +_multibytecodec_get_state(PyObject *module) +{ + _multibytecodec_state *state = PyModule_GetState(module); + assert(state != NULL); + return state; +} + +static struct PyModuleDef _multibytecodecmodule; +static _multibytecodec_state * +_multibyte_codec_find_state_by_type(PyTypeObject *type) +{ + PyObject *module = _PyType_GetModuleByDef(type, &_multibytecodecmodule); + assert(module != NULL); + return _multibytecodec_get_state(module); +} + +#define clinic_get_state() _multibyte_codec_find_state_by_type(type) /*[clinic input] module _multibytecodec -class _multibytecodec.MultibyteCodec "MultibyteCodecObject *" "&MultibyteCodec_Type" +class _multibytecodec.MultibyteCodec "MultibyteCodecObject *" "clinic_get_state()->multibytecodec_type" +class _multibytecodec.MultibyteIncrementalEncoder "MultibyteIncrementalEncoderObject *" "clinic_get_state()->encoder_type" +class _multibytecodec.MultibyteIncrementalDecoder "MultibyteIncrementalDecoderObject *" "clinic_get_state()->decoder_type" +class _multibytecodec.MultibyteStreamReader "MultibyteStreamReaderObject *" "clinic_get_state()->reader_type" +class _multibytecodec.MultibyteStreamWriter "MultibyteStreamWriterObject *" "clinic_get_state()->writer_type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=6ad689546cbb5450]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=305a76dfdd24b99c]*/ +#undef clinic_get_state typedef struct { PyObject *inobj; @@ -688,42 +721,36 @@ static struct PyMethodDef multibytecodec_methods[] = { {NULL, NULL}, }; +static int +multibytecodec_traverse(PyObject *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + return 0; +} + static void multibytecodec_dealloc(MultibyteCodecObject *self) { - PyObject_Del(self); + PyObject_GC_UnTrack(self); + PyTypeObject *tp = Py_TYPE(self); + tp->tp_free(self); + Py_DECREF(tp); } -static PyTypeObject MultibyteCodec_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "MultibyteCodec", /* tp_name */ - sizeof(MultibyteCodecObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)multibytecodec_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iterext */ - multibytecodec_methods, /* tp_methods */ +static PyType_Slot multibytecodec_slots[] = { + {Py_tp_dealloc, multibytecodec_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_methods, multibytecodec_methods}, + {Py_tp_traverse, multibytecodec_traverse}, + {0, NULL}, +}; + +static PyType_Spec multibytecodec_spec = { + .name = MODULE_NAME ".MultibyteCodec", + .basicsize = sizeof(MultibyteCodecObject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE), + .slots = multibytecodec_slots, }; @@ -869,11 +896,6 @@ decoder_feed_buffer(MultibyteStatefulDecoderContext *ctx, /*[clinic input] - class _multibytecodec.MultibyteIncrementalEncoder "MultibyteIncrementalEncoderObject *" "&MultibyteIncrementalEncoder_Type" -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3be82909cd08924d]*/ - -/*[clinic input] _multibytecodec.MultibyteIncrementalEncoder.encode input: object @@ -1024,7 +1046,9 @@ mbiencoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds) codec = PyObject_GetAttrString((PyObject *)type, "codec"); if (codec == NULL) goto errorexit; - if (!MultibyteCodec_Check(codec)) { + + _multibytecodec_state *state = _multibyte_codec_find_state_by_type(type); + if (!MultibyteCodec_Check(state, codec)) { PyErr_SetString(PyExc_TypeError, "codec is unexpected type"); goto errorexit; } @@ -1065,60 +1089,33 @@ mbiencoder_traverse(MultibyteIncrementalEncoderObject *self, static void mbiencoder_dealloc(MultibyteIncrementalEncoderObject *self) { + PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(self); ERROR_DECREF(self->errors); Py_CLEAR(self->pending); - Py_TYPE(self)->tp_free(self); + tp->tp_free(self); + Py_DECREF(tp); } -static PyTypeObject MultibyteIncrementalEncoder_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "MultibyteIncrementalEncoder", /* tp_name */ - sizeof(MultibyteIncrementalEncoderObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)mbiencoder_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC - | Py_TPFLAGS_BASETYPE, /* tp_flags */ - 0, /* tp_doc */ - (traverseproc)mbiencoder_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iterext */ - mbiencoder_methods, /* tp_methods */ - 0, /* tp_members */ - codecctx_getsets, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - mbiencoder_init, /* tp_init */ - 0, /* tp_alloc */ - mbiencoder_new, /* tp_new */ +static PyType_Slot encoder_slots[] = { + {Py_tp_dealloc, mbiencoder_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_traverse, mbiencoder_traverse}, + {Py_tp_methods, mbiencoder_methods}, + {Py_tp_getset, codecctx_getsets}, + {Py_tp_init, mbiencoder_init}, + {Py_tp_new, mbiencoder_new}, + {0, NULL}, }; +static PyType_Spec encoder_spec = { + .name = MODULE_NAME ".MultibyteIncrementalEncoder", + .basicsize = sizeof(MultibyteIncrementalEncoderObject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = encoder_slots, +}; -/*[clinic input] - class _multibytecodec.MultibyteIncrementalDecoder "MultibyteIncrementalDecoderObject *" "&MultibyteIncrementalDecoder_Type" -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f6003faaf2cea692]*/ /*[clinic input] _multibytecodec.MultibyteIncrementalDecoder.decode @@ -1191,13 +1188,13 @@ _multibytecodec_MultibyteIncrementalDecoder_decode_impl(MultibyteIncrementalDeco goto errorexit; if (wdata != data) - PyMem_Del(wdata); + PyMem_Free(wdata); Py_XDECREF(buf.excobj); return res; errorexit: if (wdata != NULL && wdata != data) - PyMem_Del(wdata); + PyMem_Free(wdata); Py_XDECREF(buf.excobj); _PyUnicodeWriter_Dealloc(&buf.writer); return NULL; @@ -1324,7 +1321,9 @@ mbidecoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds) codec = PyObject_GetAttrString((PyObject *)type, "codec"); if (codec == NULL) goto errorexit; - if (!MultibyteCodec_Check(codec)) { + + _multibytecodec_state *state = _multibyte_codec_find_state_by_type(type); + if (!MultibyteCodec_Check(state, codec)) { PyErr_SetString(PyExc_TypeError, "codec is unexpected type"); goto errorexit; } @@ -1365,59 +1364,31 @@ mbidecoder_traverse(MultibyteIncrementalDecoderObject *self, static void mbidecoder_dealloc(MultibyteIncrementalDecoderObject *self) { + PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(self); ERROR_DECREF(self->errors); - Py_TYPE(self)->tp_free(self); + tp->tp_free(self); + Py_DECREF(tp); } -static PyTypeObject MultibyteIncrementalDecoder_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "MultibyteIncrementalDecoder", /* tp_name */ - sizeof(MultibyteIncrementalDecoderObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)mbidecoder_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC - | Py_TPFLAGS_BASETYPE, /* tp_flags */ - 0, /* tp_doc */ - (traverseproc)mbidecoder_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iterext */ - mbidecoder_methods, /* tp_methods */ - 0, /* tp_members */ - codecctx_getsets, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - mbidecoder_init, /* tp_init */ - 0, /* tp_alloc */ - mbidecoder_new, /* tp_new */ +static PyType_Slot decoder_slots[] = { + {Py_tp_dealloc, mbidecoder_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_traverse, mbidecoder_traverse}, + {Py_tp_methods, mbidecoder_methods}, + {Py_tp_getset, codecctx_getsets}, + {Py_tp_init, mbidecoder_init}, + {Py_tp_new, mbidecoder_new}, + {0, NULL}, }; - -/*[clinic input] - class _multibytecodec.MultibyteStreamReader "MultibyteStreamReaderObject *" "MultibyteStreamReader_Type" -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d323634b74976f09]*/ +static PyType_Spec decoder_spec = { + .name = MODULE_NAME ".MultibyteIncrementalDecoder", + .basicsize = sizeof(MultibyteIncrementalDecoderObject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = decoder_slots, +}; static PyObject * mbstreamreader_iread(MultibyteStreamReaderObject *self, @@ -1667,7 +1638,9 @@ mbstreamreader_new(PyTypeObject *type, PyObject *args, PyObject *kwds) codec = PyObject_GetAttrString((PyObject *)type, "codec"); if (codec == NULL) goto errorexit; - if (!MultibyteCodec_Check(codec)) { + + _multibytecodec_state *state = _multibyte_codec_find_state_by_type(type); + if (!MultibyteCodec_Check(state, codec)) { PyErr_SetString(PyExc_TypeError, "codec is unexpected type"); goto errorexit; } @@ -1711,60 +1684,33 @@ mbstreamreader_traverse(MultibyteStreamReaderObject *self, static void mbstreamreader_dealloc(MultibyteStreamReaderObject *self) { + PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(self); ERROR_DECREF(self->errors); Py_XDECREF(self->stream); - Py_TYPE(self)->tp_free(self); + tp->tp_free(self); + Py_DECREF(tp); } -static PyTypeObject MultibyteStreamReader_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "MultibyteStreamReader", /* tp_name */ - sizeof(MultibyteStreamReaderObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)mbstreamreader_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC - | Py_TPFLAGS_BASETYPE, /* tp_flags */ - 0, /* tp_doc */ - (traverseproc)mbstreamreader_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iterext */ - mbstreamreader_methods, /* tp_methods */ - mbstreamreader_members, /* tp_members */ - codecctx_getsets, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - mbstreamreader_init, /* tp_init */ - 0, /* tp_alloc */ - mbstreamreader_new, /* tp_new */ +static PyType_Slot reader_slots[] = { + {Py_tp_dealloc, mbstreamreader_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_traverse, mbstreamreader_traverse}, + {Py_tp_methods, mbstreamreader_methods}, + {Py_tp_members, mbstreamreader_members}, + {Py_tp_getset, codecctx_getsets}, + {Py_tp_init, mbstreamreader_init}, + {Py_tp_new, mbstreamreader_new}, + {0, NULL}, }; - -/*[clinic input] - class _multibytecodec.MultibyteStreamWriter "MultibyteStreamWriterObject *" "&MultibyteStreamWriter_Type" -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=cde22780a215d6ac]*/ +static PyType_Spec reader_spec = { + .name = MODULE_NAME ".MultibyteStreamReader", + .basicsize = sizeof(MultibyteStreamReaderObject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = reader_slots, +}; static int mbstreamwriter_iwrite(MultibyteStreamWriterObject *self, @@ -1899,7 +1845,9 @@ mbstreamwriter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) codec = PyObject_GetAttrString((PyObject *)type, "codec"); if (codec == NULL) goto errorexit; - if (!MultibyteCodec_Check(codec)) { + + _multibytecodec_state *state = _multibyte_codec_find_state_by_type(type); + if (!MultibyteCodec_Check(state, codec)) { PyErr_SetString(PyExc_TypeError, "codec is unexpected type"); goto errorexit; } @@ -1943,10 +1891,12 @@ mbstreamwriter_traverse(MultibyteStreamWriterObject *self, static void mbstreamwriter_dealloc(MultibyteStreamWriterObject *self) { + PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(self); ERROR_DECREF(self->errors); Py_XDECREF(self->stream); - Py_TYPE(self)->tp_free(self); + tp->tp_free(self); + Py_DECREF(tp); } static struct PyMethodDef mbstreamwriter_methods[] = { @@ -1963,47 +1913,24 @@ static PyMemberDef mbstreamwriter_members[] = { {NULL,} }; -static PyTypeObject MultibyteStreamWriter_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "MultibyteStreamWriter", /* tp_name */ - sizeof(MultibyteStreamWriterObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)mbstreamwriter_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC - | Py_TPFLAGS_BASETYPE, /* tp_flags */ - 0, /* tp_doc */ - (traverseproc)mbstreamwriter_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iterext */ - mbstreamwriter_methods, /* tp_methods */ - mbstreamwriter_members, /* tp_members */ - codecctx_getsets, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - mbstreamwriter_init, /* tp_init */ - 0, /* tp_alloc */ - mbstreamwriter_new, /* tp_new */ +static PyType_Slot writer_slots[] = { + {Py_tp_dealloc, mbstreamwriter_dealloc}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_traverse, mbstreamwriter_traverse}, + {Py_tp_methods, mbstreamwriter_methods}, + {Py_tp_members, mbstreamwriter_members}, + {Py_tp_getset, codecctx_getsets}, + {Py_tp_init, mbstreamwriter_init}, + {Py_tp_new, mbstreamwriter_new}, + {0, NULL}, +}; + +static PyType_Spec writer_spec = { + .name = MODULE_NAME ".MultibyteStreamWriter", + .basicsize = sizeof(MultibyteStreamWriterObject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_IMMUTABLETYPE), + .slots = writer_slots, }; @@ -2030,59 +1957,104 @@ _multibytecodec___create_codec(PyObject *module, PyObject *arg) if (codec->codecinit != NULL && codec->codecinit(codec->config) != 0) return NULL; - self = PyObject_New(MultibyteCodecObject, &MultibyteCodec_Type); + _multibytecodec_state *state = _multibytecodec_get_state(module); + self = PyObject_GC_New(MultibyteCodecObject, state->multibytecodec_type); if (self == NULL) return NULL; self->codec = codec; + PyObject_GC_Track(self); return (PyObject *)self; } -static struct PyMethodDef __methods[] = { +static int +_multibytecodec_traverse(PyObject *mod, visitproc visit, void *arg) +{ + _multibytecodec_state *state = _multibytecodec_get_state(mod); + Py_VISIT(state->multibytecodec_type); + Py_VISIT(state->encoder_type); + Py_VISIT(state->decoder_type); + Py_VISIT(state->reader_type); + Py_VISIT(state->writer_type); + return 0; +} + +static int +_multibytecodec_clear(PyObject *mod) +{ + _multibytecodec_state *state = _multibytecodec_get_state(mod); + Py_CLEAR(state->multibytecodec_type); + Py_CLEAR(state->encoder_type); + Py_CLEAR(state->decoder_type); + Py_CLEAR(state->reader_type); + Py_CLEAR(state->writer_type); + return 0; +} + +static void +_multibytecodec_free(void *mod) +{ + _multibytecodec_clear((PyObject *)mod); +} + +#define CREATE_TYPE(module, type, spec) \ + do { \ + type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, NULL); \ + if (!type) { \ + return -1; \ + } \ + } while (0) + +#define ADD_TYPE(module, type) \ + do { \ + if (PyModule_AddType(module, type) < 0) { \ + return -1; \ + } \ + } while (0) + +static int +_multibytecodec_exec(PyObject *mod) +{ + _multibytecodec_state *state = _multibytecodec_get_state(mod); + CREATE_TYPE(mod, state->multibytecodec_type, &multibytecodec_spec); + CREATE_TYPE(mod, state->encoder_type, &encoder_spec); + CREATE_TYPE(mod, state->decoder_type, &decoder_spec); + CREATE_TYPE(mod, state->reader_type, &reader_spec); + CREATE_TYPE(mod, state->writer_type, &writer_spec); + + ADD_TYPE(mod, state->encoder_type); + ADD_TYPE(mod, state->decoder_type); + ADD_TYPE(mod, state->reader_type); + ADD_TYPE(mod, state->writer_type); + return 0; +} + +#undef CREATE_TYPE +#undef ADD_TYPE + +static struct PyMethodDef _multibytecodec_methods[] = { _MULTIBYTECODEC___CREATE_CODEC_METHODDEF {NULL, NULL}, }; +static PyModuleDef_Slot _multibytecodec_slots[] = { + {Py_mod_exec, _multibytecodec_exec}, + {0, NULL} +}; static struct PyModuleDef _multibytecodecmodule = { - PyModuleDef_HEAD_INIT, - "_multibytecodec", - NULL, - -1, - __methods, - NULL, - NULL, - NULL, - NULL + .m_base = PyModuleDef_HEAD_INIT, + .m_name = "_multibytecodec", + .m_size = sizeof(_multibytecodec_state), + .m_methods = _multibytecodec_methods, + .m_slots = _multibytecodec_slots, + .m_traverse = _multibytecodec_traverse, + .m_clear = _multibytecodec_clear, + .m_free = _multibytecodec_free, }; PyMODINIT_FUNC PyInit__multibytecodec(void) { - PyObject *m; - PyTypeObject *typelist[] = { - &MultibyteIncrementalEncoder_Type, - &MultibyteIncrementalDecoder_Type, - &MultibyteStreamReader_Type, - &MultibyteStreamWriter_Type - }; - - if (PyType_Ready(&MultibyteCodec_Type) < 0) - return NULL; - - m = PyModule_Create(&_multibytecodecmodule); - if (m == NULL) - return NULL; - - for (size_t i = 0; i < Py_ARRAY_LENGTH(typelist); i++) { - if (PyModule_AddType(m, typelist[i]) < 0) { - return NULL; - } - } - - if (PyErr_Occurred()) { - Py_DECREF(m); - m = NULL; - } - return m; + return PyModuleDef_Init(&_multibytecodecmodule); } diff --git a/contrib/tools/python3/src/Modules/cjkcodecs/multibytecodec.h b/contrib/tools/python3/src/Modules/cjkcodecs/multibytecodec.h index 59468210b9..69404ba96a 100644 --- a/contrib/tools/python3/src/Modules/cjkcodecs/multibytecodec.h +++ b/contrib/tools/python3/src/Modules/cjkcodecs/multibytecodec.h @@ -65,7 +65,7 @@ typedef struct { MultibyteCodec *codec; } MultibyteCodecObject; -#define MultibyteCodec_Check(op) Py_IS_TYPE((op), &MultibyteCodec_Type) +#define MultibyteCodec_Check(state, op) Py_IS_TYPE((op), state->multibytecodec_type) #define _MultibyteStatefulCodec_HEAD \ PyObject_HEAD \ diff --git a/contrib/tools/python3/src/Modules/clinic/_asynciomodule.c.h b/contrib/tools/python3/src/Modules/clinic/_asynciomodule.c.h index a071efc1e2..c472e652fb 100644 --- a/contrib/tools/python3/src/Modules/clinic/_asynciomodule.c.h +++ b/contrib/tools/python3/src/Modules/clinic/_asynciomodule.c.h @@ -669,6 +669,45 @@ _asyncio_get_event_loop(PyObject *module, PyObject *Py_UNUSED(ignored)) return _asyncio_get_event_loop_impl(module); } +PyDoc_STRVAR(_asyncio__get_event_loop__doc__, +"_get_event_loop($module, /, stacklevel=3)\n" +"--\n" +"\n"); + +#define _ASYNCIO__GET_EVENT_LOOP_METHODDEF \ + {"_get_event_loop", (PyCFunction)(void(*)(void))_asyncio__get_event_loop, METH_FASTCALL|METH_KEYWORDS, _asyncio__get_event_loop__doc__}, + +static PyObject * +_asyncio__get_event_loop_impl(PyObject *module, int stacklevel); + +static PyObject * +_asyncio__get_event_loop(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"stacklevel", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "_get_event_loop", 0}; + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + int stacklevel = 3; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + stacklevel = _PyLong_AsInt(args[0]); + if (stacklevel == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_pos: + return_value = _asyncio__get_event_loop_impl(module, stacklevel); + +exit: + return return_value; +} + PyDoc_STRVAR(_asyncio_get_running_loop__doc__, "get_running_loop($module, /)\n" "--\n" @@ -832,4 +871,4 @@ _asyncio__leave_task(PyObject *module, PyObject *const *args, Py_ssize_t nargs, exit: return return_value; } -/*[clinic end generated code: output=d0fc522bcbff9d61 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0d127162ac92e0c0 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/_bisectmodule.c.h b/contrib/tools/python3/src/Modules/clinic/_bisectmodule.c.h index 80ab7048f1..f118f4bbf8 100644 --- a/contrib/tools/python3/src/Modules/clinic/_bisectmodule.c.h +++ b/contrib/tools/python3/src/Modules/clinic/_bisectmodule.c.h @@ -3,14 +3,14 @@ preserve [clinic start generated code]*/ PyDoc_STRVAR(_bisect_bisect_right__doc__, -"bisect_right($module, /, a, x, lo=0, hi=None)\n" +"bisect_right($module, /, a, x, lo=0, hi=None, *, key=None)\n" "--\n" "\n" "Return the index where to insert item x in list a, assuming a is sorted.\n" "\n" "The return value i is such that all e in a[:i] have e <= x, and all e in\n" -"a[i:] have e > x. So if x already appears in the list, i points just\n" -"beyond the rightmost x already there\n" +"a[i:] have e > x. So if x already appears in the list, a.insert(i, x) will\n" +"insert just after the rightmost x already there.\n" "\n" "Optional args lo (default 0) and hi (default len(a)) bound the\n" "slice of a to be searched."); @@ -20,20 +20,21 @@ PyDoc_STRVAR(_bisect_bisect_right__doc__, static Py_ssize_t _bisect_bisect_right_impl(PyObject *module, PyObject *a, PyObject *x, - Py_ssize_t lo, Py_ssize_t hi); + Py_ssize_t lo, Py_ssize_t hi, PyObject *key); static PyObject * _bisect_bisect_right(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; - static const char * const _keywords[] = {"a", "x", "lo", "hi", NULL}; + static const char * const _keywords[] = {"a", "x", "lo", "hi", "key", NULL}; static _PyArg_Parser _parser = {NULL, _keywords, "bisect_right", 0}; - PyObject *argsbuf[4]; + PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; PyObject *a; PyObject *x; Py_ssize_t lo = 0; Py_ssize_t hi = -1; + PyObject *key = Py_None; Py_ssize_t _return_value; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 4, 0, argsbuf); @@ -46,14 +47,9 @@ _bisect_bisect_right(PyObject *module, PyObject *const *args, Py_ssize_t nargs, goto skip_optional_pos; } if (args[2]) { - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[2]); + PyObject *iobj = _PyNumber_Index(args[2]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -67,11 +63,21 @@ _bisect_bisect_right(PyObject *module, PyObject *const *args, Py_ssize_t nargs, goto skip_optional_pos; } } - if (!_Py_convert_optional_to_ssize_t(args[3], &hi)) { - goto exit; + if (args[3]) { + if (!_Py_convert_optional_to_ssize_t(args[3], &hi)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } } skip_optional_pos: - _return_value = _bisect_bisect_right_impl(module, a, x, lo, hi); + if (!noptargs) { + goto skip_optional_kwonly; + } + key = args[4]; +skip_optional_kwonly: + _return_value = _bisect_bisect_right_impl(module, a, x, lo, hi, key); if ((_return_value == -1) && PyErr_Occurred()) { goto exit; } @@ -82,7 +88,7 @@ exit: } PyDoc_STRVAR(_bisect_insort_right__doc__, -"insort_right($module, /, a, x, lo=0, hi=None)\n" +"insort_right($module, /, a, x, lo=0, hi=None, *, key=None)\n" "--\n" "\n" "Insert item x in list a, and keep it sorted assuming a is sorted.\n" @@ -97,20 +103,21 @@ PyDoc_STRVAR(_bisect_insort_right__doc__, static PyObject * _bisect_insort_right_impl(PyObject *module, PyObject *a, PyObject *x, - Py_ssize_t lo, Py_ssize_t hi); + Py_ssize_t lo, Py_ssize_t hi, PyObject *key); static PyObject * _bisect_insort_right(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; - static const char * const _keywords[] = {"a", "x", "lo", "hi", NULL}; + static const char * const _keywords[] = {"a", "x", "lo", "hi", "key", NULL}; static _PyArg_Parser _parser = {NULL, _keywords, "insort_right", 0}; - PyObject *argsbuf[4]; + PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; PyObject *a; PyObject *x; Py_ssize_t lo = 0; Py_ssize_t hi = -1; + PyObject *key = Py_None; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 4, 0, argsbuf); if (!args) { @@ -122,14 +129,9 @@ _bisect_insort_right(PyObject *module, PyObject *const *args, Py_ssize_t nargs, goto skip_optional_pos; } if (args[2]) { - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[2]); + PyObject *iobj = _PyNumber_Index(args[2]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -143,25 +145,35 @@ _bisect_insort_right(PyObject *module, PyObject *const *args, Py_ssize_t nargs, goto skip_optional_pos; } } - if (!_Py_convert_optional_to_ssize_t(args[3], &hi)) { - goto exit; + if (args[3]) { + if (!_Py_convert_optional_to_ssize_t(args[3], &hi)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } } skip_optional_pos: - return_value = _bisect_insort_right_impl(module, a, x, lo, hi); + if (!noptargs) { + goto skip_optional_kwonly; + } + key = args[4]; +skip_optional_kwonly: + return_value = _bisect_insort_right_impl(module, a, x, lo, hi, key); exit: return return_value; } PyDoc_STRVAR(_bisect_bisect_left__doc__, -"bisect_left($module, /, a, x, lo=0, hi=None)\n" +"bisect_left($module, /, a, x, lo=0, hi=None, *, key=None)\n" "--\n" "\n" "Return the index where to insert item x in list a, assuming a is sorted.\n" "\n" "The return value i is such that all e in a[:i] have e < x, and all e in\n" -"a[i:] have e >= x. So if x already appears in the list, i points just\n" -"before the leftmost x already there.\n" +"a[i:] have e >= x. So if x already appears in the list, a.insert(i, x) will\n" +"insert just before the leftmost x already there.\n" "\n" "Optional args lo (default 0) and hi (default len(a)) bound the\n" "slice of a to be searched."); @@ -171,20 +183,21 @@ PyDoc_STRVAR(_bisect_bisect_left__doc__, static Py_ssize_t _bisect_bisect_left_impl(PyObject *module, PyObject *a, PyObject *x, - Py_ssize_t lo, Py_ssize_t hi); + Py_ssize_t lo, Py_ssize_t hi, PyObject *key); static PyObject * _bisect_bisect_left(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; - static const char * const _keywords[] = {"a", "x", "lo", "hi", NULL}; + static const char * const _keywords[] = {"a", "x", "lo", "hi", "key", NULL}; static _PyArg_Parser _parser = {NULL, _keywords, "bisect_left", 0}; - PyObject *argsbuf[4]; + PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; PyObject *a; PyObject *x; Py_ssize_t lo = 0; Py_ssize_t hi = -1; + PyObject *key = Py_None; Py_ssize_t _return_value; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 4, 0, argsbuf); @@ -197,14 +210,9 @@ _bisect_bisect_left(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P goto skip_optional_pos; } if (args[2]) { - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[2]); + PyObject *iobj = _PyNumber_Index(args[2]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -218,11 +226,21 @@ _bisect_bisect_left(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P goto skip_optional_pos; } } - if (!_Py_convert_optional_to_ssize_t(args[3], &hi)) { - goto exit; + if (args[3]) { + if (!_Py_convert_optional_to_ssize_t(args[3], &hi)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } } skip_optional_pos: - _return_value = _bisect_bisect_left_impl(module, a, x, lo, hi); + if (!noptargs) { + goto skip_optional_kwonly; + } + key = args[4]; +skip_optional_kwonly: + _return_value = _bisect_bisect_left_impl(module, a, x, lo, hi, key); if ((_return_value == -1) && PyErr_Occurred()) { goto exit; } @@ -233,7 +251,7 @@ exit: } PyDoc_STRVAR(_bisect_insort_left__doc__, -"insort_left($module, /, a, x, lo=0, hi=None)\n" +"insort_left($module, /, a, x, lo=0, hi=None, *, key=None)\n" "--\n" "\n" "Insert item x in list a, and keep it sorted assuming a is sorted.\n" @@ -248,20 +266,21 @@ PyDoc_STRVAR(_bisect_insort_left__doc__, static PyObject * _bisect_insort_left_impl(PyObject *module, PyObject *a, PyObject *x, - Py_ssize_t lo, Py_ssize_t hi); + Py_ssize_t lo, Py_ssize_t hi, PyObject *key); static PyObject * _bisect_insort_left(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; - static const char * const _keywords[] = {"a", "x", "lo", "hi", NULL}; + static const char * const _keywords[] = {"a", "x", "lo", "hi", "key", NULL}; static _PyArg_Parser _parser = {NULL, _keywords, "insort_left", 0}; - PyObject *argsbuf[4]; + PyObject *argsbuf[5]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; PyObject *a; PyObject *x; Py_ssize_t lo = 0; Py_ssize_t hi = -1; + PyObject *key = Py_None; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 4, 0, argsbuf); if (!args) { @@ -273,14 +292,9 @@ _bisect_insort_left(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P goto skip_optional_pos; } if (args[2]) { - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[2]); + PyObject *iobj = _PyNumber_Index(args[2]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -294,13 +308,23 @@ _bisect_insort_left(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P goto skip_optional_pos; } } - if (!_Py_convert_optional_to_ssize_t(args[3], &hi)) { - goto exit; + if (args[3]) { + if (!_Py_convert_optional_to_ssize_t(args[3], &hi)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } } skip_optional_pos: - return_value = _bisect_insort_left_impl(module, a, x, lo, hi); + if (!noptargs) { + goto skip_optional_kwonly; + } + key = args[4]; +skip_optional_kwonly: + return_value = _bisect_insort_left_impl(module, a, x, lo, hi, key); exit: return return_value; } -/*[clinic end generated code: output=bcbd6c77331a08f0 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=aeb97db6db79bf96 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/_bz2module.c.h b/contrib/tools/python3/src/Modules/clinic/_bz2module.c.h index 0eb6280d6e..71ad0b1357 100644 --- a/contrib/tools/python3/src/Modules/clinic/_bz2module.c.h +++ b/contrib/tools/python3/src/Modules/clinic/_bz2module.c.h @@ -65,52 +65,6 @@ _bz2_BZ2Compressor_flush(BZ2Compressor *self, PyObject *Py_UNUSED(ignored)) return _bz2_BZ2Compressor_flush_impl(self); } -PyDoc_STRVAR(_bz2_BZ2Compressor___init____doc__, -"BZ2Compressor(compresslevel=9, /)\n" -"--\n" -"\n" -"Create a compressor object for compressing data incrementally.\n" -"\n" -" compresslevel\n" -" Compression level, as a number between 1 and 9.\n" -"\n" -"For one-shot compression, use the compress() function instead."); - -static int -_bz2_BZ2Compressor___init___impl(BZ2Compressor *self, int compresslevel); - -static int -_bz2_BZ2Compressor___init__(PyObject *self, PyObject *args, PyObject *kwargs) -{ - int return_value = -1; - int compresslevel = 9; - - if (Py_IS_TYPE(self, &BZ2Compressor_Type) && - !_PyArg_NoKeywords("BZ2Compressor", kwargs)) { - goto exit; - } - if (!_PyArg_CheckPositional("BZ2Compressor", PyTuple_GET_SIZE(args), 0, 1)) { - goto exit; - } - if (PyTuple_GET_SIZE(args) < 1) { - goto skip_optional; - } - if (PyFloat_Check(PyTuple_GET_ITEM(args, 0))) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } - compresslevel = _PyLong_AsInt(PyTuple_GET_ITEM(args, 0)); - if (compresslevel == -1 && PyErr_Occurred()) { - goto exit; - } -skip_optional: - return_value = _bz2_BZ2Compressor___init___impl((BZ2Compressor *)self, compresslevel); - -exit: - return return_value; -} - PyDoc_STRVAR(_bz2_BZ2Decompressor_decompress__doc__, "decompress($self, /, data, max_length=-1)\n" "--\n" @@ -162,14 +116,9 @@ _bz2_BZ2Decompressor_decompress(BZ2Decompressor *self, PyObject *const *args, Py if (!noptargs) { goto skip_optional_pos; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[1]); + PyObject *iobj = _PyNumber_Index(args[1]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -190,34 +139,4 @@ exit: return return_value; } - -PyDoc_STRVAR(_bz2_BZ2Decompressor___init____doc__, -"BZ2Decompressor()\n" -"--\n" -"\n" -"Create a decompressor object for decompressing data incrementally.\n" -"\n" -"For one-shot decompression, use the decompress() function instead."); - -static int -_bz2_BZ2Decompressor___init___impl(BZ2Decompressor *self); - -static int -_bz2_BZ2Decompressor___init__(PyObject *self, PyObject *args, PyObject *kwargs) -{ - int return_value = -1; - - if (Py_IS_TYPE(self, &BZ2Decompressor_Type) && - !_PyArg_NoPositional("BZ2Decompressor", args)) { - goto exit; - } - if (Py_IS_TYPE(self, &BZ2Decompressor_Type) && - !_PyArg_NoKeywords("BZ2Decompressor", kwargs)) { - goto exit; - } - return_value = _bz2_BZ2Decompressor___init___impl((BZ2Decompressor *)self); - -exit: - return return_value; -} -/*[clinic end generated code: output=3f3f1e788fe28ee1 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ed10705d7a9fd598 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/_codecsmodule.c.h b/contrib/tools/python3/src/Modules/clinic/_codecsmodule.c.h index 7ddc36de8a..855ac77a7f 100644 --- a/contrib/tools/python3/src/Modules/clinic/_codecsmodule.c.h +++ b/contrib/tools/python3/src/Modules/clinic/_codecsmodule.c.h @@ -15,6 +15,17 @@ PyDoc_STRVAR(_codecs_register__doc__, #define _CODECS_REGISTER_METHODDEF \ {"register", (PyCFunction)_codecs_register, METH_O, _codecs_register__doc__}, +PyDoc_STRVAR(_codecs_unregister__doc__, +"unregister($module, search_function, /)\n" +"--\n" +"\n" +"Unregister a codec search function and clear the registry\'s cache.\n" +"\n" +"If the search function is not registered, do nothing."); + +#define _CODECS_UNREGISTER_METHODDEF \ + {"unregister", (PyCFunction)_codecs_unregister, METH_O, _codecs_unregister__doc__}, + PyDoc_STRVAR(_codecs_lookup__doc__, "lookup($module, encoding, /)\n" "--\n" @@ -206,43 +217,6 @@ exit: return return_value; } -PyDoc_STRVAR(_codecs__forget_codec__doc__, -"_forget_codec($module, encoding, /)\n" -"--\n" -"\n" -"Purge the named codec from the internal codec lookup cache"); - -#define _CODECS__FORGET_CODEC_METHODDEF \ - {"_forget_codec", (PyCFunction)_codecs__forget_codec, METH_O, _codecs__forget_codec__doc__}, - -static PyObject * -_codecs__forget_codec_impl(PyObject *module, const char *encoding); - -static PyObject * -_codecs__forget_codec(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - const char *encoding; - - if (!PyUnicode_Check(arg)) { - _PyArg_BadArgument("_forget_codec", "argument", "str", arg); - goto exit; - } - Py_ssize_t encoding_length; - encoding = PyUnicode_AsUTF8AndSize(arg, &encoding_length); - if (encoding == NULL) { - goto exit; - } - if (strlen(encoding) != (size_t)encoding_length) { - PyErr_SetString(PyExc_ValueError, "embedded null character"); - goto exit; - } - return_value = _codecs__forget_codec_impl(module, encoding); - -exit: - return return_value; -} - PyDoc_STRVAR(_codecs_escape_decode__doc__, "escape_decode($module, data, errors=None, /)\n" "--\n" @@ -424,11 +398,6 @@ _codecs_utf_7_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 3) { goto skip_optional; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } final = _PyLong_AsInt(args[2]); if (final == -1 && PyErr_Occurred()) { goto exit; @@ -499,11 +468,6 @@ _codecs_utf_8_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 3) { goto skip_optional; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } final = _PyLong_AsInt(args[2]); if (final == -1 && PyErr_Occurred()) { goto exit; @@ -574,11 +538,6 @@ _codecs_utf_16_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 3) { goto skip_optional; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } final = _PyLong_AsInt(args[2]); if (final == -1 && PyErr_Occurred()) { goto exit; @@ -649,11 +608,6 @@ _codecs_utf_16_le_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar if (nargs < 3) { goto skip_optional; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } final = _PyLong_AsInt(args[2]); if (final == -1 && PyErr_Occurred()) { goto exit; @@ -724,11 +678,6 @@ _codecs_utf_16_be_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar if (nargs < 3) { goto skip_optional; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } final = _PyLong_AsInt(args[2]); if (final == -1 && PyErr_Occurred()) { goto exit; @@ -801,11 +750,6 @@ _codecs_utf_16_ex_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar if (nargs < 3) { goto skip_optional; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } byteorder = _PyLong_AsInt(args[2]); if (byteorder == -1 && PyErr_Occurred()) { goto exit; @@ -813,11 +757,6 @@ _codecs_utf_16_ex_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar if (nargs < 4) { goto skip_optional; } - if (PyFloat_Check(args[3])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } final = _PyLong_AsInt(args[3]); if (final == -1 && PyErr_Occurred()) { goto exit; @@ -888,11 +827,6 @@ _codecs_utf_32_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 3) { goto skip_optional; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } final = _PyLong_AsInt(args[2]); if (final == -1 && PyErr_Occurred()) { goto exit; @@ -963,11 +897,6 @@ _codecs_utf_32_le_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar if (nargs < 3) { goto skip_optional; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } final = _PyLong_AsInt(args[2]); if (final == -1 && PyErr_Occurred()) { goto exit; @@ -1038,11 +967,6 @@ _codecs_utf_32_be_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar if (nargs < 3) { goto skip_optional; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } final = _PyLong_AsInt(args[2]); if (final == -1 && PyErr_Occurred()) { goto exit; @@ -1115,11 +1039,6 @@ _codecs_utf_32_ex_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar if (nargs < 3) { goto skip_optional; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } byteorder = _PyLong_AsInt(args[2]); if (byteorder == -1 && PyErr_Occurred()) { goto exit; @@ -1127,11 +1046,6 @@ _codecs_utf_32_ex_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar if (nargs < 4) { goto skip_optional; } - if (PyFloat_Check(args[3])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } final = _PyLong_AsInt(args[3]); if (final == -1 && PyErr_Occurred()) { goto exit; @@ -1212,11 +1126,6 @@ _codecs_unicode_escape_decode(PyObject *module, PyObject *const *args, Py_ssize_ if (nargs < 3) { goto skip_optional; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } final = _PyLong_AsInt(args[2]); if (final == -1 && PyErr_Occurred()) { goto exit; @@ -1297,11 +1206,6 @@ _codecs_raw_unicode_escape_decode(PyObject *module, PyObject *const *args, Py_ss if (nargs < 3) { goto skip_optional; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } final = _PyLong_AsInt(args[2]); if (final == -1 && PyErr_Occurred()) { goto exit; @@ -1565,11 +1469,6 @@ _codecs_mbcs_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 3) { goto skip_optional; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } final = _PyLong_AsInt(args[2]); if (final == -1 && PyErr_Occurred()) { goto exit; @@ -1644,11 +1543,6 @@ _codecs_oem_decode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 3) { goto skip_optional; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } final = _PyLong_AsInt(args[2]); if (final == -1 && PyErr_Occurred()) { goto exit; @@ -1693,11 +1587,6 @@ _codecs_code_page_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar if (!_PyArg_CheckPositional("code_page_decode", nargs, 2, 4)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } codepage = _PyLong_AsInt(args[0]); if (codepage == -1 && PyErr_Occurred()) { goto exit; @@ -1733,11 +1622,6 @@ _codecs_code_page_decode(PyObject *module, PyObject *const *args, Py_ssize_t nar if (nargs < 4) { goto skip_optional; } - if (PyFloat_Check(args[3])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } final = _PyLong_AsInt(args[3]); if (final == -1 && PyErr_Occurred()) { goto exit; @@ -1999,11 +1883,6 @@ _codecs_utf_16_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 3) { goto skip_optional; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } byteorder = _PyLong_AsInt(args[2]); if (byteorder == -1 && PyErr_Occurred()) { goto exit; @@ -2186,11 +2065,6 @@ _codecs_utf_32_encode(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 3) { goto skip_optional; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } byteorder = _PyLong_AsInt(args[2]); if (byteorder == -1 && PyErr_Occurred()) { goto exit; @@ -2791,11 +2665,6 @@ _codecs_code_page_encode(PyObject *module, PyObject *const *args, Py_ssize_t nar if (!_PyArg_CheckPositional("code_page_encode", nargs, 2, 3)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } code_page = _PyLong_AsInt(args[0]); if (code_page == -1 && PyErr_Occurred()) { goto exit; @@ -2948,4 +2817,4 @@ exit: #ifndef _CODECS_CODE_PAGE_ENCODE_METHODDEF #define _CODECS_CODE_PAGE_ENCODE_METHODDEF #endif /* !defined(_CODECS_CODE_PAGE_ENCODE_METHODDEF) */ -/*[clinic end generated code: output=eed7dc9312baf252 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=814dae36b6f885cb input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/_collectionsmodule.c.h b/contrib/tools/python3/src/Modules/clinic/_collectionsmodule.c.h index c3ba1a6698..7e18aeb312 100644 --- a/contrib/tools/python3/src/Modules/clinic/_collectionsmodule.c.h +++ b/contrib/tools/python3/src/Modules/clinic/_collectionsmodule.c.h @@ -50,14 +50,9 @@ tuplegetter_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) if (!_PyArg_CheckPositional("_tuplegetter", PyTuple_GET_SIZE(args), 2, 2)) { goto exit; } - if (PyFloat_Check(PyTuple_GET_ITEM(args, 0))) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(PyTuple_GET_ITEM(args, 0)); + PyObject *iobj = _PyNumber_Index(PyTuple_GET_ITEM(args, 0)); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -73,4 +68,4 @@ tuplegetter_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=9d2bfcc9df5faf35 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=947186d369f50f1e input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/_curses_panel.c.h b/contrib/tools/python3/src/Modules/clinic/_curses_panel.c.h index 9840ed86e7..45898070b1 100644 --- a/contrib/tools/python3/src/Modules/clinic/_curses_panel.c.h +++ b/contrib/tools/python3/src/Modules/clinic/_curses_panel.c.h @@ -9,15 +9,26 @@ PyDoc_STRVAR(_curses_panel_panel_bottom__doc__, "Push the panel to the bottom of the stack."); #define _CURSES_PANEL_PANEL_BOTTOM_METHODDEF \ - {"bottom", (PyCFunction)_curses_panel_panel_bottom, METH_NOARGS, _curses_panel_panel_bottom__doc__}, + {"bottom", (PyCFunction)(void(*)(void))_curses_panel_panel_bottom, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _curses_panel_panel_bottom__doc__}, static PyObject * -_curses_panel_panel_bottom_impl(PyCursesPanelObject *self); +_curses_panel_panel_bottom_impl(PyCursesPanelObject *self, PyTypeObject *cls); static PyObject * -_curses_panel_panel_bottom(PyCursesPanelObject *self, PyObject *Py_UNUSED(ignored)) +_curses_panel_panel_bottom(PyCursesPanelObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return _curses_panel_panel_bottom_impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = {":bottom", _keywords, 0}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser + )) { + goto exit; + } + return_value = _curses_panel_panel_bottom_impl(self, cls); + +exit: + return return_value; } PyDoc_STRVAR(_curses_panel_panel_hide__doc__, @@ -29,15 +40,26 @@ PyDoc_STRVAR(_curses_panel_panel_hide__doc__, "This does not delete the object, it just makes the window on screen invisible."); #define _CURSES_PANEL_PANEL_HIDE_METHODDEF \ - {"hide", (PyCFunction)_curses_panel_panel_hide, METH_NOARGS, _curses_panel_panel_hide__doc__}, + {"hide", (PyCFunction)(void(*)(void))_curses_panel_panel_hide, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _curses_panel_panel_hide__doc__}, static PyObject * -_curses_panel_panel_hide_impl(PyCursesPanelObject *self); +_curses_panel_panel_hide_impl(PyCursesPanelObject *self, PyTypeObject *cls); static PyObject * -_curses_panel_panel_hide(PyCursesPanelObject *self, PyObject *Py_UNUSED(ignored)) +_curses_panel_panel_hide(PyCursesPanelObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return _curses_panel_panel_hide_impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = {":hide", _keywords, 0}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser + )) { + goto exit; + } + return_value = _curses_panel_panel_hide_impl(self, cls); + +exit: + return return_value; } PyDoc_STRVAR(_curses_panel_panel_show__doc__, @@ -47,15 +69,26 @@ PyDoc_STRVAR(_curses_panel_panel_show__doc__, "Display the panel (which might have been hidden)."); #define _CURSES_PANEL_PANEL_SHOW_METHODDEF \ - {"show", (PyCFunction)_curses_panel_panel_show, METH_NOARGS, _curses_panel_panel_show__doc__}, + {"show", (PyCFunction)(void(*)(void))_curses_panel_panel_show, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _curses_panel_panel_show__doc__}, static PyObject * -_curses_panel_panel_show_impl(PyCursesPanelObject *self); +_curses_panel_panel_show_impl(PyCursesPanelObject *self, PyTypeObject *cls); static PyObject * -_curses_panel_panel_show(PyCursesPanelObject *self, PyObject *Py_UNUSED(ignored)) +_curses_panel_panel_show(PyCursesPanelObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return _curses_panel_panel_show_impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = {":show", _keywords, 0}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser + )) { + goto exit; + } + return_value = _curses_panel_panel_show_impl(self, cls); + +exit: + return return_value; } PyDoc_STRVAR(_curses_panel_panel_top__doc__, @@ -65,15 +98,26 @@ PyDoc_STRVAR(_curses_panel_panel_top__doc__, "Push panel to the top of the stack."); #define _CURSES_PANEL_PANEL_TOP_METHODDEF \ - {"top", (PyCFunction)_curses_panel_panel_top, METH_NOARGS, _curses_panel_panel_top__doc__}, + {"top", (PyCFunction)(void(*)(void))_curses_panel_panel_top, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _curses_panel_panel_top__doc__}, static PyObject * -_curses_panel_panel_top_impl(PyCursesPanelObject *self); +_curses_panel_panel_top_impl(PyCursesPanelObject *self, PyTypeObject *cls); static PyObject * -_curses_panel_panel_top(PyCursesPanelObject *self, PyObject *Py_UNUSED(ignored)) +_curses_panel_panel_top(PyCursesPanelObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return _curses_panel_panel_top_impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = {":top", _keywords, 0}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser + )) { + goto exit; + } + return_value = _curses_panel_panel_top_impl(self, cls); + +exit: + return return_value; } PyDoc_STRVAR(_curses_panel_panel_above__doc__, @@ -137,40 +181,26 @@ PyDoc_STRVAR(_curses_panel_panel_move__doc__, "Move the panel to the screen coordinates (y, x)."); #define _CURSES_PANEL_PANEL_MOVE_METHODDEF \ - {"move", (PyCFunction)(void(*)(void))_curses_panel_panel_move, METH_FASTCALL, _curses_panel_panel_move__doc__}, + {"move", (PyCFunction)(void(*)(void))_curses_panel_panel_move, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _curses_panel_panel_move__doc__}, static PyObject * -_curses_panel_panel_move_impl(PyCursesPanelObject *self, int y, int x); +_curses_panel_panel_move_impl(PyCursesPanelObject *self, PyTypeObject *cls, + int y, int x); static PyObject * -_curses_panel_panel_move(PyCursesPanelObject *self, PyObject *const *args, Py_ssize_t nargs) +_curses_panel_panel_move(PyCursesPanelObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + static const char * const _keywords[] = {"", "", NULL}; + static _PyArg_Parser _parser = {"ii:move", _keywords, 0}; int y; int x; - if (!_PyArg_CheckPositional("move", nargs, 2, 2)) { - goto exit; - } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } - y = _PyLong_AsInt(args[0]); - if (y == -1 && PyErr_Occurred()) { - goto exit; - } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } - x = _PyLong_AsInt(args[1]); - if (x == -1 && PyErr_Occurred()) { + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &y, &x)) { goto exit; } - return_value = _curses_panel_panel_move_impl(self, y, x); + return_value = _curses_panel_panel_move_impl(self, cls, y, x); exit: return return_value; @@ -201,24 +231,26 @@ PyDoc_STRVAR(_curses_panel_panel_replace__doc__, "Change the window associated with the panel to the window win."); #define _CURSES_PANEL_PANEL_REPLACE_METHODDEF \ - {"replace", (PyCFunction)_curses_panel_panel_replace, METH_O, _curses_panel_panel_replace__doc__}, + {"replace", (PyCFunction)(void(*)(void))_curses_panel_panel_replace, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _curses_panel_panel_replace__doc__}, static PyObject * _curses_panel_panel_replace_impl(PyCursesPanelObject *self, + PyTypeObject *cls, PyCursesWindowObject *win); static PyObject * -_curses_panel_panel_replace(PyCursesPanelObject *self, PyObject *arg) +_curses_panel_panel_replace(PyCursesPanelObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = {"O!:replace", _keywords, 0}; PyCursesWindowObject *win; - if (!PyObject_TypeCheck(arg, &PyCursesWindow_Type)) { - _PyArg_BadArgument("replace", "argument", (&PyCursesWindow_Type)->tp_name, arg); + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &PyCursesWindow_Type, &win)) { goto exit; } - win = (PyCursesWindowObject *)arg; - return_value = _curses_panel_panel_replace_impl(self, win); + return_value = _curses_panel_panel_replace_impl(self, cls, win); exit: return return_value; @@ -231,7 +263,29 @@ PyDoc_STRVAR(_curses_panel_panel_set_userptr__doc__, "Set the panel\'s user pointer to obj."); #define _CURSES_PANEL_PANEL_SET_USERPTR_METHODDEF \ - {"set_userptr", (PyCFunction)_curses_panel_panel_set_userptr, METH_O, _curses_panel_panel_set_userptr__doc__}, + {"set_userptr", (PyCFunction)(void(*)(void))_curses_panel_panel_set_userptr, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _curses_panel_panel_set_userptr__doc__}, + +static PyObject * +_curses_panel_panel_set_userptr_impl(PyCursesPanelObject *self, + PyTypeObject *cls, PyObject *obj); + +static PyObject * +_curses_panel_panel_set_userptr(PyCursesPanelObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = {"O:set_userptr", _keywords, 0}; + PyObject *obj; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &obj)) { + goto exit; + } + return_value = _curses_panel_panel_set_userptr_impl(self, cls, obj); + +exit: + return return_value; +} PyDoc_STRVAR(_curses_panel_panel_userptr__doc__, "userptr($self, /)\n" @@ -240,15 +294,27 @@ PyDoc_STRVAR(_curses_panel_panel_userptr__doc__, "Return the user pointer for the panel."); #define _CURSES_PANEL_PANEL_USERPTR_METHODDEF \ - {"userptr", (PyCFunction)_curses_panel_panel_userptr, METH_NOARGS, _curses_panel_panel_userptr__doc__}, + {"userptr", (PyCFunction)(void(*)(void))_curses_panel_panel_userptr, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _curses_panel_panel_userptr__doc__}, static PyObject * -_curses_panel_panel_userptr_impl(PyCursesPanelObject *self); +_curses_panel_panel_userptr_impl(PyCursesPanelObject *self, + PyTypeObject *cls); static PyObject * -_curses_panel_panel_userptr(PyCursesPanelObject *self, PyObject *Py_UNUSED(ignored)) +_curses_panel_panel_userptr(PyCursesPanelObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return _curses_panel_panel_userptr_impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = {":userptr", _keywords, 0}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser + )) { + goto exit; + } + return_value = _curses_panel_panel_userptr_impl(self, cls); + +exit: + return return_value; } PyDoc_STRVAR(_curses_panel_bottom_panel__doc__, @@ -335,4 +401,4 @@ _curses_panel_update_panels(PyObject *module, PyObject *Py_UNUSED(ignored)) { return _curses_panel_update_panels_impl(module); } -/*[clinic end generated code: output=d96dc1fd68e898d9 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3081ef24e5560cb0 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/_cursesmodule.c.h b/contrib/tools/python3/src/Modules/clinic/_cursesmodule.c.h index 66ffcdfdb3..9c9611685b 100644 --- a/contrib/tools/python3/src/Modules/clinic/_cursesmodule.c.h +++ b/contrib/tools/python3/src/Modules/clinic/_cursesmodule.c.h @@ -252,11 +252,6 @@ _curses_window_bkgd(PyCursesWindowObject *self, PyObject *const *args, Py_ssize_ if (nargs < 2) { goto skip_optional; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } attr = PyLong_AsLong(args[1]); if (attr == -1 && PyErr_Occurred()) { goto exit; @@ -286,11 +281,6 @@ _curses_window_attroff(PyCursesWindowObject *self, PyObject *arg) PyObject *return_value = NULL; long attr; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } attr = PyLong_AsLong(arg); if (attr == -1 && PyErr_Occurred()) { goto exit; @@ -319,11 +309,6 @@ _curses_window_attron(PyCursesWindowObject *self, PyObject *arg) PyObject *return_value = NULL; long attr; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } attr = PyLong_AsLong(arg); if (attr == -1 && PyErr_Occurred()) { goto exit; @@ -352,11 +337,6 @@ _curses_window_attrset(PyCursesWindowObject *self, PyObject *arg) PyObject *return_value = NULL; long attr; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } attr = PyLong_AsLong(arg); if (attr == -1 && PyErr_Occurred()) { goto exit; @@ -399,11 +379,6 @@ _curses_window_bkgdset(PyCursesWindowObject *self, PyObject *const *args, Py_ssi if (nargs < 2) { goto skip_optional; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } attr = PyLong_AsLong(args[1]); if (attr == -1 && PyErr_Occurred()) { goto exit; @@ -534,8 +509,8 @@ _curses_window_box(PyCursesWindowObject *self, PyObject *args) { PyObject *return_value = NULL; int group_right_1 = 0; - PyObject *verch = _PyLong_Zero; - PyObject *horch = _PyLong_Zero; + PyObject *verch = _PyLong_GetZero(); + PyObject *horch = _PyLong_GetZero(); switch (PyTuple_GET_SIZE(args)) { case 0: @@ -687,11 +662,6 @@ _curses_window_echochar(PyCursesWindowObject *self, PyObject *const *args, Py_ss if (nargs < 2) { goto skip_optional; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } attr = PyLong_AsLong(args[1]); if (attr == -1 && PyErr_Occurred()) { goto exit; @@ -719,7 +689,7 @@ PyDoc_STRVAR(_curses_window_enclose__doc__, #define _CURSES_WINDOW_ENCLOSE_METHODDEF \ {"enclose", (PyCFunction)(void(*)(void))_curses_window_enclose, METH_FASTCALL, _curses_window_enclose__doc__}, -static long +static PyObject * _curses_window_enclose_impl(PyCursesWindowObject *self, int y, int x); static PyObject * @@ -728,34 +698,19 @@ _curses_window_enclose(PyCursesWindowObject *self, PyObject *const *args, Py_ssi PyObject *return_value = NULL; int y; int x; - long _return_value; if (!_PyArg_CheckPositional("enclose", nargs, 2, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } y = _PyLong_AsInt(args[0]); if (y == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } x = _PyLong_AsInt(args[1]); if (x == -1 && PyErr_Occurred()) { goto exit; } - _return_value = _curses_window_enclose_impl(self, y, x); - if ((_return_value == -1) && PyErr_Occurred()) { - goto exit; - } - return_value = PyLong_FromLong(_return_value); + return_value = _curses_window_enclose_impl(self, y, x); exit: return return_value; @@ -1303,11 +1258,6 @@ _curses_window_is_linetouched(PyCursesWindowObject *self, PyObject *arg) PyObject *return_value = NULL; int line; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } line = _PyLong_AsInt(arg); if (line == -1 && PyErr_Occurred()) { goto exit; @@ -1552,20 +1502,10 @@ _curses_window_redrawln(PyCursesWindowObject *self, PyObject *const *args, Py_ss if (!_PyArg_CheckPositional("redrawln", nargs, 2, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } beg = _PyLong_AsInt(args[0]); if (beg == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } num = _PyLong_AsInt(args[1]); if (num == -1 && PyErr_Occurred()) { goto exit; @@ -1661,20 +1601,10 @@ _curses_window_setscrreg(PyCursesWindowObject *self, PyObject *const *args, Py_s if (!_PyArg_CheckPositional("setscrreg", nargs, 2, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } top = _PyLong_AsInt(args[0]); if (top == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } bottom = _PyLong_AsInt(args[1]); if (bottom == -1 && PyErr_Occurred()) { goto exit; @@ -2005,11 +1935,6 @@ _curses_cbreak(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 1) { goto skip_optional; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } flag = _PyLong_AsInt(args[0]); if (flag == -1 && PyErr_Occurred()) { goto exit; @@ -2037,38 +1962,17 @@ PyDoc_STRVAR(_curses_color_content__doc__, {"color_content", (PyCFunction)_curses_color_content, METH_O, _curses_color_content__doc__}, static PyObject * -_curses_color_content_impl(PyObject *module, short color_number); +_curses_color_content_impl(PyObject *module, int color_number); static PyObject * _curses_color_content(PyObject *module, PyObject *arg) { PyObject *return_value = NULL; - short color_number; + int color_number; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); + if (!color_converter(arg, &color_number)) { goto exit; } - { - long ival = PyLong_AsLong(arg); - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - else if (ival < SHRT_MIN) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is less than minimum"); - goto exit; - } - else if (ival > SHRT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is greater than maximum"); - goto exit; - } - else { - color_number = (short) ival; - } - } return_value = _curses_color_content_impl(module, color_number); exit: @@ -2091,38 +1995,18 @@ PyDoc_STRVAR(_curses_color_pair__doc__, {"color_pair", (PyCFunction)_curses_color_pair, METH_O, _curses_color_pair__doc__}, static PyObject * -_curses_color_pair_impl(PyObject *module, short pair_number); +_curses_color_pair_impl(PyObject *module, int pair_number); static PyObject * _curses_color_pair(PyObject *module, PyObject *arg) { PyObject *return_value = NULL; - short pair_number; + int pair_number; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); + pair_number = _PyLong_AsInt(arg); + if (pair_number == -1 && PyErr_Occurred()) { goto exit; } - { - long ival = PyLong_AsLong(arg); - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - else if (ival < SHRT_MIN) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is less than minimum"); - goto exit; - } - else if (ival > SHRT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is greater than maximum"); - goto exit; - } - else { - pair_number = (short) ival; - } - } return_value = _curses_color_pair_impl(module, pair_number); exit: @@ -2155,11 +2039,6 @@ _curses_curs_set(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int visibility; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } visibility = _PyLong_AsInt(arg); if (visibility == -1 && PyErr_Occurred()) { goto exit; @@ -2235,11 +2114,6 @@ _curses_delay_output(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int ms; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } ms = _PyLong_AsInt(arg); if (ms == -1 && PyErr_Occurred()) { goto exit; @@ -2297,11 +2171,6 @@ _curses_echo(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 1) { goto skip_optional; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } flag = _PyLong_AsInt(args[0]); if (flag == -1 && PyErr_Occurred()) { goto exit; @@ -2469,11 +2338,6 @@ _curses_ungetmouse(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("ungetmouse", nargs, 5, 5)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { long ival = PyLong_AsLong(args[0]); if (ival == -1 && PyErr_Occurred()) { @@ -2493,29 +2357,14 @@ _curses_ungetmouse(PyObject *module, PyObject *const *args, Py_ssize_t nargs) id = (short) ival; } } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } x = _PyLong_AsInt(args[1]); if (x == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } y = _PyLong_AsInt(args[2]); if (y == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[3])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } z = _PyLong_AsInt(args[3]); if (z == -1 && PyErr_Occurred()) { goto exit; @@ -2568,11 +2417,6 @@ _curses_halfdelay(PyObject *module, PyObject *arg) PyObject *return_value = NULL; unsigned char tenths; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { long ival = PyLong_AsLong(arg); if (ival == -1 && PyErr_Occurred()) { @@ -2675,11 +2519,6 @@ _curses_has_key(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int key; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } key = _PyLong_AsInt(arg); if (key == -1 && PyErr_Occurred()) { goto exit; @@ -2715,14 +2554,14 @@ PyDoc_STRVAR(_curses_init_color__doc__, {"init_color", (PyCFunction)(void(*)(void))_curses_init_color, METH_FASTCALL, _curses_init_color__doc__}, static PyObject * -_curses_init_color_impl(PyObject *module, short color_number, short r, - short g, short b); +_curses_init_color_impl(PyObject *module, int color_number, short r, short g, + short b); static PyObject * _curses_init_color(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - short color_number; + int color_number; short r; short g; short b; @@ -2730,102 +2569,18 @@ _curses_init_color(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("init_color", nargs, 4, 4)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); + if (!color_converter(args[0], &color_number)) { goto exit; } - { - long ival = PyLong_AsLong(args[0]); - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - else if (ival < SHRT_MIN) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is less than minimum"); - goto exit; - } - else if (ival > SHRT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is greater than maximum"); - goto exit; - } - else { - color_number = (short) ival; - } - } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); + if (!component_converter(args[1], &r)) { goto exit; } - { - long ival = PyLong_AsLong(args[1]); - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - else if (ival < SHRT_MIN) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is less than minimum"); - goto exit; - } - else if (ival > SHRT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is greater than maximum"); - goto exit; - } - else { - r = (short) ival; - } - } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); + if (!component_converter(args[2], &g)) { goto exit; } - { - long ival = PyLong_AsLong(args[2]); - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - else if (ival < SHRT_MIN) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is less than minimum"); - goto exit; - } - else if (ival > SHRT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is greater than maximum"); - goto exit; - } - else { - g = (short) ival; - } - } - if (PyFloat_Check(args[3])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); + if (!component_converter(args[3], &b)) { goto exit; } - { - long ival = PyLong_AsLong(args[3]); - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - else if (ival < SHRT_MIN) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is less than minimum"); - goto exit; - } - else if (ival > SHRT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is greater than maximum"); - goto exit; - } - else { - b = (short) ival; - } - } return_value = _curses_init_color_impl(module, color_number, r, g, b); exit: @@ -2852,92 +2607,28 @@ PyDoc_STRVAR(_curses_init_pair__doc__, {"init_pair", (PyCFunction)(void(*)(void))_curses_init_pair, METH_FASTCALL, _curses_init_pair__doc__}, static PyObject * -_curses_init_pair_impl(PyObject *module, short pair_number, short fg, - short bg); +_curses_init_pair_impl(PyObject *module, int pair_number, int fg, int bg); static PyObject * _curses_init_pair(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - short pair_number; - short fg; - short bg; + int pair_number; + int fg; + int bg; if (!_PyArg_CheckPositional("init_pair", nargs, 3, 3)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); + if (!pair_converter(args[0], &pair_number)) { goto exit; } - { - long ival = PyLong_AsLong(args[0]); - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - else if (ival < SHRT_MIN) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is less than minimum"); - goto exit; - } - else if (ival > SHRT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is greater than maximum"); - goto exit; - } - else { - pair_number = (short) ival; - } - } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); + if (!color_allow_default_converter(args[1], &fg)) { goto exit; } - { - long ival = PyLong_AsLong(args[1]); - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - else if (ival < SHRT_MIN) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is less than minimum"); - goto exit; - } - else if (ival > SHRT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is greater than maximum"); - goto exit; - } - else { - fg = (short) ival; - } - } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); + if (!color_allow_default_converter(args[2], &bg)) { goto exit; } - { - long ival = PyLong_AsLong(args[2]); - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - else if (ival < SHRT_MIN) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is less than minimum"); - goto exit; - } - else if (ival > SHRT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is greater than maximum"); - goto exit; - } - else { - bg = (short) ival; - } - } return_value = _curses_init_pair_impl(module, pair_number, fg, bg); exit: @@ -3024,11 +2715,6 @@ _curses_setupterm(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyO goto skip_optional_pos; } } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(args[1]); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -3093,11 +2779,6 @@ _curses_set_escdelay(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int ms; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } ms = _PyLong_AsInt(arg); if (ms == -1 && PyErr_Occurred()) { goto exit; @@ -3161,11 +2842,6 @@ _curses_set_tabsize(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int size; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } size = _PyLong_AsInt(arg); if (size == -1 && PyErr_Occurred()) { goto exit; @@ -3195,11 +2871,6 @@ _curses_intrflush(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int flag; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } flag = _PyLong_AsInt(arg); if (flag == -1 && PyErr_Occurred()) { goto exit; @@ -3257,20 +2928,10 @@ _curses_is_term_resized(PyObject *module, PyObject *const *args, Py_ssize_t narg if (!_PyArg_CheckPositional("is_term_resized", nargs, 2, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } nlines = _PyLong_AsInt(args[0]); if (nlines == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } ncols = _PyLong_AsInt(args[1]); if (ncols == -1 && PyErr_Occurred()) { goto exit; @@ -3304,11 +2965,6 @@ _curses_keyname(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int key; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } key = _PyLong_AsInt(arg); if (key == -1 && PyErr_Occurred()) { goto exit; @@ -3379,11 +3035,6 @@ _curses_meta(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int yes; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } yes = _PyLong_AsInt(arg); if (yes == -1 && PyErr_Occurred()) { goto exit; @@ -3421,11 +3072,6 @@ _curses_mouseinterval(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int interval; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } interval = _PyLong_AsInt(arg); if (interval == -1 && PyErr_Occurred()) { goto exit; @@ -3497,11 +3143,6 @@ _curses_napms(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int ms; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } ms = _PyLong_AsInt(arg); if (ms == -1 && PyErr_Occurred()) { goto exit; @@ -3539,20 +3180,10 @@ _curses_newpad(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("newpad", nargs, 2, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } nlines = _PyLong_AsInt(args[0]); if (nlines == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } ncols = _PyLong_AsInt(args[1]); if (ncols == -1 && PyErr_Occurred()) { goto exit; @@ -3648,11 +3279,6 @@ _curses_nl(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 1) { goto skip_optional; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } flag = _PyLong_AsInt(args[0]); if (flag == -1 && PyErr_Occurred()) { goto exit; @@ -3773,44 +3399,23 @@ PyDoc_STRVAR(_curses_pair_content__doc__, "Return a tuple (fg, bg) containing the colors for the requested color pair.\n" "\n" " pair_number\n" -" The number of the color pair (1 - (COLOR_PAIRS-1))."); +" The number of the color pair (0 - (COLOR_PAIRS-1))."); #define _CURSES_PAIR_CONTENT_METHODDEF \ {"pair_content", (PyCFunction)_curses_pair_content, METH_O, _curses_pair_content__doc__}, static PyObject * -_curses_pair_content_impl(PyObject *module, short pair_number); +_curses_pair_content_impl(PyObject *module, int pair_number); static PyObject * _curses_pair_content(PyObject *module, PyObject *arg) { PyObject *return_value = NULL; - short pair_number; + int pair_number; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); + if (!pair_converter(arg, &pair_number)) { goto exit; } - { - long ival = PyLong_AsLong(arg); - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - else if (ival < SHRT_MIN) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is less than minimum"); - goto exit; - } - else if (ival > SHRT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is greater than maximum"); - goto exit; - } - else { - pair_number = (short) ival; - } - } return_value = _curses_pair_content_impl(module, pair_number); exit: @@ -3837,11 +3442,6 @@ _curses_pair_number(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int attr; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } attr = _PyLong_AsInt(arg); if (attr == -1 && PyErr_Occurred()) { goto exit; @@ -3911,11 +3511,6 @@ _curses_qiflush(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 1) { goto skip_optional; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } flag = _PyLong_AsInt(args[0]); if (flag == -1 && PyErr_Occurred()) { goto exit; @@ -3979,11 +3574,6 @@ _curses_raw(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 1) { goto skip_optional; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } flag = _PyLong_AsInt(args[0]); if (flag == -1 && PyErr_Occurred()) { goto exit; @@ -4081,20 +3671,10 @@ _curses_resizeterm(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("resizeterm", nargs, 2, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } nlines = _PyLong_AsInt(args[0]); if (nlines == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } ncols = _PyLong_AsInt(args[1]); if (ncols == -1 && PyErr_Occurred()) { goto exit; @@ -4142,20 +3722,10 @@ _curses_resize_term(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("resize_term", nargs, 2, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } nlines = _PyLong_AsInt(args[0]); if (nlines == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } ncols = _PyLong_AsInt(args[1]); if (ncols == -1 && PyErr_Occurred()) { goto exit; @@ -4217,20 +3787,10 @@ _curses_setsyx(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("setsyx", nargs, 2, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } y = _PyLong_AsInt(args[0]); if (y == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } x = _PyLong_AsInt(args[1]); if (x == -1 && PyErr_Occurred()) { goto exit; @@ -4500,11 +4060,6 @@ _curses_typeahead(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int fd; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(arg); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -4580,11 +4135,6 @@ _curses_use_env(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int flag; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } flag = _PyLong_AsInt(arg); if (flag == -1 && PyErr_Occurred()) { goto exit; @@ -4622,6 +4172,27 @@ _curses_use_default_colors(PyObject *module, PyObject *Py_UNUSED(ignored)) #endif /* !defined(STRICT_SYSV_CURSES) */ +PyDoc_STRVAR(_curses_has_extended_color_support__doc__, +"has_extended_color_support($module, /)\n" +"--\n" +"\n" +"Return True if the module supports extended colors; otherwise, return False.\n" +"\n" +"Extended color support allows more than 256 color-pairs for terminals\n" +"that support more than 16 colors (e.g. xterm-256color)."); + +#define _CURSES_HAS_EXTENDED_COLOR_SUPPORT_METHODDEF \ + {"has_extended_color_support", (PyCFunction)_curses_has_extended_color_support, METH_NOARGS, _curses_has_extended_color_support__doc__}, + +static PyObject * +_curses_has_extended_color_support_impl(PyObject *module); + +static PyObject * +_curses_has_extended_color_support(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_has_extended_color_support_impl(module); +} + #ifndef _CURSES_WINDOW_ENCLOSE_METHODDEF #define _CURSES_WINDOW_ENCLOSE_METHODDEF #endif /* !defined(_CURSES_WINDOW_ENCLOSE_METHODDEF) */ @@ -4713,4 +4284,4 @@ _curses_use_default_colors(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef _CURSES_USE_DEFAULT_COLORS_METHODDEF #define _CURSES_USE_DEFAULT_COLORS_METHODDEF #endif /* !defined(_CURSES_USE_DEFAULT_COLORS_METHODDEF) */ -/*[clinic end generated code: output=5e739120041df368 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9efc9943a3ac3741 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/_datetimemodule.c.h b/contrib/tools/python3/src/Modules/clinic/_datetimemodule.c.h index 973a4ea025..7bd7c1986d 100644 --- a/contrib/tools/python3/src/Modules/clinic/_datetimemodule.c.h +++ b/contrib/tools/python3/src/Modules/clinic/_datetimemodule.c.h @@ -35,29 +35,14 @@ iso_calendar_date_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) if (!fastargs) { goto exit; } - if (PyFloat_Check(fastargs[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } year = _PyLong_AsInt(fastargs[0]); if (year == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(fastargs[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } week = _PyLong_AsInt(fastargs[1]); if (week == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(fastargs[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } weekday = _PyLong_AsInt(fastargs[2]); if (weekday == -1 && PyErr_Occurred()) { goto exit; @@ -109,4 +94,4 @@ skip_optional_pos: exit: return return_value; } -/*[clinic end generated code: output=5e17549f29a439a5 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f61310936e3d8091 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/_dbmmodule.c.h b/contrib/tools/python3/src/Modules/clinic/_dbmmodule.c.h index a7d7350850..af288c2586 100644 --- a/contrib/tools/python3/src/Modules/clinic/_dbmmodule.c.h +++ b/contrib/tools/python3/src/Modules/clinic/_dbmmodule.c.h @@ -27,15 +27,26 @@ PyDoc_STRVAR(_dbm_dbm_keys__doc__, "Return a list of all keys in the database."); #define _DBM_DBM_KEYS_METHODDEF \ - {"keys", (PyCFunction)_dbm_dbm_keys, METH_NOARGS, _dbm_dbm_keys__doc__}, + {"keys", (PyCFunction)(void(*)(void))_dbm_dbm_keys, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _dbm_dbm_keys__doc__}, static PyObject * -_dbm_dbm_keys_impl(dbmobject *self); +_dbm_dbm_keys_impl(dbmobject *self, PyTypeObject *cls); static PyObject * -_dbm_dbm_keys(dbmobject *self, PyObject *Py_UNUSED(ignored)) +_dbm_dbm_keys(dbmobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return _dbm_dbm_keys_impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = {":keys", _keywords, 0}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser + )) { + goto exit; + } + return_value = _dbm_dbm_keys_impl(self, cls); + +exit: + return return_value; } PyDoc_STRVAR(_dbm_dbm_get__doc__, @@ -45,25 +56,27 @@ PyDoc_STRVAR(_dbm_dbm_get__doc__, "Return the value for key if present, otherwise default."); #define _DBM_DBM_GET_METHODDEF \ - {"get", (PyCFunction)(void(*)(void))_dbm_dbm_get, METH_FASTCALL, _dbm_dbm_get__doc__}, + {"get", (PyCFunction)(void(*)(void))_dbm_dbm_get, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _dbm_dbm_get__doc__}, static PyObject * -_dbm_dbm_get_impl(dbmobject *self, const char *key, +_dbm_dbm_get_impl(dbmobject *self, PyTypeObject *cls, const char *key, Py_ssize_clean_t key_length, PyObject *default_value); static PyObject * -_dbm_dbm_get(dbmobject *self, PyObject *const *args, Py_ssize_t nargs) +_dbm_dbm_get(dbmobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + static const char * const _keywords[] = {"", "", NULL}; + static _PyArg_Parser _parser = {"s#|O:get", _keywords, 0}; const char *key; Py_ssize_clean_t key_length; PyObject *default_value = Py_None; - if (!_PyArg_ParseStack(args, nargs, "s#|O:get", + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, &key, &key_length, &default_value)) { goto exit; } - return_value = _dbm_dbm_get_impl(self, key, key_length, default_value); + return_value = _dbm_dbm_get_impl(self, cls, key, key_length, default_value); exit: return return_value; @@ -78,26 +91,28 @@ PyDoc_STRVAR(_dbm_dbm_setdefault__doc__, "If key is not in the database, it is inserted with default as the value."); #define _DBM_DBM_SETDEFAULT_METHODDEF \ - {"setdefault", (PyCFunction)(void(*)(void))_dbm_dbm_setdefault, METH_FASTCALL, _dbm_dbm_setdefault__doc__}, + {"setdefault", (PyCFunction)(void(*)(void))_dbm_dbm_setdefault, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _dbm_dbm_setdefault__doc__}, static PyObject * -_dbm_dbm_setdefault_impl(dbmobject *self, const char *key, +_dbm_dbm_setdefault_impl(dbmobject *self, PyTypeObject *cls, const char *key, Py_ssize_clean_t key_length, PyObject *default_value); static PyObject * -_dbm_dbm_setdefault(dbmobject *self, PyObject *const *args, Py_ssize_t nargs) +_dbm_dbm_setdefault(dbmobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + static const char * const _keywords[] = {"", "", NULL}; + static _PyArg_Parser _parser = {"s#|O:setdefault", _keywords, 0}; const char *key; Py_ssize_clean_t key_length; PyObject *default_value = NULL; - if (!_PyArg_ParseStack(args, nargs, "s#|O:setdefault", + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, &key, &key_length, &default_value)) { goto exit; } - return_value = _dbm_dbm_setdefault_impl(self, key, key_length, default_value); + return_value = _dbm_dbm_setdefault_impl(self, cls, key, key_length, default_value); exit: return return_value; @@ -162,11 +177,6 @@ dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 3) { goto skip_optional; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } mode = _PyLong_AsInt(args[2]); if (mode == -1 && PyErr_Occurred()) { goto exit; @@ -177,4 +187,4 @@ skip_optional: exit: return return_value; } -/*[clinic end generated code: output=7ced103488cbca7a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=6947b1115df66f7c input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/_elementtree.c.h b/contrib/tools/python3/src/Modules/clinic/_elementtree.c.h index 034c1081dc..5ed5a6cadd 100644 --- a/contrib/tools/python3/src/Modules/clinic/_elementtree.c.h +++ b/contrib/tools/python3/src/Modules/clinic/_elementtree.c.h @@ -430,14 +430,9 @@ _elementtree_Element_insert(ElementObject *self, PyObject *const *args, Py_ssize if (!_PyArg_CheckPositional("insert", nargs, 2, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[0]); + PyObject *iobj = _PyNumber_Index(args[0]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -920,4 +915,4 @@ skip_optional: exit: return return_value; } -/*[clinic end generated code: output=18ddc3c84139443d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=992733cfc7390590 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/_gdbmmodule.c.h b/contrib/tools/python3/src/Modules/clinic/_gdbmmodule.c.h index 552bf6ed88..ea4ee7df00 100644 --- a/contrib/tools/python3/src/Modules/clinic/_gdbmmodule.c.h +++ b/contrib/tools/python3/src/Modules/clinic/_gdbmmodule.c.h @@ -12,10 +12,10 @@ PyDoc_STRVAR(_gdbm_gdbm_get__doc__, {"get", (PyCFunction)(void(*)(void))_gdbm_gdbm_get, METH_FASTCALL, _gdbm_gdbm_get__doc__}, static PyObject * -_gdbm_gdbm_get_impl(dbmobject *self, PyObject *key, PyObject *default_value); +_gdbm_gdbm_get_impl(gdbmobject *self, PyObject *key, PyObject *default_value); static PyObject * -_gdbm_gdbm_get(dbmobject *self, PyObject *const *args, Py_ssize_t nargs) +_gdbm_gdbm_get(gdbmobject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *key; @@ -46,11 +46,11 @@ PyDoc_STRVAR(_gdbm_gdbm_setdefault__doc__, {"setdefault", (PyCFunction)(void(*)(void))_gdbm_gdbm_setdefault, METH_FASTCALL, _gdbm_gdbm_setdefault__doc__}, static PyObject * -_gdbm_gdbm_setdefault_impl(dbmobject *self, PyObject *key, +_gdbm_gdbm_setdefault_impl(gdbmobject *self, PyObject *key, PyObject *default_value); static PyObject * -_gdbm_gdbm_setdefault(dbmobject *self, PyObject *const *args, Py_ssize_t nargs) +_gdbm_gdbm_setdefault(gdbmobject *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; PyObject *key; @@ -81,10 +81,10 @@ PyDoc_STRVAR(_gdbm_gdbm_close__doc__, {"close", (PyCFunction)_gdbm_gdbm_close, METH_NOARGS, _gdbm_gdbm_close__doc__}, static PyObject * -_gdbm_gdbm_close_impl(dbmobject *self); +_gdbm_gdbm_close_impl(gdbmobject *self); static PyObject * -_gdbm_gdbm_close(dbmobject *self, PyObject *Py_UNUSED(ignored)) +_gdbm_gdbm_close(gdbmobject *self, PyObject *Py_UNUSED(ignored)) { return _gdbm_gdbm_close_impl(self); } @@ -96,15 +96,26 @@ PyDoc_STRVAR(_gdbm_gdbm_keys__doc__, "Get a list of all keys in the database."); #define _GDBM_GDBM_KEYS_METHODDEF \ - {"keys", (PyCFunction)_gdbm_gdbm_keys, METH_NOARGS, _gdbm_gdbm_keys__doc__}, + {"keys", (PyCFunction)(void(*)(void))_gdbm_gdbm_keys, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _gdbm_gdbm_keys__doc__}, static PyObject * -_gdbm_gdbm_keys_impl(dbmobject *self); +_gdbm_gdbm_keys_impl(gdbmobject *self, PyTypeObject *cls); static PyObject * -_gdbm_gdbm_keys(dbmobject *self, PyObject *Py_UNUSED(ignored)) +_gdbm_gdbm_keys(gdbmobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return _gdbm_gdbm_keys_impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = {":keys", _keywords, 0}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser + )) { + goto exit; + } + return_value = _gdbm_gdbm_keys_impl(self, cls); + +exit: + return return_value; } PyDoc_STRVAR(_gdbm_gdbm_firstkey__doc__, @@ -118,15 +129,26 @@ PyDoc_STRVAR(_gdbm_gdbm_firstkey__doc__, "hash values, and won\'t be sorted by the key values."); #define _GDBM_GDBM_FIRSTKEY_METHODDEF \ - {"firstkey", (PyCFunction)_gdbm_gdbm_firstkey, METH_NOARGS, _gdbm_gdbm_firstkey__doc__}, + {"firstkey", (PyCFunction)(void(*)(void))_gdbm_gdbm_firstkey, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _gdbm_gdbm_firstkey__doc__}, static PyObject * -_gdbm_gdbm_firstkey_impl(dbmobject *self); +_gdbm_gdbm_firstkey_impl(gdbmobject *self, PyTypeObject *cls); static PyObject * -_gdbm_gdbm_firstkey(dbmobject *self, PyObject *Py_UNUSED(ignored)) +_gdbm_gdbm_firstkey(gdbmobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return _gdbm_gdbm_firstkey_impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = {":firstkey", _keywords, 0}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser + )) { + goto exit; + } + return_value = _gdbm_gdbm_firstkey_impl(self, cls); + +exit: + return return_value; } PyDoc_STRVAR(_gdbm_gdbm_nextkey__doc__, @@ -144,23 +166,26 @@ PyDoc_STRVAR(_gdbm_gdbm_nextkey__doc__, " k = db.nextkey(k)"); #define _GDBM_GDBM_NEXTKEY_METHODDEF \ - {"nextkey", (PyCFunction)_gdbm_gdbm_nextkey, METH_O, _gdbm_gdbm_nextkey__doc__}, + {"nextkey", (PyCFunction)(void(*)(void))_gdbm_gdbm_nextkey, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _gdbm_gdbm_nextkey__doc__}, static PyObject * -_gdbm_gdbm_nextkey_impl(dbmobject *self, const char *key, +_gdbm_gdbm_nextkey_impl(gdbmobject *self, PyTypeObject *cls, const char *key, Py_ssize_clean_t key_length); static PyObject * -_gdbm_gdbm_nextkey(dbmobject *self, PyObject *arg) +_gdbm_gdbm_nextkey(gdbmobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = {"s#:nextkey", _keywords, 0}; const char *key; Py_ssize_clean_t key_length; - if (!PyArg_Parse(arg, "s#:nextkey", &key, &key_length)) { + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &key, &key_length)) { goto exit; } - return_value = _gdbm_gdbm_nextkey_impl(self, key, key_length); + return_value = _gdbm_gdbm_nextkey_impl(self, cls, key, key_length); exit: return return_value; @@ -179,15 +204,26 @@ PyDoc_STRVAR(_gdbm_gdbm_reorganize__doc__, "kept and reused as new (key,value) pairs are added."); #define _GDBM_GDBM_REORGANIZE_METHODDEF \ - {"reorganize", (PyCFunction)_gdbm_gdbm_reorganize, METH_NOARGS, _gdbm_gdbm_reorganize__doc__}, + {"reorganize", (PyCFunction)(void(*)(void))_gdbm_gdbm_reorganize, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _gdbm_gdbm_reorganize__doc__}, static PyObject * -_gdbm_gdbm_reorganize_impl(dbmobject *self); +_gdbm_gdbm_reorganize_impl(gdbmobject *self, PyTypeObject *cls); static PyObject * -_gdbm_gdbm_reorganize(dbmobject *self, PyObject *Py_UNUSED(ignored)) +_gdbm_gdbm_reorganize(gdbmobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return _gdbm_gdbm_reorganize_impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = {":reorganize", _keywords, 0}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser + )) { + goto exit; + } + return_value = _gdbm_gdbm_reorganize_impl(self, cls); + +exit: + return return_value; } PyDoc_STRVAR(_gdbm_gdbm_sync__doc__, @@ -200,15 +236,26 @@ PyDoc_STRVAR(_gdbm_gdbm_sync__doc__, "any unwritten data to be written to the disk."); #define _GDBM_GDBM_SYNC_METHODDEF \ - {"sync", (PyCFunction)_gdbm_gdbm_sync, METH_NOARGS, _gdbm_gdbm_sync__doc__}, + {"sync", (PyCFunction)(void(*)(void))_gdbm_gdbm_sync, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _gdbm_gdbm_sync__doc__}, static PyObject * -_gdbm_gdbm_sync_impl(dbmobject *self); +_gdbm_gdbm_sync_impl(gdbmobject *self, PyTypeObject *cls); static PyObject * -_gdbm_gdbm_sync(dbmobject *self, PyObject *Py_UNUSED(ignored)) +_gdbm_gdbm_sync(gdbmobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return _gdbm_gdbm_sync_impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = {":sync", _keywords, 0}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser + )) { + goto exit; + } + return_value = _gdbm_gdbm_sync_impl(self, cls); + +exit: + return return_value; } PyDoc_STRVAR(dbmopen__doc__, @@ -283,11 +330,6 @@ dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 3) { goto skip_optional; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } mode = _PyLong_AsInt(args[2]); if (mode == -1 && PyErr_Occurred()) { goto exit; @@ -298,4 +340,4 @@ skip_optional: exit: return return_value; } -/*[clinic end generated code: output=f48d6e8d4c8a3465 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3b88446433e43d96 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/_hashopenssl.c.h b/contrib/tools/python3/src/Modules/clinic/_hashopenssl.c.h index 68aa765e52..de01489e6a 100644 --- a/contrib/tools/python3/src/Modules/clinic/_hashopenssl.c.h +++ b/contrib/tools/python3/src/Modules/clinic/_hashopenssl.c.h @@ -92,14 +92,9 @@ EVPXOF_digest(EVPobject *self, PyObject *const *args, Py_ssize_t nargs, PyObject if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[0]); + PyObject *iobj = _PyNumber_Index(args[0]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -144,14 +139,9 @@ EVPXOF_hexdigest(EVPobject *self, PyObject *const *args, Py_ssize_t nargs, PyObj if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[0]); + PyObject *iobj = _PyNumber_Index(args[0]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -936,11 +926,6 @@ pbkdf2_hmac(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject _PyArg_BadArgument("pbkdf2_hmac", "argument 'salt'", "contiguous buffer", args[2]); goto exit; } - if (PyFloat_Check(args[3])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } iterations = PyLong_AsLong(args[3]); if (iterations == -1 && PyErr_Occurred()) { goto exit; @@ -965,7 +950,7 @@ exit: return return_value; } -#if (OPENSSL_VERSION_NUMBER > 0x10100000L && !defined(OPENSSL_NO_SCRYPT) && !defined(LIBRESSL_VERSION_NUMBER)) +#if defined(PY_OPENSSL_HAS_SCRYPT) PyDoc_STRVAR(_hashlib_scrypt__doc__, "scrypt($module, /, password, *, salt=None, n=None, r=None, p=None,\n" @@ -1055,11 +1040,6 @@ _hashlib_scrypt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj } } if (args[5]) { - if (PyFloat_Check(args[5])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } maxmem = PyLong_AsLong(args[5]); if (maxmem == -1 && PyErr_Occurred()) { goto exit; @@ -1068,11 +1048,6 @@ _hashlib_scrypt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj goto skip_optional_kwonly; } } - if (PyFloat_Check(args[6])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } dklen = PyLong_AsLong(args[6]); if (dklen == -1 && PyErr_Occurred()) { goto exit; @@ -1093,7 +1068,7 @@ exit: return return_value; } -#endif /* (OPENSSL_VERSION_NUMBER > 0x10100000L && !defined(OPENSSL_NO_SCRYPT) && !defined(LIBRESSL_VERSION_NUMBER)) */ +#endif /* defined(PY_OPENSSL_HAS_SCRYPT) */ PyDoc_STRVAR(_hashlib_hmac_singleshot__doc__, "hmac_digest($module, /, key, msg, digest)\n" @@ -1106,7 +1081,7 @@ PyDoc_STRVAR(_hashlib_hmac_singleshot__doc__, static PyObject * _hashlib_hmac_singleshot_impl(PyObject *module, Py_buffer *key, - Py_buffer *msg, const char *digest); + Py_buffer *msg, PyObject *digest); static PyObject * _hashlib_hmac_singleshot(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -1117,7 +1092,7 @@ _hashlib_hmac_singleshot(PyObject *module, PyObject *const *args, Py_ssize_t nar PyObject *argsbuf[3]; Py_buffer key = {NULL, NULL}; Py_buffer msg = {NULL, NULL}; - const char *digest; + PyObject *digest; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); if (!args) { @@ -1137,19 +1112,7 @@ _hashlib_hmac_singleshot(PyObject *module, PyObject *const *args, Py_ssize_t nar _PyArg_BadArgument("hmac_digest", "argument 'msg'", "contiguous buffer", args[1]); goto exit; } - if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("hmac_digest", "argument 'digest'", "str", args[2]); - goto exit; - } - Py_ssize_t digest_length; - digest = PyUnicode_AsUTF8AndSize(args[2], &digest_length); - if (digest == NULL) { - goto exit; - } - if (strlen(digest) != (size_t)digest_length) { - PyErr_SetString(PyExc_ValueError, "embedded null character"); - goto exit; - } + digest = args[2]; return_value = _hashlib_hmac_singleshot_impl(module, &key, &msg, digest); exit: @@ -1176,7 +1139,7 @@ PyDoc_STRVAR(_hashlib_hmac_new__doc__, static PyObject * _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, PyObject *msg_obj, - const char *digestmod); + PyObject *digestmod); static PyObject * _hashlib_hmac_new(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -1188,7 +1151,7 @@ _hashlib_hmac_new(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyO Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; Py_buffer key = {NULL, NULL}; PyObject *msg_obj = NULL; - const char *digestmod = NULL; + PyObject *digestmod = NULL; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf); if (!args) { @@ -1210,19 +1173,7 @@ _hashlib_hmac_new(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyO goto skip_optional_pos; } } - if (!PyUnicode_Check(args[2])) { - _PyArg_BadArgument("hmac_new", "argument 'digestmod'", "str", args[2]); - goto exit; - } - Py_ssize_t digestmod_length; - digestmod = PyUnicode_AsUTF8AndSize(args[2], &digestmod_length); - if (digestmod == NULL) { - goto exit; - } - if (strlen(digestmod) != (size_t)digestmod_length) { - PyErr_SetString(PyExc_ValueError, "embedded null character"); - goto exit; - } + digestmod = args[2]; skip_optional_pos: return_value = _hashlib_hmac_new_impl(module, &key, msg_obj, digestmod); @@ -1324,8 +1275,6 @@ _hashlib_HMAC_hexdigest(HMACobject *self, PyObject *Py_UNUSED(ignored)) return _hashlib_HMAC_hexdigest_impl(self); } -#if !defined(LIBRESSL_VERSION_NUMBER) - PyDoc_STRVAR(_hashlib_get_fips_mode__doc__, "get_fips_mode($module, /)\n" "--\n" @@ -1361,8 +1310,6 @@ exit: return return_value; } -#endif /* !defined(LIBRESSL_VERSION_NUMBER) */ - PyDoc_STRVAR(_hashlib_compare_digest__doc__, "compare_digest($module, a, b, /)\n" "--\n" @@ -1438,8 +1385,4 @@ exit: #ifndef _HASHLIB_SCRYPT_METHODDEF #define _HASHLIB_SCRYPT_METHODDEF #endif /* !defined(_HASHLIB_SCRYPT_METHODDEF) */ - -#ifndef _HASHLIB_GET_FIPS_MODE_METHODDEF - #define _HASHLIB_GET_FIPS_MODE_METHODDEF -#endif /* !defined(_HASHLIB_GET_FIPS_MODE_METHODDEF) */ -/*[clinic end generated code: output=b6b280e46bf0b139 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=162369cb9d43f1cc input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/_heapqmodule.c.h b/contrib/tools/python3/src/Modules/clinic/_heapqmodule.c.h index 55403706ba..a894315a76 100644 --- a/contrib/tools/python3/src/Modules/clinic/_heapqmodule.c.h +++ b/contrib/tools/python3/src/Modules/clinic/_heapqmodule.c.h @@ -24,6 +24,10 @@ _heapq_heappush(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("heappush", nargs, 2, 2)) { goto exit; } + if (!PyList_Check(args[0])) { + _PyArg_BadArgument("heappush", "argument 1", "list", args[0]); + goto exit; + } heap = args[0]; item = args[1]; return_value = _heapq_heappush_impl(module, heap, item); @@ -41,6 +45,26 @@ PyDoc_STRVAR(_heapq_heappop__doc__, #define _HEAPQ_HEAPPOP_METHODDEF \ {"heappop", (PyCFunction)_heapq_heappop, METH_O, _heapq_heappop__doc__}, +static PyObject * +_heapq_heappop_impl(PyObject *module, PyObject *heap); + +static PyObject * +_heapq_heappop(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyObject *heap; + + if (!PyList_Check(arg)) { + _PyArg_BadArgument("heappop", "argument", "list", arg); + goto exit; + } + heap = arg; + return_value = _heapq_heappop_impl(module, heap); + +exit: + return return_value; +} + PyDoc_STRVAR(_heapq_heapreplace__doc__, "heapreplace($module, heap, item, /)\n" "--\n" @@ -71,6 +95,10 @@ _heapq_heapreplace(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("heapreplace", nargs, 2, 2)) { goto exit; } + if (!PyList_Check(args[0])) { + _PyArg_BadArgument("heapreplace", "argument 1", "list", args[0]); + goto exit; + } heap = args[0]; item = args[1]; return_value = _heapq_heapreplace_impl(module, heap, item); @@ -104,6 +132,10 @@ _heapq_heappushpop(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("heappushpop", nargs, 2, 2)) { goto exit; } + if (!PyList_Check(args[0])) { + _PyArg_BadArgument("heappushpop", "argument 1", "list", args[0]); + goto exit; + } heap = args[0]; item = args[1]; return_value = _heapq_heappushpop_impl(module, heap, item); @@ -121,6 +153,26 @@ PyDoc_STRVAR(_heapq_heapify__doc__, #define _HEAPQ_HEAPIFY_METHODDEF \ {"heapify", (PyCFunction)_heapq_heapify, METH_O, _heapq_heapify__doc__}, +static PyObject * +_heapq_heapify_impl(PyObject *module, PyObject *heap); + +static PyObject * +_heapq_heapify(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyObject *heap; + + if (!PyList_Check(arg)) { + _PyArg_BadArgument("heapify", "argument", "list", arg); + goto exit; + } + heap = arg; + return_value = _heapq_heapify_impl(module, heap); + +exit: + return return_value; +} + PyDoc_STRVAR(_heapq__heappop_max__doc__, "_heappop_max($module, heap, /)\n" "--\n" @@ -130,6 +182,26 @@ PyDoc_STRVAR(_heapq__heappop_max__doc__, #define _HEAPQ__HEAPPOP_MAX_METHODDEF \ {"_heappop_max", (PyCFunction)_heapq__heappop_max, METH_O, _heapq__heappop_max__doc__}, +static PyObject * +_heapq__heappop_max_impl(PyObject *module, PyObject *heap); + +static PyObject * +_heapq__heappop_max(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyObject *heap; + + if (!PyList_Check(arg)) { + _PyArg_BadArgument("_heappop_max", "argument", "list", arg); + goto exit; + } + heap = arg; + return_value = _heapq__heappop_max_impl(module, heap); + +exit: + return return_value; +} + PyDoc_STRVAR(_heapq__heapreplace_max__doc__, "_heapreplace_max($module, heap, item, /)\n" "--\n" @@ -153,6 +225,10 @@ _heapq__heapreplace_max(PyObject *module, PyObject *const *args, Py_ssize_t narg if (!_PyArg_CheckPositional("_heapreplace_max", nargs, 2, 2)) { goto exit; } + if (!PyList_Check(args[0])) { + _PyArg_BadArgument("_heapreplace_max", "argument 1", "list", args[0]); + goto exit; + } heap = args[0]; item = args[1]; return_value = _heapq__heapreplace_max_impl(module, heap, item); @@ -169,4 +245,24 @@ PyDoc_STRVAR(_heapq__heapify_max__doc__, #define _HEAPQ__HEAPIFY_MAX_METHODDEF \ {"_heapify_max", (PyCFunction)_heapq__heapify_max, METH_O, _heapq__heapify_max__doc__}, -/*[clinic end generated code: output=37ef2a3319971c8d input=a9049054013a1b77]*/ + +static PyObject * +_heapq__heapify_max_impl(PyObject *module, PyObject *heap); + +static PyObject * +_heapq__heapify_max(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyObject *heap; + + if (!PyList_Check(arg)) { + _PyArg_BadArgument("_heapify_max", "argument", "list", arg); + goto exit; + } + heap = arg; + return_value = _heapq__heapify_max_impl(module, heap); + +exit: + return return_value; +} +/*[clinic end generated code: output=9975cf51762878d5 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/_localemodule.c.h b/contrib/tools/python3/src/Modules/clinic/_localemodule.c.h new file mode 100644 index 0000000000..703d034c32 --- /dev/null +++ b/contrib/tools/python3/src/Modules/clinic/_localemodule.c.h @@ -0,0 +1,605 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(_locale_setlocale__doc__, +"setlocale($module, category, locale=<unrepresentable>, /)\n" +"--\n" +"\n" +"Activates/queries locale processing."); + +#define _LOCALE_SETLOCALE_METHODDEF \ + {"setlocale", (PyCFunction)(void(*)(void))_locale_setlocale, METH_FASTCALL, _locale_setlocale__doc__}, + +static PyObject * +_locale_setlocale_impl(PyObject *module, int category, const char *locale); + +static PyObject * +_locale_setlocale(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int category; + const char *locale = NULL; + + if (!_PyArg_CheckPositional("setlocale", nargs, 1, 2)) { + goto exit; + } + category = _PyLong_AsInt(args[0]); + if (category == -1 && PyErr_Occurred()) { + goto exit; + } + if (nargs < 2) { + goto skip_optional; + } + if (args[1] == Py_None) { + locale = NULL; + } + else if (PyUnicode_Check(args[1])) { + Py_ssize_t locale_length; + locale = PyUnicode_AsUTF8AndSize(args[1], &locale_length); + if (locale == NULL) { + goto exit; + } + if (strlen(locale) != (size_t)locale_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + } + else { + _PyArg_BadArgument("setlocale", "argument 2", "str or None", args[1]); + goto exit; + } +skip_optional: + return_value = _locale_setlocale_impl(module, category, locale); + +exit: + return return_value; +} + +PyDoc_STRVAR(_locale_localeconv__doc__, +"localeconv($module, /)\n" +"--\n" +"\n" +"Returns numeric and monetary locale-specific parameters."); + +#define _LOCALE_LOCALECONV_METHODDEF \ + {"localeconv", (PyCFunction)_locale_localeconv, METH_NOARGS, _locale_localeconv__doc__}, + +static PyObject * +_locale_localeconv_impl(PyObject *module); + +static PyObject * +_locale_localeconv(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _locale_localeconv_impl(module); +} + +#if defined(HAVE_WCSCOLL) + +PyDoc_STRVAR(_locale_strcoll__doc__, +"strcoll($module, os1, os2, /)\n" +"--\n" +"\n" +"Compares two strings according to the locale."); + +#define _LOCALE_STRCOLL_METHODDEF \ + {"strcoll", (PyCFunction)(void(*)(void))_locale_strcoll, METH_FASTCALL, _locale_strcoll__doc__}, + +static PyObject * +_locale_strcoll_impl(PyObject *module, PyObject *os1, PyObject *os2); + +static PyObject * +_locale_strcoll(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *os1; + PyObject *os2; + + if (!_PyArg_CheckPositional("strcoll", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("strcoll", "argument 1", "str", args[0]); + goto exit; + } + if (PyUnicode_READY(args[0]) == -1) { + goto exit; + } + os1 = args[0]; + if (!PyUnicode_Check(args[1])) { + _PyArg_BadArgument("strcoll", "argument 2", "str", args[1]); + goto exit; + } + if (PyUnicode_READY(args[1]) == -1) { + goto exit; + } + os2 = args[1]; + return_value = _locale_strcoll_impl(module, os1, os2); + +exit: + return return_value; +} + +#endif /* defined(HAVE_WCSCOLL) */ + +#if defined(HAVE_WCSXFRM) + +PyDoc_STRVAR(_locale_strxfrm__doc__, +"strxfrm($module, string, /)\n" +"--\n" +"\n" +"Return a string that can be used as a key for locale-aware comparisons."); + +#define _LOCALE_STRXFRM_METHODDEF \ + {"strxfrm", (PyCFunction)_locale_strxfrm, METH_O, _locale_strxfrm__doc__}, + +static PyObject * +_locale_strxfrm_impl(PyObject *module, PyObject *str); + +static PyObject * +_locale_strxfrm(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyObject *str; + + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("strxfrm", "argument", "str", arg); + goto exit; + } + if (PyUnicode_READY(arg) == -1) { + goto exit; + } + str = arg; + return_value = _locale_strxfrm_impl(module, str); + +exit: + return return_value; +} + +#endif /* defined(HAVE_WCSXFRM) */ + +#if defined(MS_WINDOWS) + +PyDoc_STRVAR(_locale__getdefaultlocale__doc__, +"_getdefaultlocale($module, /)\n" +"--\n" +"\n"); + +#define _LOCALE__GETDEFAULTLOCALE_METHODDEF \ + {"_getdefaultlocale", (PyCFunction)_locale__getdefaultlocale, METH_NOARGS, _locale__getdefaultlocale__doc__}, + +static PyObject * +_locale__getdefaultlocale_impl(PyObject *module); + +static PyObject * +_locale__getdefaultlocale(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _locale__getdefaultlocale_impl(module); +} + +#endif /* defined(MS_WINDOWS) */ + +#if defined(HAVE_LANGINFO_H) + +PyDoc_STRVAR(_locale_nl_langinfo__doc__, +"nl_langinfo($module, key, /)\n" +"--\n" +"\n" +"Return the value for the locale information associated with key."); + +#define _LOCALE_NL_LANGINFO_METHODDEF \ + {"nl_langinfo", (PyCFunction)_locale_nl_langinfo, METH_O, _locale_nl_langinfo__doc__}, + +static PyObject * +_locale_nl_langinfo_impl(PyObject *module, int item); + +static PyObject * +_locale_nl_langinfo(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int item; + + item = _PyLong_AsInt(arg); + if (item == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _locale_nl_langinfo_impl(module, item); + +exit: + return return_value; +} + +#endif /* defined(HAVE_LANGINFO_H) */ + +#if defined(HAVE_LIBINTL_H) + +PyDoc_STRVAR(_locale_gettext__doc__, +"gettext($module, msg, /)\n" +"--\n" +"\n" +"gettext(msg) -> string\n" +"\n" +"Return translation of msg."); + +#define _LOCALE_GETTEXT_METHODDEF \ + {"gettext", (PyCFunction)_locale_gettext, METH_O, _locale_gettext__doc__}, + +static PyObject * +_locale_gettext_impl(PyObject *module, const char *in); + +static PyObject * +_locale_gettext(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *in; + + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("gettext", "argument", "str", arg); + goto exit; + } + Py_ssize_t in_length; + in = PyUnicode_AsUTF8AndSize(arg, &in_length); + if (in == NULL) { + goto exit; + } + if (strlen(in) != (size_t)in_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + return_value = _locale_gettext_impl(module, in); + +exit: + return return_value; +} + +#endif /* defined(HAVE_LIBINTL_H) */ + +#if defined(HAVE_LIBINTL_H) + +PyDoc_STRVAR(_locale_dgettext__doc__, +"dgettext($module, domain, msg, /)\n" +"--\n" +"\n" +"dgettext(domain, msg) -> string\n" +"\n" +"Return translation of msg in domain."); + +#define _LOCALE_DGETTEXT_METHODDEF \ + {"dgettext", (PyCFunction)(void(*)(void))_locale_dgettext, METH_FASTCALL, _locale_dgettext__doc__}, + +static PyObject * +_locale_dgettext_impl(PyObject *module, const char *domain, const char *in); + +static PyObject * +_locale_dgettext(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + const char *domain; + const char *in; + + if (!_PyArg_CheckPositional("dgettext", nargs, 2, 2)) { + goto exit; + } + if (args[0] == Py_None) { + domain = NULL; + } + else if (PyUnicode_Check(args[0])) { + Py_ssize_t domain_length; + domain = PyUnicode_AsUTF8AndSize(args[0], &domain_length); + if (domain == NULL) { + goto exit; + } + if (strlen(domain) != (size_t)domain_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + } + else { + _PyArg_BadArgument("dgettext", "argument 1", "str or None", args[0]); + goto exit; + } + if (!PyUnicode_Check(args[1])) { + _PyArg_BadArgument("dgettext", "argument 2", "str", args[1]); + goto exit; + } + Py_ssize_t in_length; + in = PyUnicode_AsUTF8AndSize(args[1], &in_length); + if (in == NULL) { + goto exit; + } + if (strlen(in) != (size_t)in_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + return_value = _locale_dgettext_impl(module, domain, in); + +exit: + return return_value; +} + +#endif /* defined(HAVE_LIBINTL_H) */ + +#if defined(HAVE_LIBINTL_H) + +PyDoc_STRVAR(_locale_dcgettext__doc__, +"dcgettext($module, domain, msg, category, /)\n" +"--\n" +"\n" +"Return translation of msg in domain and category."); + +#define _LOCALE_DCGETTEXT_METHODDEF \ + {"dcgettext", (PyCFunction)(void(*)(void))_locale_dcgettext, METH_FASTCALL, _locale_dcgettext__doc__}, + +static PyObject * +_locale_dcgettext_impl(PyObject *module, const char *domain, + const char *msgid, int category); + +static PyObject * +_locale_dcgettext(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + const char *domain; + const char *msgid; + int category; + + if (!_PyArg_CheckPositional("dcgettext", nargs, 3, 3)) { + goto exit; + } + if (args[0] == Py_None) { + domain = NULL; + } + else if (PyUnicode_Check(args[0])) { + Py_ssize_t domain_length; + domain = PyUnicode_AsUTF8AndSize(args[0], &domain_length); + if (domain == NULL) { + goto exit; + } + if (strlen(domain) != (size_t)domain_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + } + else { + _PyArg_BadArgument("dcgettext", "argument 1", "str or None", args[0]); + goto exit; + } + if (!PyUnicode_Check(args[1])) { + _PyArg_BadArgument("dcgettext", "argument 2", "str", args[1]); + goto exit; + } + Py_ssize_t msgid_length; + msgid = PyUnicode_AsUTF8AndSize(args[1], &msgid_length); + if (msgid == NULL) { + goto exit; + } + if (strlen(msgid) != (size_t)msgid_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + category = _PyLong_AsInt(args[2]); + if (category == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _locale_dcgettext_impl(module, domain, msgid, category); + +exit: + return return_value; +} + +#endif /* defined(HAVE_LIBINTL_H) */ + +#if defined(HAVE_LIBINTL_H) + +PyDoc_STRVAR(_locale_textdomain__doc__, +"textdomain($module, domain, /)\n" +"--\n" +"\n" +"Set the C library\'s textdmain to domain, returning the new domain."); + +#define _LOCALE_TEXTDOMAIN_METHODDEF \ + {"textdomain", (PyCFunction)_locale_textdomain, METH_O, _locale_textdomain__doc__}, + +static PyObject * +_locale_textdomain_impl(PyObject *module, const char *domain); + +static PyObject * +_locale_textdomain(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *domain; + + if (arg == Py_None) { + domain = NULL; + } + else if (PyUnicode_Check(arg)) { + Py_ssize_t domain_length; + domain = PyUnicode_AsUTF8AndSize(arg, &domain_length); + if (domain == NULL) { + goto exit; + } + if (strlen(domain) != (size_t)domain_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + } + else { + _PyArg_BadArgument("textdomain", "argument", "str or None", arg); + goto exit; + } + return_value = _locale_textdomain_impl(module, domain); + +exit: + return return_value; +} + +#endif /* defined(HAVE_LIBINTL_H) */ + +#if defined(HAVE_LIBINTL_H) + +PyDoc_STRVAR(_locale_bindtextdomain__doc__, +"bindtextdomain($module, domain, dir, /)\n" +"--\n" +"\n" +"Bind the C library\'s domain to dir."); + +#define _LOCALE_BINDTEXTDOMAIN_METHODDEF \ + {"bindtextdomain", (PyCFunction)(void(*)(void))_locale_bindtextdomain, METH_FASTCALL, _locale_bindtextdomain__doc__}, + +static PyObject * +_locale_bindtextdomain_impl(PyObject *module, const char *domain, + PyObject *dirname_obj); + +static PyObject * +_locale_bindtextdomain(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + const char *domain; + PyObject *dirname_obj; + + if (!_PyArg_CheckPositional("bindtextdomain", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("bindtextdomain", "argument 1", "str", args[0]); + goto exit; + } + Py_ssize_t domain_length; + domain = PyUnicode_AsUTF8AndSize(args[0], &domain_length); + if (domain == NULL) { + goto exit; + } + if (strlen(domain) != (size_t)domain_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + dirname_obj = args[1]; + return_value = _locale_bindtextdomain_impl(module, domain, dirname_obj); + +exit: + return return_value; +} + +#endif /* defined(HAVE_LIBINTL_H) */ + +#if defined(HAVE_LIBINTL_H) && defined(HAVE_BIND_TEXTDOMAIN_CODESET) + +PyDoc_STRVAR(_locale_bind_textdomain_codeset__doc__, +"bind_textdomain_codeset($module, domain, codeset, /)\n" +"--\n" +"\n" +"Bind the C library\'s domain to codeset."); + +#define _LOCALE_BIND_TEXTDOMAIN_CODESET_METHODDEF \ + {"bind_textdomain_codeset", (PyCFunction)(void(*)(void))_locale_bind_textdomain_codeset, METH_FASTCALL, _locale_bind_textdomain_codeset__doc__}, + +static PyObject * +_locale_bind_textdomain_codeset_impl(PyObject *module, const char *domain, + const char *codeset); + +static PyObject * +_locale_bind_textdomain_codeset(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + const char *domain; + const char *codeset; + + if (!_PyArg_CheckPositional("bind_textdomain_codeset", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("bind_textdomain_codeset", "argument 1", "str", args[0]); + goto exit; + } + Py_ssize_t domain_length; + domain = PyUnicode_AsUTF8AndSize(args[0], &domain_length); + if (domain == NULL) { + goto exit; + } + if (strlen(domain) != (size_t)domain_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + if (args[1] == Py_None) { + codeset = NULL; + } + else if (PyUnicode_Check(args[1])) { + Py_ssize_t codeset_length; + codeset = PyUnicode_AsUTF8AndSize(args[1], &codeset_length); + if (codeset == NULL) { + goto exit; + } + if (strlen(codeset) != (size_t)codeset_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + } + else { + _PyArg_BadArgument("bind_textdomain_codeset", "argument 2", "str or None", args[1]); + goto exit; + } + return_value = _locale_bind_textdomain_codeset_impl(module, domain, codeset); + +exit: + return return_value; +} + +#endif /* defined(HAVE_LIBINTL_H) && defined(HAVE_BIND_TEXTDOMAIN_CODESET) */ + +PyDoc_STRVAR(_locale__get_locale_encoding__doc__, +"_get_locale_encoding($module, /)\n" +"--\n" +"\n" +"Get the current locale encoding."); + +#define _LOCALE__GET_LOCALE_ENCODING_METHODDEF \ + {"_get_locale_encoding", (PyCFunction)_locale__get_locale_encoding, METH_NOARGS, _locale__get_locale_encoding__doc__}, + +static PyObject * +_locale__get_locale_encoding_impl(PyObject *module); + +static PyObject * +_locale__get_locale_encoding(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _locale__get_locale_encoding_impl(module); +} + +#ifndef _LOCALE_STRCOLL_METHODDEF + #define _LOCALE_STRCOLL_METHODDEF +#endif /* !defined(_LOCALE_STRCOLL_METHODDEF) */ + +#ifndef _LOCALE_STRXFRM_METHODDEF + #define _LOCALE_STRXFRM_METHODDEF +#endif /* !defined(_LOCALE_STRXFRM_METHODDEF) */ + +#ifndef _LOCALE__GETDEFAULTLOCALE_METHODDEF + #define _LOCALE__GETDEFAULTLOCALE_METHODDEF +#endif /* !defined(_LOCALE__GETDEFAULTLOCALE_METHODDEF) */ + +#ifndef _LOCALE_NL_LANGINFO_METHODDEF + #define _LOCALE_NL_LANGINFO_METHODDEF +#endif /* !defined(_LOCALE_NL_LANGINFO_METHODDEF) */ + +#ifndef _LOCALE_GETTEXT_METHODDEF + #define _LOCALE_GETTEXT_METHODDEF +#endif /* !defined(_LOCALE_GETTEXT_METHODDEF) */ + +#ifndef _LOCALE_DGETTEXT_METHODDEF + #define _LOCALE_DGETTEXT_METHODDEF +#endif /* !defined(_LOCALE_DGETTEXT_METHODDEF) */ + +#ifndef _LOCALE_DCGETTEXT_METHODDEF + #define _LOCALE_DCGETTEXT_METHODDEF +#endif /* !defined(_LOCALE_DCGETTEXT_METHODDEF) */ + +#ifndef _LOCALE_TEXTDOMAIN_METHODDEF + #define _LOCALE_TEXTDOMAIN_METHODDEF +#endif /* !defined(_LOCALE_TEXTDOMAIN_METHODDEF) */ + +#ifndef _LOCALE_BINDTEXTDOMAIN_METHODDEF + #define _LOCALE_BINDTEXTDOMAIN_METHODDEF +#endif /* !defined(_LOCALE_BINDTEXTDOMAIN_METHODDEF) */ + +#ifndef _LOCALE_BIND_TEXTDOMAIN_CODESET_METHODDEF + #define _LOCALE_BIND_TEXTDOMAIN_CODESET_METHODDEF +#endif /* !defined(_LOCALE_BIND_TEXTDOMAIN_CODESET_METHODDEF) */ +/*[clinic end generated code: output=cd703c8a3a75fcf4 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/_lsprof.c.h b/contrib/tools/python3/src/Modules/clinic/_lsprof.c.h new file mode 100644 index 0000000000..5d9c209eab --- /dev/null +++ b/contrib/tools/python3/src/Modules/clinic/_lsprof.c.h @@ -0,0 +1,55 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(_lsprof_Profiler_getstats__doc__, +"getstats($self, /)\n" +"--\n" +"\n" +"list of profiler_entry objects.\n" +"\n" +"getstats() -> list of profiler_entry objects\n" +"\n" +"Return all information collected by the profiler.\n" +"Each profiler_entry is a tuple-like object with the\n" +"following attributes:\n" +"\n" +" code code object\n" +" callcount how many times this was called\n" +" reccallcount how many times called recursively\n" +" totaltime total time in this entry\n" +" inlinetime inline time in this entry (not in subcalls)\n" +" calls details of the calls\n" +"\n" +"The calls attribute is either None or a list of\n" +"profiler_subentry objects:\n" +"\n" +" code called code object\n" +" callcount how many times this is called\n" +" reccallcount how many times this is called recursively\n" +" totaltime total time spent in this call\n" +" inlinetime inline time (not in further subcalls)"); + +#define _LSPROF_PROFILER_GETSTATS_METHODDEF \ + {"getstats", (PyCFunction)(void(*)(void))_lsprof_Profiler_getstats, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _lsprof_Profiler_getstats__doc__}, + +static PyObject * +_lsprof_Profiler_getstats_impl(ProfilerObject *self, PyTypeObject *cls); + +static PyObject * +_lsprof_Profiler_getstats(ProfilerObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = {":getstats", _keywords, 0}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser + )) { + goto exit; + } + return_value = _lsprof_Profiler_getstats_impl(self, cls); + +exit: + return return_value; +} +/*[clinic end generated code: output=b4727cfebecdd22d input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/_lzmamodule.c.h b/contrib/tools/python3/src/Modules/clinic/_lzmamodule.c.h index 82ef4d517d..526031ade3 100644 --- a/contrib/tools/python3/src/Modules/clinic/_lzmamodule.c.h +++ b/contrib/tools/python3/src/Modules/clinic/_lzmamodule.c.h @@ -116,14 +116,9 @@ _lzma_LZMADecompressor_decompress(Decompressor *self, PyObject *const *args, Py_ if (!noptargs) { goto skip_optional_pos; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[1]); + PyObject *iobj = _PyNumber_Index(args[1]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -194,11 +189,6 @@ _lzma_LZMADecompressor___init__(PyObject *self, PyObject *args, PyObject *kwargs goto skip_optional_pos; } if (fastargs[0]) { - if (PyFloat_Check(fastargs[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } format = _PyLong_AsInt(fastargs[0]); if (format == -1 && PyErr_Occurred()) { goto exit; @@ -241,11 +231,6 @@ _lzma_is_check_supported(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int check_id; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } check_id = _PyLong_AsInt(arg); if (check_id == -1 && PyErr_Occurred()) { goto exit; @@ -256,39 +241,6 @@ exit: return return_value; } -PyDoc_STRVAR(_lzma__encode_filter_properties__doc__, -"_encode_filter_properties($module, filter, /)\n" -"--\n" -"\n" -"Return a bytes object encoding the options (properties) of the filter specified by *filter* (a dict).\n" -"\n" -"The result does not include the filter ID itself, only the options."); - -#define _LZMA__ENCODE_FILTER_PROPERTIES_METHODDEF \ - {"_encode_filter_properties", (PyCFunction)_lzma__encode_filter_properties, METH_O, _lzma__encode_filter_properties__doc__}, - -static PyObject * -_lzma__encode_filter_properties_impl(PyObject *module, lzma_filter filter); - -static PyObject * -_lzma__encode_filter_properties(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - lzma_filter filter = {LZMA_VLI_UNKNOWN, NULL}; - - if (!lzma_filter_converter(arg, &filter)) { - goto exit; - } - return_value = _lzma__encode_filter_properties_impl(module, filter); - -exit: - /* Cleanup for filter */ - if (filter.id != LZMA_VLI_UNKNOWN) - PyMem_Free(filter.options); - - return return_value; -} - PyDoc_STRVAR(_lzma__decode_filter_properties__doc__, "_decode_filter_properties($module, filter_id, encoded_props, /)\n" "--\n" @@ -334,4 +286,4 @@ exit: return return_value; } -/*[clinic end generated code: output=f7477a10e86a717d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=867b9e334053b679 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/_opcode.c.h b/contrib/tools/python3/src/Modules/clinic/_opcode.c.h index 777701ff14..6915f21d64 100644 --- a/contrib/tools/python3/src/Modules/clinic/_opcode.c.h +++ b/contrib/tools/python3/src/Modules/clinic/_opcode.c.h @@ -32,11 +32,6 @@ _opcode_stack_effect(PyObject *module, PyObject *const *args, Py_ssize_t nargs, if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } opcode = _PyLong_AsInt(args[0]); if (opcode == -1 && PyErr_Occurred()) { goto exit; @@ -61,4 +56,4 @@ skip_optional_kwonly: exit: return return_value; } -/*[clinic end generated code: output=7bc08f2835b2cf89 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=bcf66d25c2624197 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/_operator.c.h b/contrib/tools/python3/src/Modules/clinic/_operator.c.h index 0e39f3b77a..bda2eba6d1 100644 --- a/contrib/tools/python3/src/Modules/clinic/_operator.c.h +++ b/contrib/tools/python3/src/Modules/clinic/_operator.c.h @@ -1424,14 +1424,9 @@ _operator_length_hint(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 2) { goto skip_optional; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[1]); + PyObject *iobj = _PyNumber_Index(args[1]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -1491,4 +1486,4 @@ _operator__compare_digest(PyObject *module, PyObject *const *args, Py_ssize_t na exit: return return_value; } -/*[clinic end generated code: output=ed2bc172e42320d8 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=16749e11fda51785 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/_queuemodule.c.h b/contrib/tools/python3/src/Modules/clinic/_queuemodule.c.h index c25eacf08b..8741f7d9af 100644 --- a/contrib/tools/python3/src/Modules/clinic/_queuemodule.c.h +++ b/contrib/tools/python3/src/Modules/clinic/_queuemodule.c.h @@ -16,11 +16,11 @@ simplequeue_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; - if ((type == &PySimpleQueueType) && + if ((type == simplequeue_get_state_by_type(type)->SimpleQueueType) && !_PyArg_NoPositional("SimpleQueue", args)) { goto exit; } - if ((type == &PySimpleQueueType) && + if ((type == simplequeue_get_state_by_type(type)->SimpleQueueType) && !_PyArg_NoKeywords("SimpleQueue", kwargs)) { goto exit; } @@ -133,42 +133,26 @@ PyDoc_STRVAR(_queue_SimpleQueue_get__doc__, "in that case)."); #define _QUEUE_SIMPLEQUEUE_GET_METHODDEF \ - {"get", (PyCFunction)(void(*)(void))_queue_SimpleQueue_get, METH_FASTCALL|METH_KEYWORDS, _queue_SimpleQueue_get__doc__}, + {"get", (PyCFunction)(void(*)(void))_queue_SimpleQueue_get, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _queue_SimpleQueue_get__doc__}, static PyObject * -_queue_SimpleQueue_get_impl(simplequeueobject *self, int block, - PyObject *timeout); +_queue_SimpleQueue_get_impl(simplequeueobject *self, PyTypeObject *cls, + int block, PyObject *timeout); static PyObject * -_queue_SimpleQueue_get(simplequeueobject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +_queue_SimpleQueue_get(simplequeueobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"block", "timeout", NULL}; - static _PyArg_Parser _parser = {NULL, _keywords, "get", 0}; - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + static _PyArg_Parser _parser = {"|pO:get", _keywords, 0}; int block = 1; PyObject *timeout = Py_None; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 2, 0, argsbuf); - if (!args) { + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &block, &timeout)) { goto exit; } - if (!noptargs) { - goto skip_optional_pos; - } - if (args[0]) { - block = PyObject_IsTrue(args[0]); - if (block < 0) { - goto exit; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - timeout = args[1]; -skip_optional_pos: - return_value = _queue_SimpleQueue_get_impl(self, block, timeout); + return_value = _queue_SimpleQueue_get_impl(self, cls, block, timeout); exit: return return_value; @@ -184,15 +168,27 @@ PyDoc_STRVAR(_queue_SimpleQueue_get_nowait__doc__, "raise the Empty exception."); #define _QUEUE_SIMPLEQUEUE_GET_NOWAIT_METHODDEF \ - {"get_nowait", (PyCFunction)_queue_SimpleQueue_get_nowait, METH_NOARGS, _queue_SimpleQueue_get_nowait__doc__}, + {"get_nowait", (PyCFunction)(void(*)(void))_queue_SimpleQueue_get_nowait, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _queue_SimpleQueue_get_nowait__doc__}, static PyObject * -_queue_SimpleQueue_get_nowait_impl(simplequeueobject *self); +_queue_SimpleQueue_get_nowait_impl(simplequeueobject *self, + PyTypeObject *cls); static PyObject * -_queue_SimpleQueue_get_nowait(simplequeueobject *self, PyObject *Py_UNUSED(ignored)) +_queue_SimpleQueue_get_nowait(simplequeueobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return _queue_SimpleQueue_get_nowait_impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = {":get_nowait", _keywords, 0}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser + )) { + goto exit; + } + return_value = _queue_SimpleQueue_get_nowait_impl(self, cls); + +exit: + return return_value; } PyDoc_STRVAR(_queue_SimpleQueue_empty__doc__, @@ -250,4 +246,4 @@ _queue_SimpleQueue_qsize(simplequeueobject *self, PyObject *Py_UNUSED(ignored)) exit: return return_value; } -/*[clinic end generated code: output=b4717e2974cbc909 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ce56b46fac150909 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/_randommodule.c.h b/contrib/tools/python3/src/Modules/clinic/_randommodule.c.h index a467811d93..b3cd435b6f 100644 --- a/contrib/tools/python3/src/Modules/clinic/_randommodule.c.h +++ b/contrib/tools/python3/src/Modules/clinic/_randommodule.c.h @@ -100,11 +100,6 @@ _random_Random_getrandbits(RandomObject *self, PyObject *arg) PyObject *return_value = NULL; int k; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } k = _PyLong_AsInt(arg); if (k == -1 && PyErr_Occurred()) { goto exit; @@ -114,4 +109,4 @@ _random_Random_getrandbits(RandomObject *self, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=a7feb0c9c8d1b627 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=cc8a23b2757dc6ba input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/_sre.c.h b/contrib/tools/python3/src/Modules/clinic/_sre.c.h index d398a8504b..72d772c289 100644 --- a/contrib/tools/python3/src/Modules/clinic/_sre.c.h +++ b/contrib/tools/python3/src/Modules/clinic/_sre.c.h @@ -47,11 +47,6 @@ _sre_ascii_iscased(PyObject *module, PyObject *arg) int character; int _return_value; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } character = _PyLong_AsInt(arg); if (character == -1 && PyErr_Occurred()) { goto exit; @@ -84,11 +79,6 @@ _sre_unicode_iscased(PyObject *module, PyObject *arg) int character; int _return_value; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } character = _PyLong_AsInt(arg); if (character == -1 && PyErr_Occurred()) { goto exit; @@ -121,11 +111,6 @@ _sre_ascii_tolower(PyObject *module, PyObject *arg) int character; int _return_value; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } character = _PyLong_AsInt(arg); if (character == -1 && PyErr_Occurred()) { goto exit; @@ -158,11 +143,6 @@ _sre_unicode_tolower(PyObject *module, PyObject *arg) int character; int _return_value; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } character = _PyLong_AsInt(arg); if (character == -1 && PyErr_Occurred()) { goto exit; @@ -184,73 +164,28 @@ PyDoc_STRVAR(_sre_SRE_Pattern_match__doc__, "Matches zero or more characters at the beginning of the string."); #define _SRE_SRE_PATTERN_MATCH_METHODDEF \ - {"match", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_match, METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_match__doc__}, + {"match", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_match, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_match__doc__}, static PyObject * -_sre_SRE_Pattern_match_impl(PatternObject *self, PyObject *string, - Py_ssize_t pos, Py_ssize_t endpos); +_sre_SRE_Pattern_match_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos); static PyObject * -_sre_SRE_Pattern_match(PatternObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Pattern_match(PatternObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"string", "pos", "endpos", NULL}; - static _PyArg_Parser _parser = {NULL, _keywords, "match", 0}; - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + static _PyArg_Parser _parser = {"O|nn:match", _keywords, 0}; PyObject *string; Py_ssize_t pos = 0; Py_ssize_t endpos = PY_SSIZE_T_MAX; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf); - if (!args) { - goto exit; - } - string = args[0]; - if (!noptargs) { - goto skip_optional_pos; - } - if (args[1]) { - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } - { - Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[1]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - pos = ival; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &string, &pos, &endpos)) { goto exit; } - { - Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[2]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - endpos = ival; - } -skip_optional_pos: - return_value = _sre_SRE_Pattern_match_impl(self, string, pos, endpos); + return_value = _sre_SRE_Pattern_match_impl(self, cls, string, pos, endpos); exit: return return_value; @@ -263,73 +198,28 @@ PyDoc_STRVAR(_sre_SRE_Pattern_fullmatch__doc__, "Matches against all of the string."); #define _SRE_SRE_PATTERN_FULLMATCH_METHODDEF \ - {"fullmatch", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_fullmatch, METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_fullmatch__doc__}, + {"fullmatch", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_fullmatch, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_fullmatch__doc__}, static PyObject * -_sre_SRE_Pattern_fullmatch_impl(PatternObject *self, PyObject *string, - Py_ssize_t pos, Py_ssize_t endpos); +_sre_SRE_Pattern_fullmatch_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos); static PyObject * -_sre_SRE_Pattern_fullmatch(PatternObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Pattern_fullmatch(PatternObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"string", "pos", "endpos", NULL}; - static _PyArg_Parser _parser = {NULL, _keywords, "fullmatch", 0}; - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + static _PyArg_Parser _parser = {"O|nn:fullmatch", _keywords, 0}; PyObject *string; Py_ssize_t pos = 0; Py_ssize_t endpos = PY_SSIZE_T_MAX; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf); - if (!args) { + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &string, &pos, &endpos)) { goto exit; } - string = args[0]; - if (!noptargs) { - goto skip_optional_pos; - } - if (args[1]) { - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } - { - Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[1]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - pos = ival; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } - { - Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[2]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - endpos = ival; - } -skip_optional_pos: - return_value = _sre_SRE_Pattern_fullmatch_impl(self, string, pos, endpos); + return_value = _sre_SRE_Pattern_fullmatch_impl(self, cls, string, pos, endpos); exit: return return_value; @@ -344,73 +234,28 @@ PyDoc_STRVAR(_sre_SRE_Pattern_search__doc__, "Return None if no position in the string matches."); #define _SRE_SRE_PATTERN_SEARCH_METHODDEF \ - {"search", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_search, METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_search__doc__}, + {"search", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_search, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_search__doc__}, static PyObject * -_sre_SRE_Pattern_search_impl(PatternObject *self, PyObject *string, - Py_ssize_t pos, Py_ssize_t endpos); +_sre_SRE_Pattern_search_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos); static PyObject * -_sre_SRE_Pattern_search(PatternObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Pattern_search(PatternObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"string", "pos", "endpos", NULL}; - static _PyArg_Parser _parser = {NULL, _keywords, "search", 0}; - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + static _PyArg_Parser _parser = {"O|nn:search", _keywords, 0}; PyObject *string; Py_ssize_t pos = 0; Py_ssize_t endpos = PY_SSIZE_T_MAX; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf); - if (!args) { + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &string, &pos, &endpos)) { goto exit; } - string = args[0]; - if (!noptargs) { - goto skip_optional_pos; - } - if (args[1]) { - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } - { - Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[1]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - pos = ival; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } - { - Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[2]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - endpos = ival; - } -skip_optional_pos: - return_value = _sre_SRE_Pattern_search_impl(self, string, pos, endpos); + return_value = _sre_SRE_Pattern_search_impl(self, cls, string, pos, endpos); exit: return return_value; @@ -450,14 +295,9 @@ _sre_SRE_Pattern_findall(PatternObject *self, PyObject *const *args, Py_ssize_t goto skip_optional_pos; } if (args[1]) { - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[1]); + PyObject *iobj = _PyNumber_Index(args[1]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -471,14 +311,9 @@ _sre_SRE_Pattern_findall(PatternObject *self, PyObject *const *args, Py_ssize_t goto skip_optional_pos; } } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[2]); + PyObject *iobj = _PyNumber_Index(args[2]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -504,73 +339,28 @@ PyDoc_STRVAR(_sre_SRE_Pattern_finditer__doc__, "For each match, the iterator returns a match object."); #define _SRE_SRE_PATTERN_FINDITER_METHODDEF \ - {"finditer", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_finditer, METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_finditer__doc__}, + {"finditer", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_finditer, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_finditer__doc__}, static PyObject * -_sre_SRE_Pattern_finditer_impl(PatternObject *self, PyObject *string, - Py_ssize_t pos, Py_ssize_t endpos); +_sre_SRE_Pattern_finditer_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos); static PyObject * -_sre_SRE_Pattern_finditer(PatternObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Pattern_finditer(PatternObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"string", "pos", "endpos", NULL}; - static _PyArg_Parser _parser = {NULL, _keywords, "finditer", 0}; - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + static _PyArg_Parser _parser = {"O|nn:finditer", _keywords, 0}; PyObject *string; Py_ssize_t pos = 0; Py_ssize_t endpos = PY_SSIZE_T_MAX; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf); - if (!args) { - goto exit; - } - string = args[0]; - if (!noptargs) { - goto skip_optional_pos; - } - if (args[1]) { - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } - { - Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[1]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - pos = ival; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &string, &pos, &endpos)) { goto exit; } - { - Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[2]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - endpos = ival; - } -skip_optional_pos: - return_value = _sre_SRE_Pattern_finditer_impl(self, string, pos, endpos); + return_value = _sre_SRE_Pattern_finditer_impl(self, cls, string, pos, endpos); exit: return return_value; @@ -582,73 +372,28 @@ PyDoc_STRVAR(_sre_SRE_Pattern_scanner__doc__, "\n"); #define _SRE_SRE_PATTERN_SCANNER_METHODDEF \ - {"scanner", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_scanner, METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_scanner__doc__}, + {"scanner", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_scanner, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_scanner__doc__}, static PyObject * -_sre_SRE_Pattern_scanner_impl(PatternObject *self, PyObject *string, - Py_ssize_t pos, Py_ssize_t endpos); +_sre_SRE_Pattern_scanner_impl(PatternObject *self, PyTypeObject *cls, + PyObject *string, Py_ssize_t pos, + Py_ssize_t endpos); static PyObject * -_sre_SRE_Pattern_scanner(PatternObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Pattern_scanner(PatternObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"string", "pos", "endpos", NULL}; - static _PyArg_Parser _parser = {NULL, _keywords, "scanner", 0}; - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + static _PyArg_Parser _parser = {"O|nn:scanner", _keywords, 0}; PyObject *string; Py_ssize_t pos = 0; Py_ssize_t endpos = PY_SSIZE_T_MAX; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf); - if (!args) { + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &string, &pos, &endpos)) { goto exit; } - string = args[0]; - if (!noptargs) { - goto skip_optional_pos; - } - if (args[1]) { - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } - { - Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[1]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - pos = ival; - } - if (!--noptargs) { - goto skip_optional_pos; - } - } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } - { - Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[2]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - endpos = ival; - } -skip_optional_pos: - return_value = _sre_SRE_Pattern_scanner_impl(self, string, pos, endpos); + return_value = _sre_SRE_Pattern_scanner_impl(self, cls, string, pos, endpos); exit: return return_value; @@ -686,14 +431,9 @@ _sre_SRE_Pattern_split(PatternObject *self, PyObject *const *args, Py_ssize_t na if (!noptargs) { goto skip_optional_pos; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[1]); + PyObject *iobj = _PyNumber_Index(args[1]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -717,52 +457,27 @@ PyDoc_STRVAR(_sre_SRE_Pattern_sub__doc__, "Return the string obtained by replacing the leftmost non-overlapping occurrences of pattern in string by the replacement repl."); #define _SRE_SRE_PATTERN_SUB_METHODDEF \ - {"sub", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_sub, METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_sub__doc__}, + {"sub", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_sub, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_sub__doc__}, static PyObject * -_sre_SRE_Pattern_sub_impl(PatternObject *self, PyObject *repl, - PyObject *string, Py_ssize_t count); +_sre_SRE_Pattern_sub_impl(PatternObject *self, PyTypeObject *cls, + PyObject *repl, PyObject *string, Py_ssize_t count); static PyObject * -_sre_SRE_Pattern_sub(PatternObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Pattern_sub(PatternObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"repl", "string", "count", NULL}; - static _PyArg_Parser _parser = {NULL, _keywords, "sub", 0}; - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + static _PyArg_Parser _parser = {"OO|n:sub", _keywords, 0}; PyObject *repl; PyObject *string; Py_ssize_t count = 0; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf); - if (!args) { - goto exit; - } - repl = args[0]; - string = args[1]; - if (!noptargs) { - goto skip_optional_pos; - } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &repl, &string, &count)) { goto exit; } - { - Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[2]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - count = ival; - } -skip_optional_pos: - return_value = _sre_SRE_Pattern_sub_impl(self, repl, string, count); + return_value = _sre_SRE_Pattern_sub_impl(self, cls, repl, string, count); exit: return return_value; @@ -775,52 +490,28 @@ PyDoc_STRVAR(_sre_SRE_Pattern_subn__doc__, "Return the tuple (new_string, number_of_subs_made) found by replacing the leftmost non-overlapping occurrences of pattern with the replacement repl."); #define _SRE_SRE_PATTERN_SUBN_METHODDEF \ - {"subn", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_subn, METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_subn__doc__}, + {"subn", (PyCFunction)(void(*)(void))_sre_SRE_Pattern_subn, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Pattern_subn__doc__}, static PyObject * -_sre_SRE_Pattern_subn_impl(PatternObject *self, PyObject *repl, - PyObject *string, Py_ssize_t count); +_sre_SRE_Pattern_subn_impl(PatternObject *self, PyTypeObject *cls, + PyObject *repl, PyObject *string, + Py_ssize_t count); static PyObject * -_sre_SRE_Pattern_subn(PatternObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +_sre_SRE_Pattern_subn(PatternObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"repl", "string", "count", NULL}; - static _PyArg_Parser _parser = {NULL, _keywords, "subn", 0}; - PyObject *argsbuf[3]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + static _PyArg_Parser _parser = {"OO|n:subn", _keywords, 0}; PyObject *repl; PyObject *string; Py_ssize_t count = 0; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf); - if (!args) { + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &repl, &string, &count)) { goto exit; } - repl = args[0]; - string = args[1]; - if (!noptargs) { - goto skip_optional_pos; - } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } - { - Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[2]); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - count = ival; - } -skip_optional_pos: - return_value = _sre_SRE_Pattern_subn_impl(self, repl, string, count); + return_value = _sre_SRE_Pattern_subn_impl(self, cls, repl, string, count); exit: return return_value; @@ -884,11 +575,6 @@ _sre_compile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto exit; } pattern = args[0]; - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } flags = _PyLong_AsInt(args[1]); if (flags == -1 && PyErr_Occurred()) { goto exit; @@ -898,14 +584,9 @@ _sre_compile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto exit; } code = args[2]; - if (PyFloat_Check(args[3])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[3]); + PyObject *iobj = _PyNumber_Index(args[3]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -1180,15 +861,26 @@ PyDoc_STRVAR(_sre_SRE_Scanner_match__doc__, "\n"); #define _SRE_SRE_SCANNER_MATCH_METHODDEF \ - {"match", (PyCFunction)_sre_SRE_Scanner_match, METH_NOARGS, _sre_SRE_Scanner_match__doc__}, + {"match", (PyCFunction)(void(*)(void))_sre_SRE_Scanner_match, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Scanner_match__doc__}, static PyObject * -_sre_SRE_Scanner_match_impl(ScannerObject *self); +_sre_SRE_Scanner_match_impl(ScannerObject *self, PyTypeObject *cls); static PyObject * -_sre_SRE_Scanner_match(ScannerObject *self, PyObject *Py_UNUSED(ignored)) +_sre_SRE_Scanner_match(ScannerObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return _sre_SRE_Scanner_match_impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = {":match", _keywords, 0}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser + )) { + goto exit; + } + return_value = _sre_SRE_Scanner_match_impl(self, cls); + +exit: + return return_value; } PyDoc_STRVAR(_sre_SRE_Scanner_search__doc__, @@ -1197,14 +889,25 @@ PyDoc_STRVAR(_sre_SRE_Scanner_search__doc__, "\n"); #define _SRE_SRE_SCANNER_SEARCH_METHODDEF \ - {"search", (PyCFunction)_sre_SRE_Scanner_search, METH_NOARGS, _sre_SRE_Scanner_search__doc__}, + {"search", (PyCFunction)(void(*)(void))_sre_SRE_Scanner_search, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _sre_SRE_Scanner_search__doc__}, static PyObject * -_sre_SRE_Scanner_search_impl(ScannerObject *self); +_sre_SRE_Scanner_search_impl(ScannerObject *self, PyTypeObject *cls); static PyObject * -_sre_SRE_Scanner_search(ScannerObject *self, PyObject *Py_UNUSED(ignored)) +_sre_SRE_Scanner_search(ScannerObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return _sre_SRE_Scanner_search_impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = {":search", _keywords, 0}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser + )) { + goto exit; + } + return_value = _sre_SRE_Scanner_search_impl(self, cls); + +exit: + return return_value; } -/*[clinic end generated code: output=1adeddce58ae284c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=518f7bb775c1184f input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/_ssl.c.h b/contrib/tools/python3/src/Modules/clinic/_ssl.c.h index ce8669ae21..b59b129af8 100644 --- a/contrib/tools/python3/src/Modules/clinic/_ssl.c.h +++ b/contrib/tools/python3/src/Modules/clinic/_ssl.c.h @@ -88,6 +88,40 @@ exit: return return_value; } +PyDoc_STRVAR(_ssl__SSLSocket_get_verified_chain__doc__, +"get_verified_chain($self, /)\n" +"--\n" +"\n"); + +#define _SSL__SSLSOCKET_GET_VERIFIED_CHAIN_METHODDEF \ + {"get_verified_chain", (PyCFunction)_ssl__SSLSocket_get_verified_chain, METH_NOARGS, _ssl__SSLSocket_get_verified_chain__doc__}, + +static PyObject * +_ssl__SSLSocket_get_verified_chain_impl(PySSLSocket *self); + +static PyObject * +_ssl__SSLSocket_get_verified_chain(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) +{ + return _ssl__SSLSocket_get_verified_chain_impl(self); +} + +PyDoc_STRVAR(_ssl__SSLSocket_get_unverified_chain__doc__, +"get_unverified_chain($self, /)\n" +"--\n" +"\n"); + +#define _SSL__SSLSOCKET_GET_UNVERIFIED_CHAIN_METHODDEF \ + {"get_unverified_chain", (PyCFunction)_ssl__SSLSocket_get_unverified_chain, METH_NOARGS, _ssl__SSLSocket_get_unverified_chain__doc__}, + +static PyObject * +_ssl__SSLSocket_get_unverified_chain_impl(PySSLSocket *self); + +static PyObject * +_ssl__SSLSocket_get_unverified_chain(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) +{ + return _ssl__SSLSocket_get_unverified_chain_impl(self); +} + PyDoc_STRVAR(_ssl__SSLSocket_shared_ciphers__doc__, "shared_ciphers($self, /)\n" "--\n" @@ -139,29 +173,6 @@ _ssl__SSLSocket_version(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) return _ssl__SSLSocket_version_impl(self); } -#if (HAVE_NPN) - -PyDoc_STRVAR(_ssl__SSLSocket_selected_npn_protocol__doc__, -"selected_npn_protocol($self, /)\n" -"--\n" -"\n"); - -#define _SSL__SSLSOCKET_SELECTED_NPN_PROTOCOL_METHODDEF \ - {"selected_npn_protocol", (PyCFunction)_ssl__SSLSocket_selected_npn_protocol, METH_NOARGS, _ssl__SSLSocket_selected_npn_protocol__doc__}, - -static PyObject * -_ssl__SSLSocket_selected_npn_protocol_impl(PySSLSocket *self); - -static PyObject * -_ssl__SSLSocket_selected_npn_protocol(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) -{ - return _ssl__SSLSocket_selected_npn_protocol_impl(self); -} - -#endif /* (HAVE_NPN) */ - -#if (HAVE_ALPN) - PyDoc_STRVAR(_ssl__SSLSocket_selected_alpn_protocol__doc__, "selected_alpn_protocol($self, /)\n" "--\n" @@ -179,8 +190,6 @@ _ssl__SSLSocket_selected_alpn_protocol(PySSLSocket *self, PyObject *Py_UNUSED(ig return _ssl__SSLSocket_selected_alpn_protocol_impl(self); } -#endif /* (HAVE_ALPN) */ - PyDoc_STRVAR(_ssl__SSLSocket_compression__doc__, "compression($self, /)\n" "--\n" @@ -262,25 +271,25 @@ PyDoc_STRVAR(_ssl__SSLSocket_read__doc__, {"read", (PyCFunction)_ssl__SSLSocket_read, METH_VARARGS, _ssl__SSLSocket_read__doc__}, static PyObject * -_ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1, - Py_buffer *buffer); +_ssl__SSLSocket_read_impl(PySSLSocket *self, Py_ssize_t len, + int group_right_1, Py_buffer *buffer); static PyObject * _ssl__SSLSocket_read(PySSLSocket *self, PyObject *args) { PyObject *return_value = NULL; - int len; + Py_ssize_t len; int group_right_1 = 0; Py_buffer buffer = {NULL, NULL}; switch (PyTuple_GET_SIZE(args)) { case 1: - if (!PyArg_ParseTuple(args, "i:read", &len)) { + if (!PyArg_ParseTuple(args, "n:read", &len)) { goto exit; } break; case 2: - if (!PyArg_ParseTuple(args, "iw*:read", &len, &buffer)) { + if (!PyArg_ParseTuple(args, "nw*:read", &len, &buffer)) { goto exit; } group_right_1 = 1; @@ -399,18 +408,13 @@ _ssl__SSLContext(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *return_value = NULL; int proto_version; - if ((type == &PySSLContext_Type) && + if ((type == get_state_type(type)->PySSLContext_Type) && !_PyArg_NoKeywords("_SSLContext", kwargs)) { goto exit; } if (!_PyArg_CheckPositional("_SSLContext", PyTuple_GET_SIZE(args), 1, 1)) { goto exit; } - if (PyFloat_Check(PyTuple_GET_ITEM(args, 0))) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } proto_version = _PyLong_AsInt(PyTuple_GET_ITEM(args, 0)); if (proto_version == -1 && PyErr_Occurred()) { goto exit; @@ -457,8 +461,6 @@ exit: return return_value; } -#if (OPENSSL_VERSION_NUMBER >= 0x10002000UL) - PyDoc_STRVAR(_ssl__SSLContext_get_ciphers__doc__, "get_ciphers($self, /)\n" "--\n" @@ -476,44 +478,6 @@ _ssl__SSLContext_get_ciphers(PySSLContext *self, PyObject *Py_UNUSED(ignored)) return _ssl__SSLContext_get_ciphers_impl(self); } -#endif /* (OPENSSL_VERSION_NUMBER >= 0x10002000UL) */ - -PyDoc_STRVAR(_ssl__SSLContext__set_npn_protocols__doc__, -"_set_npn_protocols($self, protos, /)\n" -"--\n" -"\n"); - -#define _SSL__SSLCONTEXT__SET_NPN_PROTOCOLS_METHODDEF \ - {"_set_npn_protocols", (PyCFunction)_ssl__SSLContext__set_npn_protocols, METH_O, _ssl__SSLContext__set_npn_protocols__doc__}, - -static PyObject * -_ssl__SSLContext__set_npn_protocols_impl(PySSLContext *self, - Py_buffer *protos); - -static PyObject * -_ssl__SSLContext__set_npn_protocols(PySSLContext *self, PyObject *arg) -{ - PyObject *return_value = NULL; - Py_buffer protos = {NULL, NULL}; - - if (PyObject_GetBuffer(arg, &protos, PyBUF_SIMPLE) != 0) { - goto exit; - } - if (!PyBuffer_IsContiguous(&protos, 'C')) { - _PyArg_BadArgument("_set_npn_protocols", "argument", "contiguous buffer", arg); - goto exit; - } - return_value = _ssl__SSLContext__set_npn_protocols_impl(self, &protos); - -exit: - /* Cleanup for protos */ - if (protos.obj) { - PyBuffer_Release(&protos); - } - - return return_value; -} - PyDoc_STRVAR(_ssl__SSLContext__set_alpn_protocols__doc__, "_set_alpn_protocols($self, protos, /)\n" "--\n" @@ -689,16 +653,11 @@ _ssl__SSLContext__wrap_socket(PySSLContext *self, PyObject *const *args, Py_ssiz if (!args) { goto exit; } - if (!PyObject_TypeCheck(args[0], PySocketModule.Sock_Type)) { - _PyArg_BadArgument("_wrap_socket", "argument 'sock'", (PySocketModule.Sock_Type)->tp_name, args[0]); + if (!PyObject_TypeCheck(args[0], get_state_ctx(self)->Sock_Type)) { + _PyArg_BadArgument("_wrap_socket", "argument 'sock'", (get_state_ctx(self)->Sock_Type)->tp_name, args[0]); goto exit; } sock = args[0]; - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } server_side = _PyLong_AsInt(args[1]); if (server_side == -1 && PyErr_Occurred()) { goto exit; @@ -764,21 +723,16 @@ _ssl__SSLContext__wrap_bio(PySSLContext *self, PyObject *const *args, Py_ssize_t if (!args) { goto exit; } - if (!PyObject_TypeCheck(args[0], &PySSLMemoryBIO_Type)) { - _PyArg_BadArgument("_wrap_bio", "argument 'incoming'", (&PySSLMemoryBIO_Type)->tp_name, args[0]); + if (!PyObject_TypeCheck(args[0], get_state_ctx(self)->PySSLMemoryBIO_Type)) { + _PyArg_BadArgument("_wrap_bio", "argument 'incoming'", (get_state_ctx(self)->PySSLMemoryBIO_Type)->tp_name, args[0]); goto exit; } incoming = (PySSLMemoryBIO *)args[0]; - if (!PyObject_TypeCheck(args[1], &PySSLMemoryBIO_Type)) { - _PyArg_BadArgument("_wrap_bio", "argument 'outgoing'", (&PySSLMemoryBIO_Type)->tp_name, args[1]); + if (!PyObject_TypeCheck(args[1], get_state_ctx(self)->PySSLMemoryBIO_Type)) { + _PyArg_BadArgument("_wrap_bio", "argument 'outgoing'", (get_state_ctx(self)->PySSLMemoryBIO_Type)->tp_name, args[1]); goto exit; } outgoing = (PySSLMemoryBIO *)args[1]; - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } server_side = _PyLong_AsInt(args[2]); if (server_side == -1 && PyErr_Occurred()) { goto exit; @@ -844,8 +798,6 @@ _ssl__SSLContext_set_default_verify_paths(PySSLContext *self, PyObject *Py_UNUSE return _ssl__SSLContext_set_default_verify_paths_impl(self); } -#if !defined(OPENSSL_NO_ECDH) - PyDoc_STRVAR(_ssl__SSLContext_set_ecdh_curve__doc__, "set_ecdh_curve($self, name, /)\n" "--\n" @@ -854,8 +806,6 @@ PyDoc_STRVAR(_ssl__SSLContext_set_ecdh_curve__doc__, #define _SSL__SSLCONTEXT_SET_ECDH_CURVE_METHODDEF \ {"set_ecdh_curve", (PyCFunction)_ssl__SSLContext_set_ecdh_curve, METH_O, _ssl__SSLContext_set_ecdh_curve__doc__}, -#endif /* !defined(OPENSSL_NO_ECDH) */ - PyDoc_STRVAR(_ssl__SSLContext_cert_store_stats__doc__, "cert_store_stats($self, /)\n" "--\n" @@ -934,11 +884,11 @@ _ssl_MemoryBIO(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; - if ((type == &PySSLMemoryBIO_Type) && + if ((type == get_state_type(type)->PySSLMemoryBIO_Type) && !_PyArg_NoPositional("MemoryBIO", args)) { goto exit; } - if ((type == &PySSLMemoryBIO_Type) && + if ((type == get_state_type(type)->PySSLMemoryBIO_Type) && !_PyArg_NoKeywords("MemoryBIO", kwargs)) { goto exit; } @@ -977,11 +927,6 @@ _ssl_MemoryBIO_read(PySSLMemoryBIO *self, PyObject *const *args, Py_ssize_t narg if (nargs < 1) { goto skip_optional; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } len = _PyLong_AsInt(args[0]); if (len == -1 && PyErr_Occurred()) { goto exit; @@ -1132,11 +1077,6 @@ _ssl_RAND_bytes(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int n; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } n = _PyLong_AsInt(arg); if (n == -1 && PyErr_Occurred()) { goto exit; @@ -1168,11 +1108,6 @@ _ssl_RAND_pseudo_bytes(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int n; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } n = _PyLong_AsInt(arg); if (n == -1 && PyErr_Occurred()) { goto exit; @@ -1187,7 +1122,7 @@ PyDoc_STRVAR(_ssl_RAND_status__doc__, "RAND_status($module, /)\n" "--\n" "\n" -"Returns 1 if the OpenSSL PRNG has been seeded with enough data and 0 if not.\n" +"Returns True if the OpenSSL PRNG has been seeded with enough data and False if not.\n" "\n" "It is necessary to seed the PRNG with RAND_add() on some platforms before\n" "using the ssl() function."); @@ -1204,40 +1139,6 @@ _ssl_RAND_status(PyObject *module, PyObject *Py_UNUSED(ignored)) return _ssl_RAND_status_impl(module); } -#if !defined(OPENSSL_NO_EGD) - -PyDoc_STRVAR(_ssl_RAND_egd__doc__, -"RAND_egd($module, path, /)\n" -"--\n" -"\n" -"Queries the entropy gather daemon (EGD) on the socket named by \'path\'.\n" -"\n" -"Returns number of bytes read. Raises SSLError if connection to EGD\n" -"fails or if it does not provide enough data to seed PRNG."); - -#define _SSL_RAND_EGD_METHODDEF \ - {"RAND_egd", (PyCFunction)_ssl_RAND_egd, METH_O, _ssl_RAND_egd__doc__}, - -static PyObject * -_ssl_RAND_egd_impl(PyObject *module, PyObject *path); - -static PyObject * -_ssl_RAND_egd(PyObject *module, PyObject *arg) -{ - PyObject *return_value = NULL; - PyObject *path; - - if (!PyUnicode_FSConverter(arg, &path)) { - goto exit; - } - return_value = _ssl_RAND_egd_impl(module, path); - -exit: - return return_value; -} - -#endif /* !defined(OPENSSL_NO_EGD) */ - PyDoc_STRVAR(_ssl_get_default_verify_paths__doc__, "get_default_verify_paths($module, /)\n" "--\n" @@ -1333,11 +1234,6 @@ _ssl_nid2obj(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int nid; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } nid = _PyLong_AsInt(arg); if (nid == -1 && PyErr_Occurred()) { goto exit; @@ -1455,26 +1351,6 @@ exit: #endif /* defined(_MSC_VER) */ -#ifndef _SSL__SSLSOCKET_SELECTED_NPN_PROTOCOL_METHODDEF - #define _SSL__SSLSOCKET_SELECTED_NPN_PROTOCOL_METHODDEF -#endif /* !defined(_SSL__SSLSOCKET_SELECTED_NPN_PROTOCOL_METHODDEF) */ - -#ifndef _SSL__SSLSOCKET_SELECTED_ALPN_PROTOCOL_METHODDEF - #define _SSL__SSLSOCKET_SELECTED_ALPN_PROTOCOL_METHODDEF -#endif /* !defined(_SSL__SSLSOCKET_SELECTED_ALPN_PROTOCOL_METHODDEF) */ - -#ifndef _SSL__SSLCONTEXT_GET_CIPHERS_METHODDEF - #define _SSL__SSLCONTEXT_GET_CIPHERS_METHODDEF -#endif /* !defined(_SSL__SSLCONTEXT_GET_CIPHERS_METHODDEF) */ - -#ifndef _SSL__SSLCONTEXT_SET_ECDH_CURVE_METHODDEF - #define _SSL__SSLCONTEXT_SET_ECDH_CURVE_METHODDEF -#endif /* !defined(_SSL__SSLCONTEXT_SET_ECDH_CURVE_METHODDEF) */ - -#ifndef _SSL_RAND_EGD_METHODDEF - #define _SSL_RAND_EGD_METHODDEF -#endif /* !defined(_SSL_RAND_EGD_METHODDEF) */ - #ifndef _SSL_ENUM_CERTIFICATES_METHODDEF #define _SSL_ENUM_CERTIFICATES_METHODDEF #endif /* !defined(_SSL_ENUM_CERTIFICATES_METHODDEF) */ @@ -1482,4 +1358,4 @@ exit: #ifndef _SSL_ENUM_CRLS_METHODDEF #define _SSL_ENUM_CRLS_METHODDEF #endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */ -/*[clinic end generated code: output=a4aeb3f92a091c64 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5a7d7bf5cf8ee092 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/_struct.c.h b/contrib/tools/python3/src/Modules/clinic/_struct.c.h index 36c4b4046c..b0c1eb4587 100644 --- a/contrib/tools/python3/src/Modules/clinic/_struct.c.h +++ b/contrib/tools/python3/src/Modules/clinic/_struct.c.h @@ -124,14 +124,9 @@ Struct_unpack_from(PyStructObject *self, PyObject *const *args, Py_ssize_t nargs if (!noptargs) { goto skip_optional_pos; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[1]); + PyObject *iobj = _PyNumber_Index(args[1]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -204,7 +199,7 @@ calcsize(PyObject *module, PyObject *arg) PyStructObject *s_object = NULL; Py_ssize_t _return_value; - if (!cache_struct_converter(arg, &s_object)) { + if (!cache_struct_converter(module, arg, &s_object)) { goto exit; } _return_value = calcsize_impl(module, s_object); @@ -246,7 +241,7 @@ unpack(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("unpack", nargs, 2, 2)) { goto exit; } - if (!cache_struct_converter(args[0], &s_object)) { + if (!cache_struct_converter(module, args[0], &s_object)) { goto exit; } if (PyObject_GetBuffer(args[1], &buffer, PyBUF_SIMPLE) != 0) { @@ -302,7 +297,7 @@ unpack_from(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (!args) { goto exit; } - if (!cache_struct_converter(args[0], &s_object)) { + if (!cache_struct_converter(module, args[0], &s_object)) { goto exit; } if (PyObject_GetBuffer(args[1], &buffer, PyBUF_SIMPLE) != 0) { @@ -315,14 +310,9 @@ unpack_from(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (!noptargs) { goto skip_optional_pos; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[2]); + PyObject *iobj = _PyNumber_Index(args[2]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -374,7 +364,7 @@ iter_unpack(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("iter_unpack", nargs, 2, 2)) { goto exit; } - if (!cache_struct_converter(args[0], &s_object)) { + if (!cache_struct_converter(module, args[0], &s_object)) { goto exit; } buffer = args[1]; @@ -386,4 +376,4 @@ exit: return return_value; } -/*[clinic end generated code: output=6a6228cfc4b7099c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a3d3cd900091cb1c input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/_tkinter.c.h b/contrib/tools/python3/src/Modules/clinic/_tkinter.c.h index 73c3faeaf9..9718986838 100644 --- a/contrib/tools/python3/src/Modules/clinic/_tkinter.c.h +++ b/contrib/tools/python3/src/Modules/clinic/_tkinter.c.h @@ -434,11 +434,6 @@ _tkinter_tkapp_createfilehandler(TkappObject *self, PyObject *const *args, Py_ss goto exit; } file = args[0]; - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } mask = _PyLong_AsInt(args[1]); if (mask == -1 && PyErr_Occurred()) { goto exit; @@ -503,11 +498,6 @@ _tkinter_tkapp_createtimerhandler(TkappObject *self, PyObject *const *args, Py_s if (!_PyArg_CheckPositional("createtimerhandler", nargs, 2, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } milliseconds = _PyLong_AsInt(args[0]); if (milliseconds == -1 && PyErr_Occurred()) { goto exit; @@ -542,11 +532,6 @@ _tkinter_tkapp_mainloop(TkappObject *self, PyObject *const *args, Py_ssize_t nar if (nargs < 1) { goto skip_optional; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } threshold = _PyLong_AsInt(args[0]); if (threshold == -1 && PyErr_Occurred()) { goto exit; @@ -581,11 +566,6 @@ _tkinter_tkapp_dooneevent(TkappObject *self, PyObject *const *args, Py_ssize_t n if (nargs < 1) { goto skip_optional; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } flags = _PyLong_AsInt(args[0]); if (flags == -1 && PyErr_Occurred()) { goto exit; @@ -769,11 +749,6 @@ _tkinter_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 4) { goto skip_optional; } - if (PyFloat_Check(args[3])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } interactive = _PyLong_AsInt(args[3]); if (interactive == -1 && PyErr_Occurred()) { goto exit; @@ -781,11 +756,6 @@ _tkinter_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 5) { goto skip_optional; } - if (PyFloat_Check(args[4])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } wantobjects = _PyLong_AsInt(args[4]); if (wantobjects == -1 && PyErr_Occurred()) { goto exit; @@ -793,11 +763,6 @@ _tkinter_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 6) { goto skip_optional; } - if (PyFloat_Check(args[5])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } wantTk = _PyLong_AsInt(args[5]); if (wantTk == -1 && PyErr_Occurred()) { goto exit; @@ -805,11 +770,6 @@ _tkinter_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 7) { goto skip_optional; } - if (PyFloat_Check(args[6])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } sync = _PyLong_AsInt(args[6]); if (sync == -1 && PyErr_Occurred()) { goto exit; @@ -862,11 +822,6 @@ _tkinter_setbusywaitinterval(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int new_val; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } new_val = _PyLong_AsInt(arg); if (new_val == -1 && PyErr_Occurred()) { goto exit; @@ -912,4 +867,4 @@ exit: #ifndef _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF #define _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF #endif /* !defined(_TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF) */ -/*[clinic end generated code: output=492b8b833fe54bc9 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ab311480dd044fe4 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/_tracemalloc.c.h b/contrib/tools/python3/src/Modules/clinic/_tracemalloc.c.h index 049cacd832..20afd76f06 100644 --- a/contrib/tools/python3/src/Modules/clinic/_tracemalloc.c.h +++ b/contrib/tools/python3/src/Modules/clinic/_tracemalloc.c.h @@ -101,11 +101,6 @@ _tracemalloc_start(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 1) { goto skip_optional; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } nframe = _PyLong_AsInt(args[0]); if (nframe == -1 && PyErr_Occurred()) { goto exit; @@ -217,4 +212,4 @@ _tracemalloc_reset_peak(PyObject *module, PyObject *Py_UNUSED(ignored)) { return _tracemalloc_reset_peak_impl(module); } -/*[clinic end generated code: output=a130117b1af821da input=a9049054013a1b77]*/ +/*[clinic end generated code: output=bafca0a19b0b0823 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/_winapi.c.h b/contrib/tools/python3/src/Modules/clinic/_winapi.c.h index e21f2bc2b6..5bda156d7a 100644 --- a/contrib/tools/python3/src/Modules/clinic/_winapi.c.h +++ b/contrib/tools/python3/src/Modules/clinic/_winapi.c.h @@ -195,8 +195,8 @@ _winapi_CreateFileMapping(PyObject *module, PyObject *const *args, Py_ssize_t na LPCWSTR name; HANDLE _return_value; - if (!_PyArg_ParseStack(args, nargs, "" F_HANDLE "" F_POINTER "kkku:CreateFileMapping", - &file_handle, &security_attributes, &protect, &max_size_high, &max_size_low, &name)) { + if (!_PyArg_ParseStack(args, nargs, "" F_HANDLE "" F_POINTER "kkkO&:CreateFileMapping", + &file_handle, &security_attributes, &protect, &max_size_high, &max_size_low, _PyUnicode_WideCharString_Converter, &name)) { goto exit; } _return_value = _winapi_CreateFileMapping_impl(module, file_handle, security_attributes, protect, max_size_high, max_size_low, name); @@ -209,6 +209,11 @@ _winapi_CreateFileMapping(PyObject *module, PyObject *const *args, Py_ssize_t na return_value = HANDLE_TO_PYNUM(_return_value); exit: + /* Cleanup for name */ + #if !USE_UNICODE_WCHAR_CACHE + PyMem_Free((void *)name); + #endif /* USE_UNICODE_WCHAR_CACHE */ + return return_value; } @@ -221,23 +226,55 @@ PyDoc_STRVAR(_winapi_CreateJunction__doc__, {"CreateJunction", (PyCFunction)(void(*)(void))_winapi_CreateJunction, METH_FASTCALL, _winapi_CreateJunction__doc__}, static PyObject * -_winapi_CreateJunction_impl(PyObject *module, LPWSTR src_path, - LPWSTR dst_path); +_winapi_CreateJunction_impl(PyObject *module, LPCWSTR src_path, + LPCWSTR dst_path); static PyObject * _winapi_CreateJunction(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - LPWSTR src_path; - LPWSTR dst_path; + LPCWSTR src_path; + LPCWSTR dst_path; - if (!_PyArg_ParseStack(args, nargs, "uu:CreateJunction", - &src_path, &dst_path)) { + if (!_PyArg_CheckPositional("CreateJunction", nargs, 2, 2)) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("CreateJunction", "argument 1", "str", args[0]); + goto exit; + } + #if USE_UNICODE_WCHAR_CACHE + src_path = _PyUnicode_AsUnicode(args[0]); + #else /* USE_UNICODE_WCHAR_CACHE */ + src_path = PyUnicode_AsWideCharString(args[0], NULL); + #endif /* USE_UNICODE_WCHAR_CACHE */ + if (src_path == NULL) { + goto exit; + } + if (!PyUnicode_Check(args[1])) { + _PyArg_BadArgument("CreateJunction", "argument 2", "str", args[1]); + goto exit; + } + #if USE_UNICODE_WCHAR_CACHE + dst_path = _PyUnicode_AsUnicode(args[1]); + #else /* USE_UNICODE_WCHAR_CACHE */ + dst_path = PyUnicode_AsWideCharString(args[1], NULL); + #endif /* USE_UNICODE_WCHAR_CACHE */ + if (dst_path == NULL) { goto exit; } return_value = _winapi_CreateJunction_impl(module, src_path, dst_path); exit: + /* Cleanup for src_path */ + #if !USE_UNICODE_WCHAR_CACHE + PyMem_Free((void *)src_path); + #endif /* USE_UNICODE_WCHAR_CACHE */ + /* Cleanup for dst_path */ + #if !USE_UNICODE_WCHAR_CACHE + PyMem_Free((void *)dst_path); + #endif /* USE_UNICODE_WCHAR_CACHE */ + return return_value; } @@ -367,13 +404,22 @@ _winapi_CreateProcess(PyObject *module, PyObject *const *args, Py_ssize_t nargs) const Py_UNICODE *current_directory; PyObject *startup_info; - if (!_PyArg_ParseStack(args, nargs, "ZOOOikOZO:CreateProcess", - &application_name, &command_line, &proc_attrs, &thread_attrs, &inherit_handles, &creation_flags, &env_mapping, ¤t_directory, &startup_info)) { + if (!_PyArg_ParseStack(args, nargs, "O&OOOikOO&O:CreateProcess", + _PyUnicode_WideCharString_Opt_Converter, &application_name, &command_line, &proc_attrs, &thread_attrs, &inherit_handles, &creation_flags, &env_mapping, _PyUnicode_WideCharString_Opt_Converter, ¤t_directory, &startup_info)) { goto exit; } return_value = _winapi_CreateProcess_impl(module, application_name, command_line, proc_attrs, thread_attrs, inherit_handles, creation_flags, env_mapping, current_directory, startup_info); exit: + /* Cleanup for application_name */ + #if !USE_UNICODE_WCHAR_CACHE + PyMem_Free((void *)application_name); + #endif /* USE_UNICODE_WCHAR_CACHE */ + /* Cleanup for current_directory */ + #if !USE_UNICODE_WCHAR_CACHE + PyMem_Free((void *)current_directory); + #endif /* USE_UNICODE_WCHAR_CACHE */ + return return_value; } @@ -706,8 +752,8 @@ _winapi_OpenFileMapping(PyObject *module, PyObject *const *args, Py_ssize_t narg LPCWSTR name; HANDLE _return_value; - if (!_PyArg_ParseStack(args, nargs, "kiu:OpenFileMapping", - &desired_access, &inherit_handle, &name)) { + if (!_PyArg_ParseStack(args, nargs, "kiO&:OpenFileMapping", + &desired_access, &inherit_handle, _PyUnicode_WideCharString_Converter, &name)) { goto exit; } _return_value = _winapi_OpenFileMapping_impl(module, desired_access, inherit_handle, name); @@ -720,6 +766,11 @@ _winapi_OpenFileMapping(PyObject *module, PyObject *const *args, Py_ssize_t narg return_value = HANDLE_TO_PYNUM(_return_value); exit: + /* Cleanup for name */ + #if !USE_UNICODE_WCHAR_CACHE + PyMem_Free((void *)name); + #endif /* USE_UNICODE_WCHAR_CACHE */ + return return_value; } @@ -1097,4 +1148,40 @@ _winapi_GetFileType(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P exit: return return_value; } -/*[clinic end generated code: output=f3897898ea1da99d input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_winapi__mimetypes_read_windows_registry__doc__, +"_mimetypes_read_windows_registry($module, /, on_type_read)\n" +"--\n" +"\n" +"Optimized function for reading all known MIME types from the registry.\n" +"\n" +"*on_type_read* is a callable taking *type* and *ext* arguments, as for\n" +"MimeTypes.add_type."); + +#define _WINAPI__MIMETYPES_READ_WINDOWS_REGISTRY_METHODDEF \ + {"_mimetypes_read_windows_registry", (PyCFunction)(void(*)(void))_winapi__mimetypes_read_windows_registry, METH_FASTCALL|METH_KEYWORDS, _winapi__mimetypes_read_windows_registry__doc__}, + +static PyObject * +_winapi__mimetypes_read_windows_registry_impl(PyObject *module, + PyObject *on_type_read); + +static PyObject * +_winapi__mimetypes_read_windows_registry(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"on_type_read", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "_mimetypes_read_windows_registry", 0}; + PyObject *argsbuf[1]; + PyObject *on_type_read; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + on_type_read = args[0]; + return_value = _winapi__mimetypes_read_windows_registry_impl(module, on_type_read); + +exit: + return return_value; +} +/*[clinic end generated code: output=ac3623be6e42017c input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/arraymodule.c.h b/contrib/tools/python3/src/Modules/clinic/arraymodule.c.h index 005c7ffce4..c46cc738de 100644 --- a/contrib/tools/python3/src/Modules/clinic/arraymodule.c.h +++ b/contrib/tools/python3/src/Modules/clinic/arraymodule.c.h @@ -39,13 +39,50 @@ PyDoc_STRVAR(array_array_count__doc__, {"count", (PyCFunction)array_array_count, METH_O, array_array_count__doc__}, PyDoc_STRVAR(array_array_index__doc__, -"index($self, v, /)\n" +"index($self, v, start=0, stop=sys.maxsize, /)\n" "--\n" "\n" -"Return index of first occurrence of v in the array."); +"Return index of first occurrence of v in the array.\n" +"\n" +"Raise ValueError if the value is not present."); #define ARRAY_ARRAY_INDEX_METHODDEF \ - {"index", (PyCFunction)array_array_index, METH_O, array_array_index__doc__}, + {"index", (PyCFunction)(void(*)(void))array_array_index, METH_FASTCALL, array_array_index__doc__}, + +static PyObject * +array_array_index_impl(arrayobject *self, PyObject *v, Py_ssize_t start, + Py_ssize_t stop); + +static PyObject * +array_array_index(arrayobject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *v; + Py_ssize_t start = 0; + Py_ssize_t stop = PY_SSIZE_T_MAX; + + if (!_PyArg_CheckPositional("index", nargs, 1, 3)) { + goto exit; + } + v = args[0]; + if (nargs < 2) { + goto skip_optional; + } + if (!_PyEval_SliceIndexNotNone(args[1], &start)) { + goto exit; + } + if (nargs < 3) { + goto skip_optional; + } + if (!_PyEval_SliceIndexNotNone(args[2], &stop)) { + goto exit; + } +skip_optional: + return_value = array_array_index_impl(self, v, start, stop); + +exit: + return return_value; +} PyDoc_STRVAR(array_array_remove__doc__, "remove($self, v, /)\n" @@ -82,14 +119,9 @@ array_array_pop(arrayobject *self, PyObject *const *args, Py_ssize_t nargs) if (nargs < 1) { goto skip_optional; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[0]); + PyObject *iobj = _PyNumber_Index(args[0]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -113,7 +145,28 @@ PyDoc_STRVAR(array_array_extend__doc__, "Append items to the end of the array."); #define ARRAY_ARRAY_EXTEND_METHODDEF \ - {"extend", (PyCFunction)array_array_extend, METH_O, array_array_extend__doc__}, + {"extend", (PyCFunction)(void(*)(void))array_array_extend, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, array_array_extend__doc__}, + +static PyObject * +array_array_extend_impl(arrayobject *self, PyTypeObject *cls, PyObject *bb); + +static PyObject * +array_array_extend(arrayobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = {"O:extend", _keywords, 0}; + PyObject *bb; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &bb)) { + goto exit; + } + return_value = array_array_extend_impl(self, cls, bb); + +exit: + return return_value; +} PyDoc_STRVAR(array_array_insert__doc__, "insert($self, i, v, /)\n" @@ -137,14 +190,9 @@ array_array_insert(arrayobject *self, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("insert", nargs, 2, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[0]); + PyObject *iobj = _PyNumber_Index(args[0]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -253,14 +301,9 @@ array_array_fromfile(arrayobject *self, PyObject *const *args, Py_ssize_t nargs) goto exit; } f = args[0]; - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[1]); + PyObject *iobj = _PyNumber_Index(args[1]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -483,11 +526,6 @@ array__array_reconstructor(PyObject *module, PyObject *const *args, Py_ssize_t n goto exit; } typecode = PyUnicode_READ_CHAR(args[1], 0); - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } mformat_code = _PyLong_AsInt(args[2]); if (mformat_code == -1 && PyErr_Occurred()) { goto exit; @@ -534,4 +572,4 @@ PyDoc_STRVAR(array_arrayiterator___setstate____doc__, #define ARRAY_ARRAYITERATOR___SETSTATE___METHODDEF \ {"__setstate__", (PyCFunction)array_arrayiterator___setstate__, METH_O, array_arrayiterator___setstate____doc__}, -/*[clinic end generated code: output=485e848d1f3d05e7 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f130a994f98f1227 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/audioop.c.h b/contrib/tools/python3/src/Modules/clinic/audioop.c.h index 8745533eeb..da12bd17b5 100644 --- a/contrib/tools/python3/src/Modules/clinic/audioop.c.h +++ b/contrib/tools/python3/src/Modules/clinic/audioop.c.h @@ -33,23 +33,13 @@ audioop_getsample(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("getsample", "argument 1", "contiguous buffer", args[0]); goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } width = _PyLong_AsInt(args[1]); if (width == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[2]); + PyObject *iobj = _PyNumber_Index(args[2]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -99,11 +89,6 @@ audioop_max(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("max", "argument 1", "contiguous buffer", args[0]); goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } width = _PyLong_AsInt(args[1]); if (width == -1 && PyErr_Occurred()) { goto exit; @@ -148,11 +133,6 @@ audioop_minmax(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("minmax", "argument 1", "contiguous buffer", args[0]); goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } width = _PyLong_AsInt(args[1]); if (width == -1 && PyErr_Occurred()) { goto exit; @@ -197,11 +177,6 @@ audioop_avg(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("avg", "argument 1", "contiguous buffer", args[0]); goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } width = _PyLong_AsInt(args[1]); if (width == -1 && PyErr_Occurred()) { goto exit; @@ -246,11 +221,6 @@ audioop_rms(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("rms", "argument 1", "contiguous buffer", args[0]); goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } width = _PyLong_AsInt(args[1]); if (width == -1 && PyErr_Occurred()) { goto exit; @@ -400,14 +370,9 @@ audioop_findmax(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("findmax", "argument 1", "contiguous buffer", args[0]); goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[1]); + PyObject *iobj = _PyNumber_Index(args[1]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -457,11 +422,6 @@ audioop_avgpp(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("avgpp", "argument 1", "contiguous buffer", args[0]); goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } width = _PyLong_AsInt(args[1]); if (width == -1 && PyErr_Occurred()) { goto exit; @@ -506,11 +466,6 @@ audioop_maxpp(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("maxpp", "argument 1", "contiguous buffer", args[0]); goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } width = _PyLong_AsInt(args[1]); if (width == -1 && PyErr_Occurred()) { goto exit; @@ -555,11 +510,6 @@ audioop_cross(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("cross", "argument 1", "contiguous buffer", args[0]); goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } width = _PyLong_AsInt(args[1]); if (width == -1 && PyErr_Occurred()) { goto exit; @@ -606,11 +556,6 @@ audioop_mul(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("mul", "argument 1", "contiguous buffer", args[0]); goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } width = _PyLong_AsInt(args[1]); if (width == -1 && PyErr_Occurred()) { goto exit; @@ -668,11 +613,6 @@ audioop_tomono(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("tomono", "argument 1", "contiguous buffer", args[0]); goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } width = _PyLong_AsInt(args[1]); if (width == -1 && PyErr_Occurred()) { goto exit; @@ -740,11 +680,6 @@ audioop_tostereo(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("tostereo", "argument 1", "contiguous buffer", args[0]); goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } width = _PyLong_AsInt(args[1]); if (width == -1 && PyErr_Occurred()) { goto exit; @@ -818,11 +753,6 @@ audioop_add(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("add", "argument 2", "contiguous buffer", args[1]); goto exit; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } width = _PyLong_AsInt(args[2]); if (width == -1 && PyErr_Occurred()) { goto exit; @@ -872,20 +802,10 @@ audioop_bias(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("bias", "argument 1", "contiguous buffer", args[0]); goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } width = _PyLong_AsInt(args[1]); if (width == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } bias = _PyLong_AsInt(args[2]); if (bias == -1 && PyErr_Occurred()) { goto exit; @@ -930,11 +850,6 @@ audioop_reverse(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("reverse", "argument 1", "contiguous buffer", args[0]); goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } width = _PyLong_AsInt(args[1]); if (width == -1 && PyErr_Occurred()) { goto exit; @@ -979,11 +894,6 @@ audioop_byteswap(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("byteswap", "argument 1", "contiguous buffer", args[0]); goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } width = _PyLong_AsInt(args[1]); if (width == -1 && PyErr_Occurred()) { goto exit; @@ -1030,20 +940,10 @@ audioop_lin2lin(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("lin2lin", "argument 1", "contiguous buffer", args[0]); goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } width = _PyLong_AsInt(args[1]); if (width == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } newwidth = _PyLong_AsInt(args[2]); if (newwidth == -1 && PyErr_Occurred()) { goto exit; @@ -1097,38 +997,18 @@ audioop_ratecv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("ratecv", "argument 1", "contiguous buffer", args[0]); goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } width = _PyLong_AsInt(args[1]); if (width == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } nchannels = _PyLong_AsInt(args[2]); if (nchannels == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[3])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } inrate = _PyLong_AsInt(args[3]); if (inrate == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[4])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } outrate = _PyLong_AsInt(args[4]); if (outrate == -1 && PyErr_Occurred()) { goto exit; @@ -1137,11 +1017,6 @@ audioop_ratecv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 7) { goto skip_optional; } - if (PyFloat_Check(args[6])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } weightA = _PyLong_AsInt(args[6]); if (weightA == -1 && PyErr_Occurred()) { goto exit; @@ -1149,11 +1024,6 @@ audioop_ratecv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 8) { goto skip_optional; } - if (PyFloat_Check(args[7])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } weightB = _PyLong_AsInt(args[7]); if (weightB == -1 && PyErr_Occurred()) { goto exit; @@ -1199,11 +1069,6 @@ audioop_lin2ulaw(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("lin2ulaw", "argument 1", "contiguous buffer", args[0]); goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } width = _PyLong_AsInt(args[1]); if (width == -1 && PyErr_Occurred()) { goto exit; @@ -1248,11 +1113,6 @@ audioop_ulaw2lin(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("ulaw2lin", "argument 1", "contiguous buffer", args[0]); goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } width = _PyLong_AsInt(args[1]); if (width == -1 && PyErr_Occurred()) { goto exit; @@ -1297,11 +1157,6 @@ audioop_lin2alaw(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("lin2alaw", "argument 1", "contiguous buffer", args[0]); goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } width = _PyLong_AsInt(args[1]); if (width == -1 && PyErr_Occurred()) { goto exit; @@ -1346,11 +1201,6 @@ audioop_alaw2lin(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("alaw2lin", "argument 1", "contiguous buffer", args[0]); goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } width = _PyLong_AsInt(args[1]); if (width == -1 && PyErr_Occurred()) { goto exit; @@ -1397,11 +1247,6 @@ audioop_lin2adpcm(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("lin2adpcm", "argument 1", "contiguous buffer", args[0]); goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } width = _PyLong_AsInt(args[1]); if (width == -1 && PyErr_Occurred()) { goto exit; @@ -1449,11 +1294,6 @@ audioop_adpcm2lin(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("adpcm2lin", "argument 1", "contiguous buffer", args[0]); goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } width = _PyLong_AsInt(args[1]); if (width == -1 && PyErr_Occurred()) { goto exit; @@ -1469,4 +1309,4 @@ exit: return return_value; } -/*[clinic end generated code: output=6b4f2c597f295abc input=a9049054013a1b77]*/ +/*[clinic end generated code: output=840f8c315ebd4946 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/binascii.c.h b/contrib/tools/python3/src/Modules/clinic/binascii.c.h index 4d02c72c47..ae1c457432 100644 --- a/contrib/tools/python3/src/Modules/clinic/binascii.c.h +++ b/contrib/tools/python3/src/Modules/clinic/binascii.c.h @@ -70,11 +70,6 @@ binascii_b2a_uu(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj if (!noptargs) { goto skip_optional_kwonly; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } backtick = _PyLong_AsInt(args[1]); if (backtick == -1 && PyErr_Occurred()) { goto exit; @@ -159,11 +154,6 @@ binascii_b2a_base64(PyObject *module, PyObject *const *args, Py_ssize_t nargs, P if (!noptargs) { goto skip_optional_kwonly; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } newline = _PyLong_AsInt(args[1]); if (newline == -1 && PyErr_Occurred()) { goto exit; @@ -348,11 +338,6 @@ binascii_crc_hqx(PyObject *module, PyObject *const *args, Py_ssize_t nargs) _PyArg_BadArgument("crc_hqx", "argument 1", "contiguous buffer", args[0]); goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } crc = (unsigned int)PyLong_AsUnsignedLongMask(args[1]); if (crc == (unsigned int)-1 && PyErr_Occurred()) { goto exit; @@ -401,11 +386,6 @@ binascii_crc32(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 2) { goto skip_optional; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } crc = (unsigned int)PyLong_AsUnsignedLongMask(args[1]); if (crc == (unsigned int)-1 && PyErr_Occurred()) { goto exit; @@ -488,11 +468,6 @@ binascii_b2a_hex(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb goto skip_optional_pos; } } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } bytes_per_sep = _PyLong_AsInt(args[2]); if (bytes_per_sep == -1 && PyErr_Occurred()) { goto exit; @@ -563,11 +538,6 @@ binascii_hexlify(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb goto skip_optional_pos; } } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } bytes_per_sep = _PyLong_AsInt(args[2]); if (bytes_per_sep == -1 && PyErr_Occurred()) { goto exit; @@ -684,11 +654,6 @@ binascii_a2b_qp(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj if (!noptargs) { goto skip_optional_pos; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } header = _PyLong_AsInt(args[1]); if (header == -1 && PyErr_Occurred()) { goto exit; @@ -749,11 +714,6 @@ binascii_b2a_qp(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj goto skip_optional_pos; } if (args[1]) { - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } quotetabs = _PyLong_AsInt(args[1]); if (quotetabs == -1 && PyErr_Occurred()) { goto exit; @@ -763,11 +723,6 @@ binascii_b2a_qp(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj } } if (args[2]) { - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } istext = _PyLong_AsInt(args[2]); if (istext == -1 && PyErr_Occurred()) { goto exit; @@ -776,11 +731,6 @@ binascii_b2a_qp(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj goto skip_optional_pos; } } - if (PyFloat_Check(args[3])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } header = _PyLong_AsInt(args[3]); if (header == -1 && PyErr_Occurred()) { goto exit; @@ -796,4 +746,4 @@ exit: return return_value; } -/*[clinic end generated code: output=a1e878d3963b615e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=95a0178f30801b89 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/fcntlmodule.c.h b/contrib/tools/python3/src/Modules/clinic/fcntlmodule.c.h index 024a44cfbf..adf527fd44 100644 --- a/contrib/tools/python3/src/Modules/clinic/fcntlmodule.c.h +++ b/contrib/tools/python3/src/Modules/clinic/fcntlmodule.c.h @@ -35,12 +35,7 @@ fcntl_fcntl(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("fcntl", nargs, 2, 3)) { goto exit; } - if (!conv_descriptor(args[0], &fd)) { - goto exit; - } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { goto exit; } code = _PyLong_AsInt(args[1]); @@ -110,12 +105,7 @@ fcntl_ioctl(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("ioctl", nargs, 2, 4)) { goto exit; } - if (!conv_descriptor(args[0], &fd)) { - goto exit; - } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { goto exit; } code = (unsigned int)PyLong_AsUnsignedLongMask(args[1]); @@ -165,12 +155,7 @@ fcntl_flock(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("flock", nargs, 2, 2)) { goto exit; } - if (!conv_descriptor(args[0], &fd)) { - goto exit; - } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { goto exit; } code = _PyLong_AsInt(args[1]); @@ -230,12 +215,7 @@ fcntl_lockf(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("lockf", nargs, 2, 5)) { goto exit; } - if (!conv_descriptor(args[0], &fd)) { - goto exit; - } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { goto exit; } code = _PyLong_AsInt(args[1]); @@ -253,11 +233,6 @@ fcntl_lockf(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 5) { goto skip_optional; } - if (PyFloat_Check(args[4])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } whence = _PyLong_AsInt(args[4]); if (whence == -1 && PyErr_Occurred()) { goto exit; @@ -268,4 +243,4 @@ skip_optional: exit: return return_value; } -/*[clinic end generated code: output=e912d25e28362c52 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=8ea34bd0f7cf25ec input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/gcmodule.c.h b/contrib/tools/python3/src/Modules/clinic/gcmodule.c.h index 72795c66bf..30efc7e0c2 100644 --- a/contrib/tools/python3/src/Modules/clinic/gcmodule.c.h +++ b/contrib/tools/python3/src/Modules/clinic/gcmodule.c.h @@ -102,11 +102,6 @@ gc_collect(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject * if (!noptargs) { goto skip_optional_pos; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } generation = _PyLong_AsInt(args[0]); if (generation == -1 && PyErr_Occurred()) { goto exit; @@ -151,11 +146,6 @@ gc_set_debug(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int flags; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } flags = _PyLong_AsInt(arg); if (flags == -1 && PyErr_Occurred()) { goto exit; @@ -382,4 +372,4 @@ gc_get_freeze_count(PyObject *module, PyObject *Py_UNUSED(ignored)) exit: return return_value; } -/*[clinic end generated code: output=bd6a8056989e2e69 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=61e15f3a549f3ab5 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/itertoolsmodule.c.h b/contrib/tools/python3/src/Modules/clinic/itertoolsmodule.c.h index 251b67b17e..d3f54221dd 100644 --- a/contrib/tools/python3/src/Modules/clinic/itertoolsmodule.c.h +++ b/contrib/tools/python3/src/Modules/clinic/itertoolsmodule.c.h @@ -2,6 +2,37 @@ preserve [clinic start generated code]*/ +PyDoc_STRVAR(pairwise_new__doc__, +"pairwise(iterable, /)\n" +"--\n" +"\n" +"Return an iterator of overlapping pairs taken from the input iterator.\n" +"\n" +" s -> (s0,s1), (s1,s2), (s2, s3), ..."); + +static PyObject * +pairwise_new_impl(PyTypeObject *type, PyObject *iterable); + +static PyObject * +pairwise_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + PyObject *iterable; + + if ((type == &pairwise_type) && + !_PyArg_NoKeywords("pairwise", kwargs)) { + goto exit; + } + if (!_PyArg_CheckPositional("pairwise", PyTuple_GET_SIZE(args), 1, 1)) { + goto exit; + } + iterable = PyTuple_GET_ITEM(args, 0); + return_value = pairwise_new_impl(type, iterable); + +exit: + return return_value; +} + PyDoc_STRVAR(itertools_groupby__doc__, "groupby(iterable, key=None)\n" "--\n" @@ -170,14 +201,9 @@ itertools_tee(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 2) { goto skip_optional; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[1]); + PyObject *iobj = _PyNumber_Index(args[1]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -356,14 +382,9 @@ itertools_combinations(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto exit; } iterable = fastargs[0]; - if (PyFloat_Check(fastargs[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(fastargs[1]); + PyObject *iobj = _PyNumber_Index(fastargs[1]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -409,14 +430,9 @@ itertools_combinations_with_replacement(PyTypeObject *type, PyObject *args, PyOb goto exit; } iterable = fastargs[0]; - if (PyFloat_Check(fastargs[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(fastargs[1]); + PyObject *iobj = _PyNumber_Index(fastargs[1]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -642,4 +658,4 @@ skip_optional_pos: exit: return return_value; } -/*[clinic end generated code: output=0c2799c88400b63f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c91f57481a2461d3 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/md5module.c.h b/contrib/tools/python3/src/Modules/clinic/md5module.c.h index c109f9efec..4762f2800d 100644 --- a/contrib/tools/python3/src/Modules/clinic/md5module.c.h +++ b/contrib/tools/python3/src/Modules/clinic/md5module.c.h @@ -9,15 +9,26 @@ PyDoc_STRVAR(MD5Type_copy__doc__, "Return a copy of the hash object."); #define MD5TYPE_COPY_METHODDEF \ - {"copy", (PyCFunction)MD5Type_copy, METH_NOARGS, MD5Type_copy__doc__}, + {"copy", (PyCFunction)(void(*)(void))MD5Type_copy, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, MD5Type_copy__doc__}, static PyObject * -MD5Type_copy_impl(MD5object *self); +MD5Type_copy_impl(MD5object *self, PyTypeObject *cls); static PyObject * -MD5Type_copy(MD5object *self, PyObject *Py_UNUSED(ignored)) +MD5Type_copy(MD5object *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return MD5Type_copy_impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = {":copy", _keywords, 0}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser + )) { + goto exit; + } + return_value = MD5Type_copy_impl(self, cls); + +exit: + return return_value; } PyDoc_STRVAR(MD5Type_digest__doc__, @@ -115,4 +126,4 @@ skip_optional_kwonly: exit: return return_value; } -/*[clinic end generated code: output=dbe3abc60086f3ef input=a9049054013a1b77]*/ +/*[clinic end generated code: output=53ff7f22dbaaea36 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/overlapped.c.h b/contrib/tools/python3/src/Modules/clinic/overlapped.c.h new file mode 100644 index 0000000000..efecd9028b --- /dev/null +++ b/contrib/tools/python3/src/Modules/clinic/overlapped.c.h @@ -0,0 +1,908 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(_overlapped_CreateIoCompletionPort__doc__, +"CreateIoCompletionPort($module, handle, port, key, concurrency, /)\n" +"--\n" +"\n" +"Create a completion port or register a handle with a port."); + +#define _OVERLAPPED_CREATEIOCOMPLETIONPORT_METHODDEF \ + {"CreateIoCompletionPort", (PyCFunction)(void(*)(void))_overlapped_CreateIoCompletionPort, METH_FASTCALL, _overlapped_CreateIoCompletionPort__doc__}, + +static PyObject * +_overlapped_CreateIoCompletionPort_impl(PyObject *module, HANDLE FileHandle, + HANDLE ExistingCompletionPort, + ULONG_PTR CompletionKey, + DWORD NumberOfConcurrentThreads); + +static PyObject * +_overlapped_CreateIoCompletionPort(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + HANDLE FileHandle; + HANDLE ExistingCompletionPort; + ULONG_PTR CompletionKey; + DWORD NumberOfConcurrentThreads; + + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE""F_HANDLE""F_ULONG_PTR"k:CreateIoCompletionPort", + &FileHandle, &ExistingCompletionPort, &CompletionKey, &NumberOfConcurrentThreads)) { + goto exit; + } + return_value = _overlapped_CreateIoCompletionPort_impl(module, FileHandle, ExistingCompletionPort, CompletionKey, NumberOfConcurrentThreads); + +exit: + return return_value; +} + +PyDoc_STRVAR(_overlapped_GetQueuedCompletionStatus__doc__, +"GetQueuedCompletionStatus($module, port, msecs, /)\n" +"--\n" +"\n" +"Get a message from completion port.\n" +"\n" +"Wait for up to msecs milliseconds."); + +#define _OVERLAPPED_GETQUEUEDCOMPLETIONSTATUS_METHODDEF \ + {"GetQueuedCompletionStatus", (PyCFunction)(void(*)(void))_overlapped_GetQueuedCompletionStatus, METH_FASTCALL, _overlapped_GetQueuedCompletionStatus__doc__}, + +static PyObject * +_overlapped_GetQueuedCompletionStatus_impl(PyObject *module, + HANDLE CompletionPort, + DWORD Milliseconds); + +static PyObject * +_overlapped_GetQueuedCompletionStatus(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + HANDLE CompletionPort; + DWORD Milliseconds; + + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"k:GetQueuedCompletionStatus", + &CompletionPort, &Milliseconds)) { + goto exit; + } + return_value = _overlapped_GetQueuedCompletionStatus_impl(module, CompletionPort, Milliseconds); + +exit: + return return_value; +} + +PyDoc_STRVAR(_overlapped_PostQueuedCompletionStatus__doc__, +"PostQueuedCompletionStatus($module, port, bytes, key, address, /)\n" +"--\n" +"\n" +"Post a message to completion port."); + +#define _OVERLAPPED_POSTQUEUEDCOMPLETIONSTATUS_METHODDEF \ + {"PostQueuedCompletionStatus", (PyCFunction)(void(*)(void))_overlapped_PostQueuedCompletionStatus, METH_FASTCALL, _overlapped_PostQueuedCompletionStatus__doc__}, + +static PyObject * +_overlapped_PostQueuedCompletionStatus_impl(PyObject *module, + HANDLE CompletionPort, + DWORD NumberOfBytes, + ULONG_PTR CompletionKey, + OVERLAPPED *Overlapped); + +static PyObject * +_overlapped_PostQueuedCompletionStatus(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + HANDLE CompletionPort; + DWORD NumberOfBytes; + ULONG_PTR CompletionKey; + OVERLAPPED *Overlapped; + + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"k"F_ULONG_PTR""F_POINTER":PostQueuedCompletionStatus", + &CompletionPort, &NumberOfBytes, &CompletionKey, &Overlapped)) { + goto exit; + } + return_value = _overlapped_PostQueuedCompletionStatus_impl(module, CompletionPort, NumberOfBytes, CompletionKey, Overlapped); + +exit: + return return_value; +} + +PyDoc_STRVAR(_overlapped_RegisterWaitWithQueue__doc__, +"RegisterWaitWithQueue($module, Object, CompletionPort, Overlapped,\n" +" Timeout, /)\n" +"--\n" +"\n" +"Register wait for Object; when complete CompletionPort is notified."); + +#define _OVERLAPPED_REGISTERWAITWITHQUEUE_METHODDEF \ + {"RegisterWaitWithQueue", (PyCFunction)(void(*)(void))_overlapped_RegisterWaitWithQueue, METH_FASTCALL, _overlapped_RegisterWaitWithQueue__doc__}, + +static PyObject * +_overlapped_RegisterWaitWithQueue_impl(PyObject *module, HANDLE Object, + HANDLE CompletionPort, + OVERLAPPED *Overlapped, + DWORD Milliseconds); + +static PyObject * +_overlapped_RegisterWaitWithQueue(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + HANDLE Object; + HANDLE CompletionPort; + OVERLAPPED *Overlapped; + DWORD Milliseconds; + + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE""F_HANDLE""F_POINTER"k:RegisterWaitWithQueue", + &Object, &CompletionPort, &Overlapped, &Milliseconds)) { + goto exit; + } + return_value = _overlapped_RegisterWaitWithQueue_impl(module, Object, CompletionPort, Overlapped, Milliseconds); + +exit: + return return_value; +} + +PyDoc_STRVAR(_overlapped_UnregisterWait__doc__, +"UnregisterWait($module, WaitHandle, /)\n" +"--\n" +"\n" +"Unregister wait handle."); + +#define _OVERLAPPED_UNREGISTERWAIT_METHODDEF \ + {"UnregisterWait", (PyCFunction)_overlapped_UnregisterWait, METH_O, _overlapped_UnregisterWait__doc__}, + +static PyObject * +_overlapped_UnregisterWait_impl(PyObject *module, HANDLE WaitHandle); + +static PyObject * +_overlapped_UnregisterWait(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + HANDLE WaitHandle; + + if (!PyArg_Parse(arg, ""F_HANDLE":UnregisterWait", &WaitHandle)) { + goto exit; + } + return_value = _overlapped_UnregisterWait_impl(module, WaitHandle); + +exit: + return return_value; +} + +PyDoc_STRVAR(_overlapped_UnregisterWaitEx__doc__, +"UnregisterWaitEx($module, WaitHandle, Event, /)\n" +"--\n" +"\n" +"Unregister wait handle."); + +#define _OVERLAPPED_UNREGISTERWAITEX_METHODDEF \ + {"UnregisterWaitEx", (PyCFunction)(void(*)(void))_overlapped_UnregisterWaitEx, METH_FASTCALL, _overlapped_UnregisterWaitEx__doc__}, + +static PyObject * +_overlapped_UnregisterWaitEx_impl(PyObject *module, HANDLE WaitHandle, + HANDLE Event); + +static PyObject * +_overlapped_UnregisterWaitEx(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + HANDLE WaitHandle; + HANDLE Event; + + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE""F_HANDLE":UnregisterWaitEx", + &WaitHandle, &Event)) { + goto exit; + } + return_value = _overlapped_UnregisterWaitEx_impl(module, WaitHandle, Event); + +exit: + return return_value; +} + +PyDoc_STRVAR(_overlapped_CreateEvent__doc__, +"CreateEvent($module, EventAttributes, ManualReset, InitialState, Name,\n" +" /)\n" +"--\n" +"\n" +"Create an event.\n" +"\n" +"EventAttributes must be None."); + +#define _OVERLAPPED_CREATEEVENT_METHODDEF \ + {"CreateEvent", (PyCFunction)(void(*)(void))_overlapped_CreateEvent, METH_FASTCALL, _overlapped_CreateEvent__doc__}, + +static PyObject * +_overlapped_CreateEvent_impl(PyObject *module, PyObject *EventAttributes, + BOOL ManualReset, BOOL InitialState, + const Py_UNICODE *Name); + +static PyObject * +_overlapped_CreateEvent(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *EventAttributes; + BOOL ManualReset; + BOOL InitialState; + const Py_UNICODE *Name; + + if (!_PyArg_ParseStack(args, nargs, "OiiO&:CreateEvent", + &EventAttributes, &ManualReset, &InitialState, _PyUnicode_WideCharString_Opt_Converter, &Name)) { + goto exit; + } + return_value = _overlapped_CreateEvent_impl(module, EventAttributes, ManualReset, InitialState, Name); + +exit: + /* Cleanup for Name */ + #if !USE_UNICODE_WCHAR_CACHE + PyMem_Free((void *)Name); + #endif /* USE_UNICODE_WCHAR_CACHE */ + + return return_value; +} + +PyDoc_STRVAR(_overlapped_SetEvent__doc__, +"SetEvent($module, Handle, /)\n" +"--\n" +"\n" +"Set event."); + +#define _OVERLAPPED_SETEVENT_METHODDEF \ + {"SetEvent", (PyCFunction)_overlapped_SetEvent, METH_O, _overlapped_SetEvent__doc__}, + +static PyObject * +_overlapped_SetEvent_impl(PyObject *module, HANDLE Handle); + +static PyObject * +_overlapped_SetEvent(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + HANDLE Handle; + + if (!PyArg_Parse(arg, ""F_HANDLE":SetEvent", &Handle)) { + goto exit; + } + return_value = _overlapped_SetEvent_impl(module, Handle); + +exit: + return return_value; +} + +PyDoc_STRVAR(_overlapped_ResetEvent__doc__, +"ResetEvent($module, Handle, /)\n" +"--\n" +"\n" +"Reset event."); + +#define _OVERLAPPED_RESETEVENT_METHODDEF \ + {"ResetEvent", (PyCFunction)_overlapped_ResetEvent, METH_O, _overlapped_ResetEvent__doc__}, + +static PyObject * +_overlapped_ResetEvent_impl(PyObject *module, HANDLE Handle); + +static PyObject * +_overlapped_ResetEvent(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + HANDLE Handle; + + if (!PyArg_Parse(arg, ""F_HANDLE":ResetEvent", &Handle)) { + goto exit; + } + return_value = _overlapped_ResetEvent_impl(module, Handle); + +exit: + return return_value; +} + +PyDoc_STRVAR(_overlapped_BindLocal__doc__, +"BindLocal($module, handle, family, /)\n" +"--\n" +"\n" +"Bind a socket handle to an arbitrary local port.\n" +"\n" +"family should be AF_INET or AF_INET6."); + +#define _OVERLAPPED_BINDLOCAL_METHODDEF \ + {"BindLocal", (PyCFunction)(void(*)(void))_overlapped_BindLocal, METH_FASTCALL, _overlapped_BindLocal__doc__}, + +static PyObject * +_overlapped_BindLocal_impl(PyObject *module, HANDLE Socket, int Family); + +static PyObject * +_overlapped_BindLocal(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + HANDLE Socket; + int Family; + + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"i:BindLocal", + &Socket, &Family)) { + goto exit; + } + return_value = _overlapped_BindLocal_impl(module, Socket, Family); + +exit: + return return_value; +} + +PyDoc_STRVAR(_overlapped_FormatMessage__doc__, +"FormatMessage($module, error_code, /)\n" +"--\n" +"\n" +"Return error message for an error code."); + +#define _OVERLAPPED_FORMATMESSAGE_METHODDEF \ + {"FormatMessage", (PyCFunction)_overlapped_FormatMessage, METH_O, _overlapped_FormatMessage__doc__}, + +static PyObject * +_overlapped_FormatMessage_impl(PyObject *module, DWORD code); + +static PyObject * +_overlapped_FormatMessage(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + DWORD code; + + if (!PyArg_Parse(arg, "k:FormatMessage", &code)) { + goto exit; + } + return_value = _overlapped_FormatMessage_impl(module, code); + +exit: + return return_value; +} + +PyDoc_STRVAR(_overlapped_Overlapped__doc__, +"Overlapped(event=_overlapped.INVALID_HANDLE_VALUE)\n" +"--\n" +"\n" +"OVERLAPPED structure wrapper."); + +static PyObject * +_overlapped_Overlapped_impl(PyTypeObject *type, HANDLE event); + +static PyObject * +_overlapped_Overlapped(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"event", NULL}; + static _PyArg_Parser _parser = {"|"F_HANDLE":Overlapped", _keywords, 0}; + HANDLE event = INVALID_HANDLE_VALUE; + + if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser, + &event)) { + goto exit; + } + return_value = _overlapped_Overlapped_impl(type, event); + +exit: + return return_value; +} + +PyDoc_STRVAR(_overlapped_Overlapped_cancel__doc__, +"cancel($self, /)\n" +"--\n" +"\n" +"Cancel overlapped operation."); + +#define _OVERLAPPED_OVERLAPPED_CANCEL_METHODDEF \ + {"cancel", (PyCFunction)_overlapped_Overlapped_cancel, METH_NOARGS, _overlapped_Overlapped_cancel__doc__}, + +static PyObject * +_overlapped_Overlapped_cancel_impl(OverlappedObject *self); + +static PyObject * +_overlapped_Overlapped_cancel(OverlappedObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _overlapped_Overlapped_cancel_impl(self); +} + +PyDoc_STRVAR(_overlapped_Overlapped_getresult__doc__, +"getresult($self, wait=False, /)\n" +"--\n" +"\n" +"Retrieve result of operation.\n" +"\n" +"If wait is true then it blocks until the operation is finished. If wait\n" +"is false and the operation is still pending then an error is raised."); + +#define _OVERLAPPED_OVERLAPPED_GETRESULT_METHODDEF \ + {"getresult", (PyCFunction)(void(*)(void))_overlapped_Overlapped_getresult, METH_FASTCALL, _overlapped_Overlapped_getresult__doc__}, + +static PyObject * +_overlapped_Overlapped_getresult_impl(OverlappedObject *self, BOOL wait); + +static PyObject * +_overlapped_Overlapped_getresult(OverlappedObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + BOOL wait = FALSE; + + if (!_PyArg_ParseStack(args, nargs, "|i:getresult", + &wait)) { + goto exit; + } + return_value = _overlapped_Overlapped_getresult_impl(self, wait); + +exit: + return return_value; +} + +PyDoc_STRVAR(_overlapped_Overlapped_ReadFile__doc__, +"ReadFile($self, handle, size, /)\n" +"--\n" +"\n" +"Start overlapped read."); + +#define _OVERLAPPED_OVERLAPPED_READFILE_METHODDEF \ + {"ReadFile", (PyCFunction)(void(*)(void))_overlapped_Overlapped_ReadFile, METH_FASTCALL, _overlapped_Overlapped_ReadFile__doc__}, + +static PyObject * +_overlapped_Overlapped_ReadFile_impl(OverlappedObject *self, HANDLE handle, + DWORD size); + +static PyObject * +_overlapped_Overlapped_ReadFile(OverlappedObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + HANDLE handle; + DWORD size; + + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"k:ReadFile", + &handle, &size)) { + goto exit; + } + return_value = _overlapped_Overlapped_ReadFile_impl(self, handle, size); + +exit: + return return_value; +} + +PyDoc_STRVAR(_overlapped_Overlapped_ReadFileInto__doc__, +"ReadFileInto($self, handle, buf, /)\n" +"--\n" +"\n" +"Start overlapped receive."); + +#define _OVERLAPPED_OVERLAPPED_READFILEINTO_METHODDEF \ + {"ReadFileInto", (PyCFunction)(void(*)(void))_overlapped_Overlapped_ReadFileInto, METH_FASTCALL, _overlapped_Overlapped_ReadFileInto__doc__}, + +static PyObject * +_overlapped_Overlapped_ReadFileInto_impl(OverlappedObject *self, + HANDLE handle, PyObject *bufobj); + +static PyObject * +_overlapped_Overlapped_ReadFileInto(OverlappedObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + HANDLE handle; + PyObject *bufobj; + + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"O:ReadFileInto", + &handle, &bufobj)) { + goto exit; + } + return_value = _overlapped_Overlapped_ReadFileInto_impl(self, handle, bufobj); + +exit: + return return_value; +} + +PyDoc_STRVAR(_overlapped_Overlapped_WSARecv__doc__, +"WSARecv($self, handle, size, flags=0, /)\n" +"--\n" +"\n" +"Start overlapped receive."); + +#define _OVERLAPPED_OVERLAPPED_WSARECV_METHODDEF \ + {"WSARecv", (PyCFunction)(void(*)(void))_overlapped_Overlapped_WSARecv, METH_FASTCALL, _overlapped_Overlapped_WSARecv__doc__}, + +static PyObject * +_overlapped_Overlapped_WSARecv_impl(OverlappedObject *self, HANDLE handle, + DWORD size, DWORD flags); + +static PyObject * +_overlapped_Overlapped_WSARecv(OverlappedObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + HANDLE handle; + DWORD size; + DWORD flags = 0; + + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"k|k:WSARecv", + &handle, &size, &flags)) { + goto exit; + } + return_value = _overlapped_Overlapped_WSARecv_impl(self, handle, size, flags); + +exit: + return return_value; +} + +PyDoc_STRVAR(_overlapped_Overlapped_WSARecvInto__doc__, +"WSARecvInto($self, handle, buf, flags, /)\n" +"--\n" +"\n" +"Start overlapped receive."); + +#define _OVERLAPPED_OVERLAPPED_WSARECVINTO_METHODDEF \ + {"WSARecvInto", (PyCFunction)(void(*)(void))_overlapped_Overlapped_WSARecvInto, METH_FASTCALL, _overlapped_Overlapped_WSARecvInto__doc__}, + +static PyObject * +_overlapped_Overlapped_WSARecvInto_impl(OverlappedObject *self, + HANDLE handle, PyObject *bufobj, + DWORD flags); + +static PyObject * +_overlapped_Overlapped_WSARecvInto(OverlappedObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + HANDLE handle; + PyObject *bufobj; + DWORD flags; + + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"Ok:WSARecvInto", + &handle, &bufobj, &flags)) { + goto exit; + } + return_value = _overlapped_Overlapped_WSARecvInto_impl(self, handle, bufobj, flags); + +exit: + return return_value; +} + +PyDoc_STRVAR(_overlapped_Overlapped_WriteFile__doc__, +"WriteFile($self, handle, buf, /)\n" +"--\n" +"\n" +"Start overlapped write."); + +#define _OVERLAPPED_OVERLAPPED_WRITEFILE_METHODDEF \ + {"WriteFile", (PyCFunction)(void(*)(void))_overlapped_Overlapped_WriteFile, METH_FASTCALL, _overlapped_Overlapped_WriteFile__doc__}, + +static PyObject * +_overlapped_Overlapped_WriteFile_impl(OverlappedObject *self, HANDLE handle, + PyObject *bufobj); + +static PyObject * +_overlapped_Overlapped_WriteFile(OverlappedObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + HANDLE handle; + PyObject *bufobj; + + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"O:WriteFile", + &handle, &bufobj)) { + goto exit; + } + return_value = _overlapped_Overlapped_WriteFile_impl(self, handle, bufobj); + +exit: + return return_value; +} + +PyDoc_STRVAR(_overlapped_Overlapped_WSASend__doc__, +"WSASend($self, handle, buf, flags, /)\n" +"--\n" +"\n" +"Start overlapped send."); + +#define _OVERLAPPED_OVERLAPPED_WSASEND_METHODDEF \ + {"WSASend", (PyCFunction)(void(*)(void))_overlapped_Overlapped_WSASend, METH_FASTCALL, _overlapped_Overlapped_WSASend__doc__}, + +static PyObject * +_overlapped_Overlapped_WSASend_impl(OverlappedObject *self, HANDLE handle, + PyObject *bufobj, DWORD flags); + +static PyObject * +_overlapped_Overlapped_WSASend(OverlappedObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + HANDLE handle; + PyObject *bufobj; + DWORD flags; + + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"Ok:WSASend", + &handle, &bufobj, &flags)) { + goto exit; + } + return_value = _overlapped_Overlapped_WSASend_impl(self, handle, bufobj, flags); + +exit: + return return_value; +} + +PyDoc_STRVAR(_overlapped_Overlapped_AcceptEx__doc__, +"AcceptEx($self, listen_handle, accept_handle, /)\n" +"--\n" +"\n" +"Start overlapped wait for client to connect."); + +#define _OVERLAPPED_OVERLAPPED_ACCEPTEX_METHODDEF \ + {"AcceptEx", (PyCFunction)(void(*)(void))_overlapped_Overlapped_AcceptEx, METH_FASTCALL, _overlapped_Overlapped_AcceptEx__doc__}, + +static PyObject * +_overlapped_Overlapped_AcceptEx_impl(OverlappedObject *self, + HANDLE ListenSocket, + HANDLE AcceptSocket); + +static PyObject * +_overlapped_Overlapped_AcceptEx(OverlappedObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + HANDLE ListenSocket; + HANDLE AcceptSocket; + + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE""F_HANDLE":AcceptEx", + &ListenSocket, &AcceptSocket)) { + goto exit; + } + return_value = _overlapped_Overlapped_AcceptEx_impl(self, ListenSocket, AcceptSocket); + +exit: + return return_value; +} + +PyDoc_STRVAR(_overlapped_Overlapped_ConnectEx__doc__, +"ConnectEx($self, client_handle, address_as_bytes, /)\n" +"--\n" +"\n" +"Start overlapped connect.\n" +"\n" +"client_handle should be unbound."); + +#define _OVERLAPPED_OVERLAPPED_CONNECTEX_METHODDEF \ + {"ConnectEx", (PyCFunction)(void(*)(void))_overlapped_Overlapped_ConnectEx, METH_FASTCALL, _overlapped_Overlapped_ConnectEx__doc__}, + +static PyObject * +_overlapped_Overlapped_ConnectEx_impl(OverlappedObject *self, + HANDLE ConnectSocket, + PyObject *AddressObj); + +static PyObject * +_overlapped_Overlapped_ConnectEx(OverlappedObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + HANDLE ConnectSocket; + PyObject *AddressObj; + + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"O!:ConnectEx", + &ConnectSocket, &PyTuple_Type, &AddressObj)) { + goto exit; + } + return_value = _overlapped_Overlapped_ConnectEx_impl(self, ConnectSocket, AddressObj); + +exit: + return return_value; +} + +PyDoc_STRVAR(_overlapped_Overlapped_DisconnectEx__doc__, +"DisconnectEx($self, handle, flags, /)\n" +"--\n" +"\n"); + +#define _OVERLAPPED_OVERLAPPED_DISCONNECTEX_METHODDEF \ + {"DisconnectEx", (PyCFunction)(void(*)(void))_overlapped_Overlapped_DisconnectEx, METH_FASTCALL, _overlapped_Overlapped_DisconnectEx__doc__}, + +static PyObject * +_overlapped_Overlapped_DisconnectEx_impl(OverlappedObject *self, + HANDLE Socket, DWORD flags); + +static PyObject * +_overlapped_Overlapped_DisconnectEx(OverlappedObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + HANDLE Socket; + DWORD flags; + + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"k:DisconnectEx", + &Socket, &flags)) { + goto exit; + } + return_value = _overlapped_Overlapped_DisconnectEx_impl(self, Socket, flags); + +exit: + return return_value; +} + +PyDoc_STRVAR(_overlapped_Overlapped_TransmitFile__doc__, +"TransmitFile($self, socket, file, offset, offset_high, count_to_write,\n" +" count_per_send, flags, /)\n" +"--\n" +"\n" +"Transmit file data over a connected socket."); + +#define _OVERLAPPED_OVERLAPPED_TRANSMITFILE_METHODDEF \ + {"TransmitFile", (PyCFunction)(void(*)(void))_overlapped_Overlapped_TransmitFile, METH_FASTCALL, _overlapped_Overlapped_TransmitFile__doc__}, + +static PyObject * +_overlapped_Overlapped_TransmitFile_impl(OverlappedObject *self, + HANDLE Socket, HANDLE File, + DWORD offset, DWORD offset_high, + DWORD count_to_write, + DWORD count_per_send, DWORD flags); + +static PyObject * +_overlapped_Overlapped_TransmitFile(OverlappedObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + HANDLE Socket; + HANDLE File; + DWORD offset; + DWORD offset_high; + DWORD count_to_write; + DWORD count_per_send; + DWORD flags; + + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE""F_HANDLE"kkkkk:TransmitFile", + &Socket, &File, &offset, &offset_high, &count_to_write, &count_per_send, &flags)) { + goto exit; + } + return_value = _overlapped_Overlapped_TransmitFile_impl(self, Socket, File, offset, offset_high, count_to_write, count_per_send, flags); + +exit: + return return_value; +} + +PyDoc_STRVAR(_overlapped_Overlapped_ConnectNamedPipe__doc__, +"ConnectNamedPipe($self, handle, /)\n" +"--\n" +"\n" +"Start overlapped wait for a client to connect."); + +#define _OVERLAPPED_OVERLAPPED_CONNECTNAMEDPIPE_METHODDEF \ + {"ConnectNamedPipe", (PyCFunction)_overlapped_Overlapped_ConnectNamedPipe, METH_O, _overlapped_Overlapped_ConnectNamedPipe__doc__}, + +static PyObject * +_overlapped_Overlapped_ConnectNamedPipe_impl(OverlappedObject *self, + HANDLE Pipe); + +static PyObject * +_overlapped_Overlapped_ConnectNamedPipe(OverlappedObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + HANDLE Pipe; + + if (!PyArg_Parse(arg, ""F_HANDLE":ConnectNamedPipe", &Pipe)) { + goto exit; + } + return_value = _overlapped_Overlapped_ConnectNamedPipe_impl(self, Pipe); + +exit: + return return_value; +} + +PyDoc_STRVAR(_overlapped_Overlapped_ConnectPipe__doc__, +"ConnectPipe($self, addr, /)\n" +"--\n" +"\n" +"Connect to the pipe for asynchronous I/O (overlapped)."); + +#define _OVERLAPPED_OVERLAPPED_CONNECTPIPE_METHODDEF \ + {"ConnectPipe", (PyCFunction)_overlapped_Overlapped_ConnectPipe, METH_O, _overlapped_Overlapped_ConnectPipe__doc__}, + +static PyObject * +_overlapped_Overlapped_ConnectPipe_impl(OverlappedObject *self, + const Py_UNICODE *Address); + +static PyObject * +_overlapped_Overlapped_ConnectPipe(OverlappedObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + const Py_UNICODE *Address; + + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("ConnectPipe", "argument", "str", arg); + goto exit; + } + #if USE_UNICODE_WCHAR_CACHE + Address = _PyUnicode_AsUnicode(arg); + #else /* USE_UNICODE_WCHAR_CACHE */ + Address = PyUnicode_AsWideCharString(arg, NULL); + #endif /* USE_UNICODE_WCHAR_CACHE */ + if (Address == NULL) { + goto exit; + } + return_value = _overlapped_Overlapped_ConnectPipe_impl(self, Address); + +exit: + /* Cleanup for Address */ + #if !USE_UNICODE_WCHAR_CACHE + PyMem_Free((void *)Address); + #endif /* USE_UNICODE_WCHAR_CACHE */ + + return return_value; +} + +PyDoc_STRVAR(_overlapped_WSAConnect__doc__, +"WSAConnect($module, client_handle, address_as_bytes, /)\n" +"--\n" +"\n" +"Bind a remote address to a connectionless (UDP) socket."); + +#define _OVERLAPPED_WSACONNECT_METHODDEF \ + {"WSAConnect", (PyCFunction)(void(*)(void))_overlapped_WSAConnect, METH_FASTCALL, _overlapped_WSAConnect__doc__}, + +static PyObject * +_overlapped_WSAConnect_impl(PyObject *module, HANDLE ConnectSocket, + PyObject *AddressObj); + +static PyObject * +_overlapped_WSAConnect(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + HANDLE ConnectSocket; + PyObject *AddressObj; + + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"O:WSAConnect", + &ConnectSocket, &AddressObj)) { + goto exit; + } + return_value = _overlapped_WSAConnect_impl(module, ConnectSocket, AddressObj); + +exit: + return return_value; +} + +PyDoc_STRVAR(_overlapped_Overlapped_WSASendTo__doc__, +"WSASendTo($self, handle, buf, flags, address_as_bytes, /)\n" +"--\n" +"\n" +"Start overlapped sendto over a connectionless (UDP) socket."); + +#define _OVERLAPPED_OVERLAPPED_WSASENDTO_METHODDEF \ + {"WSASendTo", (PyCFunction)(void(*)(void))_overlapped_Overlapped_WSASendTo, METH_FASTCALL, _overlapped_Overlapped_WSASendTo__doc__}, + +static PyObject * +_overlapped_Overlapped_WSASendTo_impl(OverlappedObject *self, HANDLE handle, + PyObject *bufobj, DWORD flags, + PyObject *AddressObj); + +static PyObject * +_overlapped_Overlapped_WSASendTo(OverlappedObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + HANDLE handle; + PyObject *bufobj; + DWORD flags; + PyObject *AddressObj; + + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"OkO:WSASendTo", + &handle, &bufobj, &flags, &AddressObj)) { + goto exit; + } + return_value = _overlapped_Overlapped_WSASendTo_impl(self, handle, bufobj, flags, AddressObj); + +exit: + return return_value; +} + +PyDoc_STRVAR(_overlapped_Overlapped_WSARecvFrom__doc__, +"WSARecvFrom($self, handle, size, flags=0, /)\n" +"--\n" +"\n" +"Start overlapped receive."); + +#define _OVERLAPPED_OVERLAPPED_WSARECVFROM_METHODDEF \ + {"WSARecvFrom", (PyCFunction)(void(*)(void))_overlapped_Overlapped_WSARecvFrom, METH_FASTCALL, _overlapped_Overlapped_WSARecvFrom__doc__}, + +static PyObject * +_overlapped_Overlapped_WSARecvFrom_impl(OverlappedObject *self, + HANDLE handle, DWORD size, + DWORD flags); + +static PyObject * +_overlapped_Overlapped_WSARecvFrom(OverlappedObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + HANDLE handle; + DWORD size; + DWORD flags = 0; + + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"k|k:WSARecvFrom", + &handle, &size, &flags)) { + goto exit; + } + return_value = _overlapped_Overlapped_WSARecvFrom_impl(self, handle, size, flags); + +exit: + return return_value; +} +/*[clinic end generated code: output=ee2ec2f93c8d334b input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/posixmodule.c.h b/contrib/tools/python3/src/Modules/clinic/posixmodule.c.h index 28798ab99c..7921c222b9 100644 --- a/contrib/tools/python3/src/Modules/clinic/posixmodule.c.h +++ b/contrib/tools/python3/src/Modules/clinic/posixmodule.c.h @@ -187,11 +187,6 @@ os_access(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k if (!path_converter(args[0], &path)) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } mode = _PyLong_AsInt(args[1]); if (mode == -1 && PyErr_Occurred()) { goto exit; @@ -257,11 +252,6 @@ os_ttyname(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int fd; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(arg); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -367,7 +357,7 @@ os_fchdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k if (!args) { goto exit; } - if (!fildes_converter(args[0], &fd)) { + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { goto exit; } return_value = os_fchdir_impl(module, fd); @@ -431,11 +421,6 @@ os_chmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw if (!path_converter(args[0], &path)) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } mode = _PyLong_AsInt(args[1]); if (mode == -1 && PyErr_Occurred()) { goto exit; @@ -495,20 +480,10 @@ os_fchmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } mode = _PyLong_AsInt(args[1]); if (mode == -1 && PyErr_Occurred()) { goto exit; @@ -555,11 +530,6 @@ os_lchmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k if (!path_converter(args[0], &path)) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } mode = _PyLong_AsInt(args[1]); if (mode == -1 && PyErr_Occurred()) { goto exit; @@ -757,7 +727,7 @@ os_fsync(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw if (!args) { goto exit; } - if (!fildes_converter(args[0], &fd)) { + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { goto exit; } return_value = os_fsync_impl(module, fd); @@ -817,7 +787,7 @@ os_fdatasync(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (!args) { goto exit; } - if (!fildes_converter(args[0], &fd)) { + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { goto exit; } return_value = os_fdatasync_impl(module, fd); @@ -952,11 +922,6 @@ os_fchown(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -1394,11 +1359,6 @@ os_mkdir(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw goto skip_optional_pos; } if (args[1]) { - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } mode = _PyLong_AsInt(args[1]); if (mode == -1 && PyErr_Occurred()) { goto exit; @@ -1444,11 +1404,6 @@ os_nice(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int increment; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } increment = _PyLong_AsInt(arg); if (increment == -1 && PyErr_Occurred()) { goto exit; @@ -1489,20 +1444,10 @@ os_getpriority(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } which = _PyLong_AsInt(args[0]); if (which == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } who = _PyLong_AsInt(args[1]); if (who == -1 && PyErr_Occurred()) { goto exit; @@ -1544,29 +1489,14 @@ os_setpriority(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } which = _PyLong_AsInt(args[0]); if (which == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } who = _PyLong_AsInt(args[1]); if (who == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } priority = _PyLong_AsInt(args[2]); if (priority == -1 && PyErr_Occurred()) { goto exit; @@ -1785,12 +1715,25 @@ os_system(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k { PyObject *return_value = NULL; static const char * const _keywords[] = {"command", NULL}; - static _PyArg_Parser _parser = {"u:system", _keywords, 0}; + static _PyArg_Parser _parser = {NULL, _keywords, "system", 0}; + PyObject *argsbuf[1]; const Py_UNICODE *command; long _return_value; - if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &command)) { + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("system", "argument 'command'", "str", args[0]); + goto exit; + } + #if USE_UNICODE_WCHAR_CACHE + command = _PyUnicode_AsUnicode(args[0]); + #else /* USE_UNICODE_WCHAR_CACHE */ + command = PyUnicode_AsWideCharString(args[0], NULL); + #endif /* USE_UNICODE_WCHAR_CACHE */ + if (command == NULL) { goto exit; } _return_value = os_system_impl(module, command); @@ -1800,6 +1743,11 @@ os_system(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k return_value = PyLong_FromLong(_return_value); exit: + /* Cleanup for command */ + #if !USE_UNICODE_WCHAR_CACHE + PyMem_Free((void *)command); + #endif /* USE_UNICODE_WCHAR_CACHE */ + return return_value; } @@ -1869,11 +1817,6 @@ os_umask(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int mask; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } mask = _PyLong_AsInt(arg); if (mask == -1 && PyErr_Occurred()) { goto exit; @@ -2134,11 +2077,6 @@ os__exit(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } status = _PyLong_AsInt(args[0]); if (status == -1 && PyErr_Occurred()) { goto exit; @@ -2330,11 +2268,6 @@ os_posix_spawn(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje } } if (args[5]) { - if (PyFloat_Check(args[5])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } resetids = _PyLong_AsInt(args[5]); if (resetids == -1 && PyErr_Occurred()) { goto exit; @@ -2344,11 +2277,6 @@ os_posix_spawn(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje } } if (args[6]) { - if (PyFloat_Check(args[6])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } setsid = _PyLong_AsInt(args[6]); if (setsid == -1 && PyErr_Occurred()) { goto exit; @@ -2467,11 +2395,6 @@ os_posix_spawnp(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj } } if (args[5]) { - if (PyFloat_Check(args[5])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } resetids = _PyLong_AsInt(args[5]); if (resetids == -1 && PyErr_Occurred()) { goto exit; @@ -2481,11 +2404,6 @@ os_posix_spawnp(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj } } if (args[6]) { - if (PyFloat_Check(args[6])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } setsid = _PyLong_AsInt(args[6]); if (setsid == -1 && PyErr_Occurred()) { goto exit; @@ -2551,11 +2469,6 @@ os_spawnv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("spawnv", nargs, 3, 3)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } mode = _PyLong_AsInt(args[0]); if (mode == -1 && PyErr_Occurred()) { goto exit; @@ -2611,11 +2524,6 @@ os_spawnve(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("spawnve", nargs, 4, 4)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } mode = _PyLong_AsInt(args[0]); if (mode == -1 && PyErr_Occurred()) { goto exit; @@ -2779,11 +2687,6 @@ os_sched_get_priority_max(PyObject *module, PyObject *const *args, Py_ssize_t na if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } policy = _PyLong_AsInt(args[0]); if (policy == -1 && PyErr_Occurred()) { goto exit; @@ -2823,11 +2726,6 @@ os_sched_get_priority_min(PyObject *module, PyObject *const *args, Py_ssize_t na if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } policy = _PyLong_AsInt(args[0]); if (policy == -1 && PyErr_Occurred()) { goto exit; @@ -3329,11 +3227,6 @@ os_getgrouplist(PyObject *module, PyObject *const *args, Py_ssize_t nargs) PyErr_SetString(PyExc_ValueError, "embedded null character"); goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } basegid = _PyLong_AsInt(args[1]); if (basegid == -1 && PyErr_Occurred()) { goto exit; @@ -3452,11 +3345,6 @@ os_initgroups(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!PyUnicode_FSConverter(args[0], &oname)) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } gid = _PyLong_AsInt(args[1]); if (gid == -1 && PyErr_Occurred()) { goto exit; @@ -3750,11 +3638,6 @@ os_plock(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int op; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } op = _PyLong_AsInt(arg); if (op == -1 && PyErr_Occurred()) { goto exit; @@ -4010,11 +3893,6 @@ os_wait3(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } options = _PyLong_AsInt(args[0]); if (options == -1 && PyErr_Occurred()) { goto exit; @@ -4518,11 +4396,6 @@ os_tcgetpgrp(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int fd; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(arg); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -4606,11 +4479,6 @@ os_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn if (!path_converter(args[0], &path)) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } flags = _PyLong_AsInt(args[1]); if (flags == -1 && PyErr_Occurred()) { goto exit; @@ -4619,11 +4487,6 @@ os_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn goto skip_optional_pos; } if (args[2]) { - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } mode = _PyLong_AsInt(args[2]); if (mode == -1 && PyErr_Occurred()) { goto exit; @@ -4678,11 +4541,6 @@ os_close(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -4715,20 +4573,10 @@ os_closerange(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("closerange", nargs, 2, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd_low = _PyLong_AsInt(args[0]); if (fd_low == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd_high = _PyLong_AsInt(args[1]); if (fd_high == -1 && PyErr_Occurred()) { goto exit; @@ -4758,11 +4606,6 @@ os_dup(PyObject *module, PyObject *arg) int fd; int _return_value; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(arg); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -4806,20 +4649,10 @@ os_dup2(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd2 = _PyLong_AsInt(args[1]); if (fd2 == -1 && PyErr_Occurred()) { goto exit; @@ -4874,20 +4707,10 @@ os_lockf(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("lockf", nargs, 3, 3)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } command = _PyLong_AsInt(args[1]); if (command == -1 && PyErr_Occurred()) { goto exit; @@ -4930,11 +4753,6 @@ os_lseek(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("lseek", nargs, 3, 3)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -4942,11 +4760,6 @@ os_lseek(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!Py_off_t_converter(args[1], &position)) { goto exit; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } how = _PyLong_AsInt(args[2]); if (how == -1 && PyErr_Occurred()) { goto exit; @@ -4983,23 +4796,13 @@ os_read(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("read", nargs, 2, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[1]); + PyObject *iobj = _PyNumber_Index(args[1]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -5048,11 +4851,6 @@ os_readv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("readv", nargs, 2, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -5098,23 +4896,13 @@ os_pread(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("pread", nargs, 3, 3)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[1]); + PyObject *iobj = _PyNumber_Index(args[1]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -5177,11 +4965,6 @@ os_preadv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("preadv", nargs, 3, 4)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -5193,11 +4976,6 @@ os_preadv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 4) { goto skip_optional; } - if (PyFloat_Check(args[3])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } flags = _PyLong_AsInt(args[3]); if (flags == -1 && PyErr_Occurred()) { goto exit; @@ -5238,11 +5016,6 @@ os_write(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("write", nargs, 2, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -5306,20 +5079,10 @@ os_sendfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } out_fd = _PyLong_AsInt(args[0]); if (out_fd == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } in_fd = _PyLong_AsInt(args[1]); if (in_fd == -1 && PyErr_Occurred()) { goto exit; @@ -5345,11 +5108,6 @@ os_sendfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto skip_optional_pos; } } - if (PyFloat_Check(args[6])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } flags = _PyLong_AsInt(args[6]); if (flags == -1 && PyErr_Occurred()) { goto exit; @@ -5400,20 +5158,10 @@ os_sendfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } out_fd = _PyLong_AsInt(args[0]); if (out_fd == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } in_fd = _PyLong_AsInt(args[1]); if (in_fd == -1 && PyErr_Occurred()) { goto exit; @@ -5421,14 +5169,9 @@ os_sendfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (!Py_off_t_converter(args[2], &offset)) { goto exit; } - if (PyFloat_Check(args[3])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[3]); + PyObject *iobj = _PyNumber_Index(args[3]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -5453,11 +5196,6 @@ os_sendfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto skip_optional_pos; } } - if (PyFloat_Check(args[6])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } flags = _PyLong_AsInt(args[6]); if (flags == -1 && PyErr_Occurred()) { goto exit; @@ -5502,33 +5240,18 @@ os_sendfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } out_fd = _PyLong_AsInt(args[0]); if (out_fd == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } in_fd = _PyLong_AsInt(args[1]); if (in_fd == -1 && PyErr_Occurred()) { goto exit; } offobj = args[2]; - if (PyFloat_Check(args[3])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[3]); + PyObject *iobj = _PyNumber_Index(args[3]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -5571,29 +5294,14 @@ os__fcopyfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("_fcopyfile", nargs, 3, 3)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } in_fd = _PyLong_AsInt(args[0]); if (in_fd == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } out_fd = _PyLong_AsInt(args[1]); if (out_fd == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } flags = _PyLong_AsInt(args[2]); if (flags == -1 && PyErr_Occurred()) { goto exit; @@ -5634,11 +5342,6 @@ os_fstat(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -5671,11 +5374,6 @@ os_isatty(PyObject *module, PyObject *arg) int fd; int _return_value; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(arg); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -5741,11 +5439,6 @@ os_pipe2(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int flags; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } flags = _PyLong_AsInt(arg); if (flags == -1 && PyErr_Occurred()) { goto exit; @@ -5786,11 +5479,6 @@ os_writev(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("writev", nargs, 2, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -5838,11 +5526,6 @@ os_pwrite(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("pwrite", nargs, 3, 3)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -5893,6 +5576,7 @@ PyDoc_STRVAR(os_pwritev__doc__, "\n" "- RWF_DSYNC\n" "- RWF_SYNC\n" +"- RWF_APPEND\n" "\n" "Using non-zero flags requires Linux 4.7 or newer."); @@ -5916,11 +5600,6 @@ os_pwritev(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("pwritev", nargs, 3, 4)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -5932,11 +5611,6 @@ os_pwritev(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 4) { goto skip_optional; } - if (PyFloat_Check(args[3])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } flags = _PyLong_AsInt(args[3]); if (flags == -1 && PyErr_Occurred()) { goto exit; @@ -6002,32 +5676,17 @@ os_copy_file_range(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } src = _PyLong_AsInt(args[0]); if (src == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } dst = _PyLong_AsInt(args[1]); if (dst == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[2]); + PyObject *iobj = _PyNumber_Index(args[2]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -6056,6 +5715,106 @@ exit: #endif /* defined(HAVE_COPY_FILE_RANGE) */ +#if ((defined(HAVE_SPLICE) && !defined(_AIX))) + +PyDoc_STRVAR(os_splice__doc__, +"splice($module, /, src, dst, count, offset_src=None, offset_dst=None,\n" +" flags=0)\n" +"--\n" +"\n" +"Transfer count bytes from one pipe to a descriptor or vice versa.\n" +"\n" +" src\n" +" Source file descriptor.\n" +" dst\n" +" Destination file descriptor.\n" +" count\n" +" Number of bytes to copy.\n" +" offset_src\n" +" Starting offset in src.\n" +" offset_dst\n" +" Starting offset in dst.\n" +" flags\n" +" Flags to modify the semantics of the call.\n" +"\n" +"If offset_src is None, then src is read from the current position;\n" +"respectively for offset_dst. The offset associated to the file\n" +"descriptor that refers to a pipe must be None."); + +#define OS_SPLICE_METHODDEF \ + {"splice", (PyCFunction)(void(*)(void))os_splice, METH_FASTCALL|METH_KEYWORDS, os_splice__doc__}, + +static PyObject * +os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count, + PyObject *offset_src, PyObject *offset_dst, + unsigned int flags); + +static PyObject * +os_splice(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"src", "dst", "count", "offset_src", "offset_dst", "flags", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "splice", 0}; + PyObject *argsbuf[6]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; + int src; + int dst; + Py_ssize_t count; + PyObject *offset_src = Py_None; + PyObject *offset_dst = Py_None; + unsigned int flags = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 6, 0, argsbuf); + if (!args) { + goto exit; + } + src = _PyLong_AsInt(args[0]); + if (src == -1 && PyErr_Occurred()) { + goto exit; + } + dst = _PyLong_AsInt(args[1]); + if (dst == -1 && PyErr_Occurred()) { + goto exit; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[2]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + count = ival; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[3]) { + offset_src = args[3]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[4]) { + offset_dst = args[4]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (!_PyLong_UnsignedInt_Converter(args[5], &flags)) { + goto exit; + } +skip_optional_pos: + return_value = os_splice_impl(module, src, dst, count, offset_src, offset_dst, flags); + +exit: + return return_value; +} + +#endif /* ((defined(HAVE_SPLICE) && !defined(_AIX))) */ + #if defined(HAVE_MKFIFO) PyDoc_STRVAR(os_mkfifo__doc__, @@ -6098,11 +5857,6 @@ os_mkfifo(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k goto skip_optional_pos; } if (args[1]) { - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } mode = _PyLong_AsInt(args[1]); if (mode == -1 && PyErr_Occurred()) { goto exit; @@ -6181,11 +5935,6 @@ os_mknod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw goto skip_optional_pos; } if (args[1]) { - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } mode = _PyLong_AsInt(args[1]); if (mode == -1 && PyErr_Occurred()) { goto exit; @@ -6318,20 +6067,10 @@ os_makedev(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("makedev", nargs, 2, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } major = _PyLong_AsInt(args[0]); if (major == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } minor = _PyLong_AsInt(args[1]); if (minor == -1 && PyErr_Occurred()) { goto exit; @@ -6372,11 +6111,6 @@ os_ftruncate(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("ftruncate", nargs, 2, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -6469,11 +6203,6 @@ os_posix_fallocate(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("posix_fallocate", nargs, 3, 3)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -6527,11 +6256,6 @@ os_posix_fadvise(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("posix_fadvise", nargs, 4, 4)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -6542,11 +6266,6 @@ os_posix_fadvise(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!Py_off_t_converter(args[2], &length)) { goto exit; } - if (PyFloat_Check(args[3])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } advice = _PyLong_AsInt(args[3]); if (advice == -1 && PyErr_Occurred()) { goto exit; @@ -6738,11 +6457,6 @@ os_strerror(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int code; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } code = _PyLong_AsInt(arg); if (code == -1 && PyErr_Occurred()) { goto exit; @@ -6774,11 +6488,6 @@ os_WCOREDUMP(PyObject *module, PyObject *arg) int status; int _return_value; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } status = _PyLong_AsInt(arg); if (status == -1 && PyErr_Occurred()) { goto exit; @@ -6826,11 +6535,6 @@ os_WIFCONTINUED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } status = _PyLong_AsInt(args[0]); if (status == -1 && PyErr_Occurred()) { goto exit; @@ -6875,11 +6579,6 @@ os_WIFSTOPPED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } status = _PyLong_AsInt(args[0]); if (status == -1 && PyErr_Occurred()) { goto exit; @@ -6924,11 +6623,6 @@ os_WIFSIGNALED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } status = _PyLong_AsInt(args[0]); if (status == -1 && PyErr_Occurred()) { goto exit; @@ -6973,11 +6667,6 @@ os_WIFEXITED(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } status = _PyLong_AsInt(args[0]); if (status == -1 && PyErr_Occurred()) { goto exit; @@ -7022,11 +6711,6 @@ os_WEXITSTATUS(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } status = _PyLong_AsInt(args[0]); if (status == -1 && PyErr_Occurred()) { goto exit; @@ -7071,11 +6755,6 @@ os_WTERMSIG(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } status = _PyLong_AsInt(args[0]); if (status == -1 && PyErr_Occurred()) { goto exit; @@ -7120,11 +6799,6 @@ os_WSTOPSIG(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } status = _PyLong_AsInt(args[0]); if (status == -1 && PyErr_Occurred()) { goto exit; @@ -7163,11 +6837,6 @@ os_fstatvfs(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int fd; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(arg); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -7293,13 +6962,7 @@ os_fpathconf(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("fpathconf", nargs, 2, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } - fd = _PyLong_AsInt(args[0]); - if (fd == -1 && PyErr_Occurred()) { + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { goto exit; } if (!conv_path_confname(args[1], &name)) { @@ -7462,7 +7125,8 @@ os_abort(PyObject *module, PyObject *Py_UNUSED(ignored)) #if defined(MS_WINDOWS) PyDoc_STRVAR(os_startfile__doc__, -"startfile($module, /, filepath, operation=<unrepresentable>)\n" +"startfile($module, /, filepath, operation=<unrepresentable>,\n" +" arguments=<unrepresentable>, cwd=None, show_cmd=1)\n" "--\n" "\n" "Start a file with its associated application.\n" @@ -7474,6 +7138,16 @@ PyDoc_STRVAR(os_startfile__doc__, "When another \"operation\" is given, it specifies what should be done with\n" "the file. A typical operation is \"print\".\n" "\n" +"\"arguments\" is passed to the application, but should be omitted if the\n" +"file is a document.\n" +"\n" +"\"cwd\" is the working directory for the operation. If \"filepath\" is\n" +"relative, it will be resolved against this directory. This argument\n" +"should usually be an absolute path.\n" +"\n" +"\"show_cmd\" can be used to override the recommended visibility option.\n" +"See the Windows ShellExecute documentation for values.\n" +"\n" "startfile returns as soon as the associated application is launched.\n" "There is no option to wait for the application to close, and no way\n" "to retrieve the application\'s exit status.\n" @@ -7487,26 +7161,95 @@ PyDoc_STRVAR(os_startfile__doc__, static PyObject * os_startfile_impl(PyObject *module, path_t *filepath, - const Py_UNICODE *operation); + const Py_UNICODE *operation, const Py_UNICODE *arguments, + path_t *cwd, int show_cmd); static PyObject * os_startfile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; - static const char * const _keywords[] = {"filepath", "operation", NULL}; - static _PyArg_Parser _parser = {"O&|u:startfile", _keywords, 0}; + static const char * const _keywords[] = {"filepath", "operation", "arguments", "cwd", "show_cmd", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "startfile", 0}; + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; path_t filepath = PATH_T_INITIALIZE("startfile", "filepath", 0, 0); const Py_UNICODE *operation = NULL; + const Py_UNICODE *arguments = NULL; + path_t cwd = PATH_T_INITIALIZE("startfile", "cwd", 1, 0); + int show_cmd = 1; - if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - path_converter, &filepath, &operation)) { + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 5, 0, argsbuf); + if (!args) { goto exit; } - return_value = os_startfile_impl(module, &filepath, operation); + if (!path_converter(args[0], &filepath)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[1]) { + if (!PyUnicode_Check(args[1])) { + _PyArg_BadArgument("startfile", "argument 'operation'", "str", args[1]); + goto exit; + } + #if USE_UNICODE_WCHAR_CACHE + operation = _PyUnicode_AsUnicode(args[1]); + #else /* USE_UNICODE_WCHAR_CACHE */ + operation = PyUnicode_AsWideCharString(args[1], NULL); + #endif /* USE_UNICODE_WCHAR_CACHE */ + if (operation == NULL) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[2]) { + if (!PyUnicode_Check(args[2])) { + _PyArg_BadArgument("startfile", "argument 'arguments'", "str", args[2]); + goto exit; + } + #if USE_UNICODE_WCHAR_CACHE + arguments = _PyUnicode_AsUnicode(args[2]); + #else /* USE_UNICODE_WCHAR_CACHE */ + arguments = PyUnicode_AsWideCharString(args[2], NULL); + #endif /* USE_UNICODE_WCHAR_CACHE */ + if (arguments == NULL) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[3]) { + if (!path_converter(args[3], &cwd)) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + show_cmd = _PyLong_AsInt(args[4]); + if (show_cmd == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_pos: + return_value = os_startfile_impl(module, &filepath, operation, arguments, &cwd, show_cmd); exit: /* Cleanup for filepath */ path_cleanup(&filepath); + /* Cleanup for operation */ + #if !USE_UNICODE_WCHAR_CACHE + PyMem_Free((void *)operation); + #endif /* USE_UNICODE_WCHAR_CACHE */ + /* Cleanup for arguments */ + #if !USE_UNICODE_WCHAR_CACHE + PyMem_Free((void *)arguments); + #endif /* USE_UNICODE_WCHAR_CACHE */ + /* Cleanup for cwd */ + path_cleanup(&cwd); return return_value; } @@ -7567,11 +7310,6 @@ os_device_encoding(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -7829,11 +7567,6 @@ os_setxattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject goto skip_optional_pos; } if (args[3]) { - if (PyFloat_Check(args[3])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } flags = _PyLong_AsInt(args[3]); if (flags == -1 && PyErr_Occurred()) { goto exit; @@ -8015,14 +7748,9 @@ os_urandom(PyObject *module, PyObject *arg) PyObject *return_value = NULL; Py_ssize_t size; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(arg); + PyObject *iobj = _PyNumber_Index(arg); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -8072,11 +7800,6 @@ os_memfd_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj if (!noptargs) { goto skip_optional_pos; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } flags = (unsigned int)PyLong_AsUnsignedLongMask(args[1]); if (flags == (unsigned int)-1 && PyErr_Occurred()) { goto exit; @@ -8093,6 +7816,134 @@ exit: #endif /* defined(HAVE_MEMFD_CREATE) */ +#if defined(HAVE_EVENTFD) + +PyDoc_STRVAR(os_eventfd__doc__, +"eventfd($module, /, initval, flags=EFD_CLOEXEC)\n" +"--\n" +"\n" +"Creates and returns an event notification file descriptor."); + +#define OS_EVENTFD_METHODDEF \ + {"eventfd", (PyCFunction)(void(*)(void))os_eventfd, METH_FASTCALL|METH_KEYWORDS, os_eventfd__doc__}, + +static PyObject * +os_eventfd_impl(PyObject *module, unsigned int initval, int flags); + +static PyObject * +os_eventfd(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"initval", "flags", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "eventfd", 0}; + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + unsigned int initval; + int flags = EFD_CLOEXEC; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!_PyLong_UnsignedInt_Converter(args[0], &initval)) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + flags = _PyLong_AsInt(args[1]); + if (flags == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional_pos: + return_value = os_eventfd_impl(module, initval, flags); + +exit: + return return_value; +} + +#endif /* defined(HAVE_EVENTFD) */ + +#if defined(HAVE_EVENTFD) + +PyDoc_STRVAR(os_eventfd_read__doc__, +"eventfd_read($module, /, fd)\n" +"--\n" +"\n" +"Read eventfd value"); + +#define OS_EVENTFD_READ_METHODDEF \ + {"eventfd_read", (PyCFunction)(void(*)(void))os_eventfd_read, METH_FASTCALL|METH_KEYWORDS, os_eventfd_read__doc__}, + +static PyObject * +os_eventfd_read_impl(PyObject *module, int fd); + +static PyObject * +os_eventfd_read(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"fd", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "eventfd_read", 0}; + PyObject *argsbuf[1]; + int fd; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + return_value = os_eventfd_read_impl(module, fd); + +exit: + return return_value; +} + +#endif /* defined(HAVE_EVENTFD) */ + +#if defined(HAVE_EVENTFD) + +PyDoc_STRVAR(os_eventfd_write__doc__, +"eventfd_write($module, /, fd, value)\n" +"--\n" +"\n" +"Write eventfd value."); + +#define OS_EVENTFD_WRITE_METHODDEF \ + {"eventfd_write", (PyCFunction)(void(*)(void))os_eventfd_write, METH_FASTCALL|METH_KEYWORDS, os_eventfd_write__doc__}, + +static PyObject * +os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value); + +static PyObject * +os_eventfd_write(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"fd", "value", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "eventfd_write", 0}; + PyObject *argsbuf[2]; + int fd; + unsigned long long value; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + if (!_PyLong_UnsignedLongLong_Converter(args[1], &value)) { + goto exit; + } + return_value = os_eventfd_write_impl(module, fd, value); + +exit: + return return_value; +} + +#endif /* defined(HAVE_EVENTFD) */ + #if (defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)) PyDoc_STRVAR(os_get_terminal_size__doc__, @@ -8131,11 +7982,6 @@ os_get_terminal_size(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 1) { goto skip_optional; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -8190,11 +8036,6 @@ os_get_inheritable(PyObject *module, PyObject *arg) int fd; int _return_value; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(arg); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -8231,20 +8072,10 @@ os_set_inheritable(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("set_inheritable", nargs, 2, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } inheritable = _PyLong_AsInt(args[1]); if (inheritable == -1 && PyErr_Occurred()) { goto exit; @@ -8348,11 +8179,6 @@ os_get_blocking(PyObject *module, PyObject *arg) int fd; int _return_value; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(arg); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -8396,20 +8222,10 @@ os_set_blocking(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("set_blocking", nargs, 2, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(args[0]); if (fd == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } blocking = _PyLong_AsInt(args[1]); if (blocking == -1 && PyErr_Occurred()) { goto exit; @@ -8708,14 +8524,9 @@ os_getrandom(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (!args) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } { Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(args[0]); + PyObject *iobj = _PyNumber_Index(args[0]); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); @@ -8728,11 +8539,6 @@ os_getrandom(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject if (!noptargs) { goto skip_optional_pos; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } flags = _PyLong_AsInt(args[1]); if (flags == -1 && PyErr_Occurred()) { goto exit; @@ -9258,6 +9064,10 @@ exit: #define OS_COPY_FILE_RANGE_METHODDEF #endif /* !defined(OS_COPY_FILE_RANGE_METHODDEF) */ +#ifndef OS_SPLICE_METHODDEF + #define OS_SPLICE_METHODDEF +#endif /* !defined(OS_SPLICE_METHODDEF) */ + #ifndef OS_MKFIFO_METHODDEF #define OS_MKFIFO_METHODDEF #endif /* !defined(OS_MKFIFO_METHODDEF) */ @@ -9406,6 +9216,18 @@ exit: #define OS_MEMFD_CREATE_METHODDEF #endif /* !defined(OS_MEMFD_CREATE_METHODDEF) */ +#ifndef OS_EVENTFD_METHODDEF + #define OS_EVENTFD_METHODDEF +#endif /* !defined(OS_EVENTFD_METHODDEF) */ + +#ifndef OS_EVENTFD_READ_METHODDEF + #define OS_EVENTFD_READ_METHODDEF +#endif /* !defined(OS_EVENTFD_READ_METHODDEF) */ + +#ifndef OS_EVENTFD_WRITE_METHODDEF + #define OS_EVENTFD_WRITE_METHODDEF +#endif /* !defined(OS_EVENTFD_WRITE_METHODDEF) */ + #ifndef OS_GET_TERMINAL_SIZE_METHODDEF #define OS_GET_TERMINAL_SIZE_METHODDEF #endif /* !defined(OS_GET_TERMINAL_SIZE_METHODDEF) */ @@ -9441,4 +9263,4 @@ exit: #ifndef OS_WAITSTATUS_TO_EXITCODE_METHODDEF #define OS_WAITSTATUS_TO_EXITCODE_METHODDEF #endif /* !defined(OS_WAITSTATUS_TO_EXITCODE_METHODDEF) */ -/*[clinic end generated code: output=c7c8796918b09139 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=65a85d7d3f2c487e input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/pyexpat.c.h b/contrib/tools/python3/src/Modules/clinic/pyexpat.c.h index ee5907ca7e..7c56d6a8b2 100644 --- a/contrib/tools/python3/src/Modules/clinic/pyexpat.c.h +++ b/contrib/tools/python3/src/Modules/clinic/pyexpat.c.h @@ -11,37 +11,26 @@ PyDoc_STRVAR(pyexpat_xmlparser_Parse__doc__, "`isfinal\' should be true at end of input."); #define PYEXPAT_XMLPARSER_PARSE_METHODDEF \ - {"Parse", (PyCFunction)(void(*)(void))pyexpat_xmlparser_Parse, METH_FASTCALL, pyexpat_xmlparser_Parse__doc__}, + {"Parse", (PyCFunction)(void(*)(void))pyexpat_xmlparser_Parse, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, pyexpat_xmlparser_Parse__doc__}, static PyObject * -pyexpat_xmlparser_Parse_impl(xmlparseobject *self, PyObject *data, - int isfinal); +pyexpat_xmlparser_Parse_impl(xmlparseobject *self, PyTypeObject *cls, + PyObject *data, int isfinal); static PyObject * -pyexpat_xmlparser_Parse(xmlparseobject *self, PyObject *const *args, Py_ssize_t nargs) +pyexpat_xmlparser_Parse(xmlparseobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + static const char * const _keywords[] = {"", "", NULL}; + static _PyArg_Parser _parser = {"O|i:Parse", _keywords, 0}; PyObject *data; int isfinal = 0; - if (!_PyArg_CheckPositional("Parse", nargs, 1, 2)) { + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &data, &isfinal)) { goto exit; } - data = args[0]; - if (nargs < 2) { - goto skip_optional; - } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } - isfinal = _PyLong_AsInt(args[1]); - if (isfinal == -1 && PyErr_Occurred()) { - goto exit; - } -skip_optional: - return_value = pyexpat_xmlparser_Parse_impl(self, data, isfinal); + return_value = pyexpat_xmlparser_Parse_impl(self, cls, data, isfinal); exit: return return_value; @@ -54,7 +43,29 @@ PyDoc_STRVAR(pyexpat_xmlparser_ParseFile__doc__, "Parse XML data from file-like object."); #define PYEXPAT_XMLPARSER_PARSEFILE_METHODDEF \ - {"ParseFile", (PyCFunction)pyexpat_xmlparser_ParseFile, METH_O, pyexpat_xmlparser_ParseFile__doc__}, + {"ParseFile", (PyCFunction)(void(*)(void))pyexpat_xmlparser_ParseFile, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, pyexpat_xmlparser_ParseFile__doc__}, + +static PyObject * +pyexpat_xmlparser_ParseFile_impl(xmlparseobject *self, PyTypeObject *cls, + PyObject *file); + +static PyObject * +pyexpat_xmlparser_ParseFile(xmlparseobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = {"O:ParseFile", _keywords, 0}; + PyObject *file; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &file)) { + goto exit; + } + return_value = pyexpat_xmlparser_ParseFile_impl(self, cls, file); + +exit: + return return_value; +} PyDoc_STRVAR(pyexpat_xmlparser_SetBase__doc__, "SetBase($self, base, /)\n" @@ -140,59 +151,28 @@ PyDoc_STRVAR(pyexpat_xmlparser_ExternalEntityParserCreate__doc__, "Create a parser for parsing an external entity based on the information passed to the ExternalEntityRefHandler."); #define PYEXPAT_XMLPARSER_EXTERNALENTITYPARSERCREATE_METHODDEF \ - {"ExternalEntityParserCreate", (PyCFunction)(void(*)(void))pyexpat_xmlparser_ExternalEntityParserCreate, METH_FASTCALL, pyexpat_xmlparser_ExternalEntityParserCreate__doc__}, + {"ExternalEntityParserCreate", (PyCFunction)(void(*)(void))pyexpat_xmlparser_ExternalEntityParserCreate, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, pyexpat_xmlparser_ExternalEntityParserCreate__doc__}, static PyObject * pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self, + PyTypeObject *cls, const char *context, const char *encoding); static PyObject * -pyexpat_xmlparser_ExternalEntityParserCreate(xmlparseobject *self, PyObject *const *args, Py_ssize_t nargs) +pyexpat_xmlparser_ExternalEntityParserCreate(xmlparseobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + static const char * const _keywords[] = {"", "", NULL}; + static _PyArg_Parser _parser = {"z|s:ExternalEntityParserCreate", _keywords, 0}; const char *context; const char *encoding = NULL; - if (!_PyArg_CheckPositional("ExternalEntityParserCreate", nargs, 1, 2)) { + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &context, &encoding)) { goto exit; } - if (args[0] == Py_None) { - context = NULL; - } - else if (PyUnicode_Check(args[0])) { - Py_ssize_t context_length; - context = PyUnicode_AsUTF8AndSize(args[0], &context_length); - if (context == NULL) { - goto exit; - } - if (strlen(context) != (size_t)context_length) { - PyErr_SetString(PyExc_ValueError, "embedded null character"); - goto exit; - } - } - else { - _PyArg_BadArgument("ExternalEntityParserCreate", "argument 1", "str or None", args[0]); - goto exit; - } - if (nargs < 2) { - goto skip_optional; - } - if (!PyUnicode_Check(args[1])) { - _PyArg_BadArgument("ExternalEntityParserCreate", "argument 2", "str", args[1]); - goto exit; - } - Py_ssize_t encoding_length; - encoding = PyUnicode_AsUTF8AndSize(args[1], &encoding_length); - if (encoding == NULL) { - goto exit; - } - if (strlen(encoding) != (size_t)encoding_length) { - PyErr_SetString(PyExc_ValueError, "embedded null character"); - goto exit; - } -skip_optional: - return_value = pyexpat_xmlparser_ExternalEntityParserCreate_impl(self, context, encoding); + return_value = pyexpat_xmlparser_ExternalEntityParserCreate_impl(self, cls, context, encoding); exit: return return_value; @@ -221,11 +201,6 @@ pyexpat_xmlparser_SetParamEntityParsing(xmlparseobject *self, PyObject *arg) PyObject *return_value = NULL; int flag; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } flag = _PyLong_AsInt(arg); if (flag == -1 && PyErr_Occurred()) { goto exit; @@ -249,29 +224,25 @@ PyDoc_STRVAR(pyexpat_xmlparser_UseForeignDTD__doc__, "information to the parser. \'flag\' defaults to True if not provided."); #define PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF \ - {"UseForeignDTD", (PyCFunction)(void(*)(void))pyexpat_xmlparser_UseForeignDTD, METH_FASTCALL, pyexpat_xmlparser_UseForeignDTD__doc__}, + {"UseForeignDTD", (PyCFunction)(void(*)(void))pyexpat_xmlparser_UseForeignDTD, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, pyexpat_xmlparser_UseForeignDTD__doc__}, static PyObject * -pyexpat_xmlparser_UseForeignDTD_impl(xmlparseobject *self, int flag); +pyexpat_xmlparser_UseForeignDTD_impl(xmlparseobject *self, PyTypeObject *cls, + int flag); static PyObject * -pyexpat_xmlparser_UseForeignDTD(xmlparseobject *self, PyObject *const *args, Py_ssize_t nargs) +pyexpat_xmlparser_UseForeignDTD(xmlparseobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = {"|p:UseForeignDTD", _keywords, 0}; int flag = 1; - if (!_PyArg_CheckPositional("UseForeignDTD", nargs, 0, 1)) { + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &flag)) { goto exit; } - if (nargs < 1) { - goto skip_optional; - } - flag = PyObject_IsTrue(args[0]); - if (flag < 0) { - goto exit; - } -skip_optional: - return_value = pyexpat_xmlparser_UseForeignDTD_impl(self, flag); + return_value = pyexpat_xmlparser_UseForeignDTD_impl(self, cls, flag); exit: return return_value; @@ -384,11 +355,6 @@ pyexpat_ErrorString(PyObject *module, PyObject *arg) PyObject *return_value = NULL; long code; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } code = PyLong_AsLong(arg); if (code == -1 && PyErr_Occurred()) { goto exit; @@ -402,4 +368,4 @@ exit: #ifndef PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF #define PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF #endif /* !defined(PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF) */ -/*[clinic end generated code: output=68ce25024280af41 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=612b9d6a17a679a7 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/readline.c.h b/contrib/tools/python3/src/Modules/clinic/readline.c.h new file mode 100644 index 0000000000..d1ee8089f7 --- /dev/null +++ b/contrib/tools/python3/src/Modules/clinic/readline.c.h @@ -0,0 +1,688 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(readline_parse_and_bind__doc__, +"parse_and_bind($module, string, /)\n" +"--\n" +"\n" +"Execute the init line provided in the string argument."); + +#define READLINE_PARSE_AND_BIND_METHODDEF \ + {"parse_and_bind", (PyCFunction)readline_parse_and_bind, METH_O, readline_parse_and_bind__doc__}, + +PyDoc_STRVAR(readline_read_init_file__doc__, +"read_init_file($module, filename=None, /)\n" +"--\n" +"\n" +"Execute a readline initialization file.\n" +"\n" +"The default filename is the last filename used."); + +#define READLINE_READ_INIT_FILE_METHODDEF \ + {"read_init_file", (PyCFunction)(void(*)(void))readline_read_init_file, METH_FASTCALL, readline_read_init_file__doc__}, + +static PyObject * +readline_read_init_file_impl(PyObject *module, PyObject *filename_obj); + +static PyObject * +readline_read_init_file(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *filename_obj = Py_None; + + if (!_PyArg_CheckPositional("read_init_file", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + filename_obj = args[0]; +skip_optional: + return_value = readline_read_init_file_impl(module, filename_obj); + +exit: + return return_value; +} + +PyDoc_STRVAR(readline_read_history_file__doc__, +"read_history_file($module, filename=None, /)\n" +"--\n" +"\n" +"Load a readline history file.\n" +"\n" +"The default filename is ~/.history."); + +#define READLINE_READ_HISTORY_FILE_METHODDEF \ + {"read_history_file", (PyCFunction)(void(*)(void))readline_read_history_file, METH_FASTCALL, readline_read_history_file__doc__}, + +static PyObject * +readline_read_history_file_impl(PyObject *module, PyObject *filename_obj); + +static PyObject * +readline_read_history_file(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *filename_obj = Py_None; + + if (!_PyArg_CheckPositional("read_history_file", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + filename_obj = args[0]; +skip_optional: + return_value = readline_read_history_file_impl(module, filename_obj); + +exit: + return return_value; +} + +PyDoc_STRVAR(readline_write_history_file__doc__, +"write_history_file($module, filename=None, /)\n" +"--\n" +"\n" +"Save a readline history file.\n" +"\n" +"The default filename is ~/.history."); + +#define READLINE_WRITE_HISTORY_FILE_METHODDEF \ + {"write_history_file", (PyCFunction)(void(*)(void))readline_write_history_file, METH_FASTCALL, readline_write_history_file__doc__}, + +static PyObject * +readline_write_history_file_impl(PyObject *module, PyObject *filename_obj); + +static PyObject * +readline_write_history_file(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *filename_obj = Py_None; + + if (!_PyArg_CheckPositional("write_history_file", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + filename_obj = args[0]; +skip_optional: + return_value = readline_write_history_file_impl(module, filename_obj); + +exit: + return return_value; +} + +#if defined(HAVE_RL_APPEND_HISTORY) + +PyDoc_STRVAR(readline_append_history_file__doc__, +"append_history_file($module, nelements, filename=None, /)\n" +"--\n" +"\n" +"Append the last nelements items of the history list to file.\n" +"\n" +"The default filename is ~/.history."); + +#define READLINE_APPEND_HISTORY_FILE_METHODDEF \ + {"append_history_file", (PyCFunction)(void(*)(void))readline_append_history_file, METH_FASTCALL, readline_append_history_file__doc__}, + +static PyObject * +readline_append_history_file_impl(PyObject *module, int nelements, + PyObject *filename_obj); + +static PyObject * +readline_append_history_file(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int nelements; + PyObject *filename_obj = Py_None; + + if (!_PyArg_CheckPositional("append_history_file", nargs, 1, 2)) { + goto exit; + } + nelements = _PyLong_AsInt(args[0]); + if (nelements == -1 && PyErr_Occurred()) { + goto exit; + } + if (nargs < 2) { + goto skip_optional; + } + filename_obj = args[1]; +skip_optional: + return_value = readline_append_history_file_impl(module, nelements, filename_obj); + +exit: + return return_value; +} + +#endif /* defined(HAVE_RL_APPEND_HISTORY) */ + +PyDoc_STRVAR(readline_set_history_length__doc__, +"set_history_length($module, length, /)\n" +"--\n" +"\n" +"Set the maximal number of lines which will be written to the history file.\n" +"\n" +"A negative length is used to inhibit history truncation."); + +#define READLINE_SET_HISTORY_LENGTH_METHODDEF \ + {"set_history_length", (PyCFunction)readline_set_history_length, METH_O, readline_set_history_length__doc__}, + +static PyObject * +readline_set_history_length_impl(PyObject *module, int length); + +static PyObject * +readline_set_history_length(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int length; + + length = _PyLong_AsInt(arg); + if (length == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = readline_set_history_length_impl(module, length); + +exit: + return return_value; +} + +PyDoc_STRVAR(readline_get_history_length__doc__, +"get_history_length($module, /)\n" +"--\n" +"\n" +"Return the maximum number of lines that will be written to the history file."); + +#define READLINE_GET_HISTORY_LENGTH_METHODDEF \ + {"get_history_length", (PyCFunction)readline_get_history_length, METH_NOARGS, readline_get_history_length__doc__}, + +static PyObject * +readline_get_history_length_impl(PyObject *module); + +static PyObject * +readline_get_history_length(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return readline_get_history_length_impl(module); +} + +PyDoc_STRVAR(readline_set_completion_display_matches_hook__doc__, +"set_completion_display_matches_hook($module, function=None, /)\n" +"--\n" +"\n" +"Set or remove the completion display function.\n" +"\n" +"The function is called as\n" +" function(substitution, [matches], longest_match_length)\n" +"once each time matches need to be displayed."); + +#define READLINE_SET_COMPLETION_DISPLAY_MATCHES_HOOK_METHODDEF \ + {"set_completion_display_matches_hook", (PyCFunction)(void(*)(void))readline_set_completion_display_matches_hook, METH_FASTCALL, readline_set_completion_display_matches_hook__doc__}, + +static PyObject * +readline_set_completion_display_matches_hook_impl(PyObject *module, + PyObject *function); + +static PyObject * +readline_set_completion_display_matches_hook(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *function = Py_None; + + if (!_PyArg_CheckPositional("set_completion_display_matches_hook", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + function = args[0]; +skip_optional: + return_value = readline_set_completion_display_matches_hook_impl(module, function); + +exit: + return return_value; +} + +PyDoc_STRVAR(readline_set_startup_hook__doc__, +"set_startup_hook($module, function=None, /)\n" +"--\n" +"\n" +"Set or remove the function invoked by the rl_startup_hook callback.\n" +"\n" +"The function is called with no arguments just\n" +"before readline prints the first prompt."); + +#define READLINE_SET_STARTUP_HOOK_METHODDEF \ + {"set_startup_hook", (PyCFunction)(void(*)(void))readline_set_startup_hook, METH_FASTCALL, readline_set_startup_hook__doc__}, + +static PyObject * +readline_set_startup_hook_impl(PyObject *module, PyObject *function); + +static PyObject * +readline_set_startup_hook(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *function = Py_None; + + if (!_PyArg_CheckPositional("set_startup_hook", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + function = args[0]; +skip_optional: + return_value = readline_set_startup_hook_impl(module, function); + +exit: + return return_value; +} + +#if defined(HAVE_RL_PRE_INPUT_HOOK) + +PyDoc_STRVAR(readline_set_pre_input_hook__doc__, +"set_pre_input_hook($module, function=None, /)\n" +"--\n" +"\n" +"Set or remove the function invoked by the rl_pre_input_hook callback.\n" +"\n" +"The function is called with no arguments after the first prompt\n" +"has been printed and just before readline starts reading input\n" +"characters."); + +#define READLINE_SET_PRE_INPUT_HOOK_METHODDEF \ + {"set_pre_input_hook", (PyCFunction)(void(*)(void))readline_set_pre_input_hook, METH_FASTCALL, readline_set_pre_input_hook__doc__}, + +static PyObject * +readline_set_pre_input_hook_impl(PyObject *module, PyObject *function); + +static PyObject * +readline_set_pre_input_hook(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *function = Py_None; + + if (!_PyArg_CheckPositional("set_pre_input_hook", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + function = args[0]; +skip_optional: + return_value = readline_set_pre_input_hook_impl(module, function); + +exit: + return return_value; +} + +#endif /* defined(HAVE_RL_PRE_INPUT_HOOK) */ + +PyDoc_STRVAR(readline_get_completion_type__doc__, +"get_completion_type($module, /)\n" +"--\n" +"\n" +"Get the type of completion being attempted."); + +#define READLINE_GET_COMPLETION_TYPE_METHODDEF \ + {"get_completion_type", (PyCFunction)readline_get_completion_type, METH_NOARGS, readline_get_completion_type__doc__}, + +static PyObject * +readline_get_completion_type_impl(PyObject *module); + +static PyObject * +readline_get_completion_type(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return readline_get_completion_type_impl(module); +} + +PyDoc_STRVAR(readline_get_begidx__doc__, +"get_begidx($module, /)\n" +"--\n" +"\n" +"Get the beginning index of the completion scope."); + +#define READLINE_GET_BEGIDX_METHODDEF \ + {"get_begidx", (PyCFunction)readline_get_begidx, METH_NOARGS, readline_get_begidx__doc__}, + +static PyObject * +readline_get_begidx_impl(PyObject *module); + +static PyObject * +readline_get_begidx(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return readline_get_begidx_impl(module); +} + +PyDoc_STRVAR(readline_get_endidx__doc__, +"get_endidx($module, /)\n" +"--\n" +"\n" +"Get the ending index of the completion scope."); + +#define READLINE_GET_ENDIDX_METHODDEF \ + {"get_endidx", (PyCFunction)readline_get_endidx, METH_NOARGS, readline_get_endidx__doc__}, + +static PyObject * +readline_get_endidx_impl(PyObject *module); + +static PyObject * +readline_get_endidx(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return readline_get_endidx_impl(module); +} + +PyDoc_STRVAR(readline_set_completer_delims__doc__, +"set_completer_delims($module, string, /)\n" +"--\n" +"\n" +"Set the word delimiters for completion."); + +#define READLINE_SET_COMPLETER_DELIMS_METHODDEF \ + {"set_completer_delims", (PyCFunction)readline_set_completer_delims, METH_O, readline_set_completer_delims__doc__}, + +PyDoc_STRVAR(readline_remove_history_item__doc__, +"remove_history_item($module, pos, /)\n" +"--\n" +"\n" +"Remove history item given by its zero-based position."); + +#define READLINE_REMOVE_HISTORY_ITEM_METHODDEF \ + {"remove_history_item", (PyCFunction)readline_remove_history_item, METH_O, readline_remove_history_item__doc__}, + +static PyObject * +readline_remove_history_item_impl(PyObject *module, int entry_number); + +static PyObject * +readline_remove_history_item(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int entry_number; + + entry_number = _PyLong_AsInt(arg); + if (entry_number == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = readline_remove_history_item_impl(module, entry_number); + +exit: + return return_value; +} + +PyDoc_STRVAR(readline_replace_history_item__doc__, +"replace_history_item($module, pos, line, /)\n" +"--\n" +"\n" +"Replaces history item given by its position with contents of line.\n" +"\n" +"pos is zero-based."); + +#define READLINE_REPLACE_HISTORY_ITEM_METHODDEF \ + {"replace_history_item", (PyCFunction)(void(*)(void))readline_replace_history_item, METH_FASTCALL, readline_replace_history_item__doc__}, + +static PyObject * +readline_replace_history_item_impl(PyObject *module, int entry_number, + PyObject *line); + +static PyObject * +readline_replace_history_item(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int entry_number; + PyObject *line; + + if (!_PyArg_CheckPositional("replace_history_item", nargs, 2, 2)) { + goto exit; + } + entry_number = _PyLong_AsInt(args[0]); + if (entry_number == -1 && PyErr_Occurred()) { + goto exit; + } + if (!PyUnicode_Check(args[1])) { + _PyArg_BadArgument("replace_history_item", "argument 2", "str", args[1]); + goto exit; + } + if (PyUnicode_READY(args[1]) == -1) { + goto exit; + } + line = args[1]; + return_value = readline_replace_history_item_impl(module, entry_number, line); + +exit: + return return_value; +} + +PyDoc_STRVAR(readline_add_history__doc__, +"add_history($module, string, /)\n" +"--\n" +"\n" +"Add an item to the history buffer."); + +#define READLINE_ADD_HISTORY_METHODDEF \ + {"add_history", (PyCFunction)readline_add_history, METH_O, readline_add_history__doc__}, + +PyDoc_STRVAR(readline_set_auto_history__doc__, +"set_auto_history($module, enabled, /)\n" +"--\n" +"\n" +"Enables or disables automatic history."); + +#define READLINE_SET_AUTO_HISTORY_METHODDEF \ + {"set_auto_history", (PyCFunction)readline_set_auto_history, METH_O, readline_set_auto_history__doc__}, + +static PyObject * +readline_set_auto_history_impl(PyObject *module, + int _should_auto_add_history); + +static PyObject * +readline_set_auto_history(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int _should_auto_add_history; + + _should_auto_add_history = PyObject_IsTrue(arg); + if (_should_auto_add_history < 0) { + goto exit; + } + return_value = readline_set_auto_history_impl(module, _should_auto_add_history); + +exit: + return return_value; +} + +PyDoc_STRVAR(readline_get_completer_delims__doc__, +"get_completer_delims($module, /)\n" +"--\n" +"\n" +"Get the word delimiters for completion."); + +#define READLINE_GET_COMPLETER_DELIMS_METHODDEF \ + {"get_completer_delims", (PyCFunction)readline_get_completer_delims, METH_NOARGS, readline_get_completer_delims__doc__}, + +static PyObject * +readline_get_completer_delims_impl(PyObject *module); + +static PyObject * +readline_get_completer_delims(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return readline_get_completer_delims_impl(module); +} + +PyDoc_STRVAR(readline_set_completer__doc__, +"set_completer($module, function=None, /)\n" +"--\n" +"\n" +"Set or remove the completer function.\n" +"\n" +"The function is called as function(text, state),\n" +"for state in 0, 1, 2, ..., until it returns a non-string.\n" +"It should return the next possible completion starting with \'text\'."); + +#define READLINE_SET_COMPLETER_METHODDEF \ + {"set_completer", (PyCFunction)(void(*)(void))readline_set_completer, METH_FASTCALL, readline_set_completer__doc__}, + +static PyObject * +readline_set_completer_impl(PyObject *module, PyObject *function); + +static PyObject * +readline_set_completer(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *function = Py_None; + + if (!_PyArg_CheckPositional("set_completer", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + function = args[0]; +skip_optional: + return_value = readline_set_completer_impl(module, function); + +exit: + return return_value; +} + +PyDoc_STRVAR(readline_get_completer__doc__, +"get_completer($module, /)\n" +"--\n" +"\n" +"Get the current completer function."); + +#define READLINE_GET_COMPLETER_METHODDEF \ + {"get_completer", (PyCFunction)readline_get_completer, METH_NOARGS, readline_get_completer__doc__}, + +static PyObject * +readline_get_completer_impl(PyObject *module); + +static PyObject * +readline_get_completer(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return readline_get_completer_impl(module); +} + +PyDoc_STRVAR(readline_get_history_item__doc__, +"get_history_item($module, index, /)\n" +"--\n" +"\n" +"Return the current contents of history item at one-based index."); + +#define READLINE_GET_HISTORY_ITEM_METHODDEF \ + {"get_history_item", (PyCFunction)readline_get_history_item, METH_O, readline_get_history_item__doc__}, + +static PyObject * +readline_get_history_item_impl(PyObject *module, int idx); + +static PyObject * +readline_get_history_item(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int idx; + + idx = _PyLong_AsInt(arg); + if (idx == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = readline_get_history_item_impl(module, idx); + +exit: + return return_value; +} + +PyDoc_STRVAR(readline_get_current_history_length__doc__, +"get_current_history_length($module, /)\n" +"--\n" +"\n" +"Return the current (not the maximum) length of history."); + +#define READLINE_GET_CURRENT_HISTORY_LENGTH_METHODDEF \ + {"get_current_history_length", (PyCFunction)readline_get_current_history_length, METH_NOARGS, readline_get_current_history_length__doc__}, + +static PyObject * +readline_get_current_history_length_impl(PyObject *module); + +static PyObject * +readline_get_current_history_length(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return readline_get_current_history_length_impl(module); +} + +PyDoc_STRVAR(readline_get_line_buffer__doc__, +"get_line_buffer($module, /)\n" +"--\n" +"\n" +"Return the current contents of the line buffer."); + +#define READLINE_GET_LINE_BUFFER_METHODDEF \ + {"get_line_buffer", (PyCFunction)readline_get_line_buffer, METH_NOARGS, readline_get_line_buffer__doc__}, + +static PyObject * +readline_get_line_buffer_impl(PyObject *module); + +static PyObject * +readline_get_line_buffer(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return readline_get_line_buffer_impl(module); +} + +#if defined(HAVE_RL_COMPLETION_APPEND_CHARACTER) + +PyDoc_STRVAR(readline_clear_history__doc__, +"clear_history($module, /)\n" +"--\n" +"\n" +"Clear the current readline history."); + +#define READLINE_CLEAR_HISTORY_METHODDEF \ + {"clear_history", (PyCFunction)readline_clear_history, METH_NOARGS, readline_clear_history__doc__}, + +static PyObject * +readline_clear_history_impl(PyObject *module); + +static PyObject * +readline_clear_history(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return readline_clear_history_impl(module); +} + +#endif /* defined(HAVE_RL_COMPLETION_APPEND_CHARACTER) */ + +PyDoc_STRVAR(readline_insert_text__doc__, +"insert_text($module, string, /)\n" +"--\n" +"\n" +"Insert text into the line buffer at the cursor position."); + +#define READLINE_INSERT_TEXT_METHODDEF \ + {"insert_text", (PyCFunction)readline_insert_text, METH_O, readline_insert_text__doc__}, + +PyDoc_STRVAR(readline_redisplay__doc__, +"redisplay($module, /)\n" +"--\n" +"\n" +"Change what\'s displayed on the screen to reflect contents of the line buffer."); + +#define READLINE_REDISPLAY_METHODDEF \ + {"redisplay", (PyCFunction)readline_redisplay, METH_NOARGS, readline_redisplay__doc__}, + +static PyObject * +readline_redisplay_impl(PyObject *module); + +static PyObject * +readline_redisplay(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return readline_redisplay_impl(module); +} + +#ifndef READLINE_APPEND_HISTORY_FILE_METHODDEF + #define READLINE_APPEND_HISTORY_FILE_METHODDEF +#endif /* !defined(READLINE_APPEND_HISTORY_FILE_METHODDEF) */ + +#ifndef READLINE_SET_PRE_INPUT_HOOK_METHODDEF + #define READLINE_SET_PRE_INPUT_HOOK_METHODDEF +#endif /* !defined(READLINE_SET_PRE_INPUT_HOOK_METHODDEF) */ + +#ifndef READLINE_CLEAR_HISTORY_METHODDEF + #define READLINE_CLEAR_HISTORY_METHODDEF +#endif /* !defined(READLINE_CLEAR_HISTORY_METHODDEF) */ +/*[clinic end generated code: output=f7d390113b27989f input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/resource.c.h b/contrib/tools/python3/src/Modules/clinic/resource.c.h index 80efb714bb..32c092ad7a 100644 --- a/contrib/tools/python3/src/Modules/clinic/resource.c.h +++ b/contrib/tools/python3/src/Modules/clinic/resource.c.h @@ -19,11 +19,6 @@ resource_getrusage(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int who; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } who = _PyLong_AsInt(arg); if (who == -1 && PyErr_Occurred()) { goto exit; @@ -51,11 +46,6 @@ resource_getrlimit(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int resource; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } resource = _PyLong_AsInt(arg); if (resource == -1 && PyErr_Occurred()) { goto exit; @@ -87,11 +77,6 @@ resource_setrlimit(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("setrlimit", nargs, 2, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } resource = _PyLong_AsInt(args[0]); if (resource == -1 && PyErr_Occurred()) { goto exit; @@ -178,4 +163,4 @@ exit: #ifndef RESOURCE_PRLIMIT_METHODDEF #define RESOURCE_PRLIMIT_METHODDEF #endif /* !defined(RESOURCE_PRLIMIT_METHODDEF) */ -/*[clinic end generated code: output=ef3034f291156a34 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ad190fb33d647d1e input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/selectmodule.c.h b/contrib/tools/python3/src/Modules/clinic/selectmodule.c.h index 7791af8f93..be752e9816 100644 --- a/contrib/tools/python3/src/Modules/clinic/selectmodule.c.h +++ b/contrib/tools/python3/src/Modules/clinic/selectmodule.c.h @@ -92,7 +92,7 @@ select_poll_register(pollObject *self, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("register", nargs, 1, 2)) { goto exit; } - if (!fildes_converter(args[0], &fd)) { + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { goto exit; } if (nargs < 2) { @@ -140,7 +140,7 @@ select_poll_modify(pollObject *self, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("modify", nargs, 2, 2)) { goto exit; } - if (!fildes_converter(args[0], &fd)) { + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { goto exit; } if (!_PyLong_UnsignedShort_Converter(args[1], &eventmask)) { @@ -174,7 +174,7 @@ select_poll_unregister(pollObject *self, PyObject *arg) PyObject *return_value = NULL; int fd; - if (!fildes_converter(arg, &fd)) { + if (!_PyLong_FileDescriptor_Converter(arg, &fd)) { goto exit; } return_value = select_poll_unregister_impl(self, fd); @@ -260,7 +260,7 @@ select_devpoll_register(devpollObject *self, PyObject *const *args, Py_ssize_t n if (!_PyArg_CheckPositional("register", nargs, 1, 2)) { goto exit; } - if (!fildes_converter(args[0], &fd)) { + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { goto exit; } if (nargs < 2) { @@ -310,7 +310,7 @@ select_devpoll_modify(devpollObject *self, PyObject *const *args, Py_ssize_t nar if (!_PyArg_CheckPositional("modify", nargs, 1, 2)) { goto exit; } - if (!fildes_converter(args[0], &fd)) { + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { goto exit; } if (nargs < 2) { @@ -348,7 +348,7 @@ select_devpoll_unregister(devpollObject *self, PyObject *arg) PyObject *return_value = NULL; int fd; - if (!fildes_converter(arg, &fd)) { + if (!_PyLong_FileDescriptor_Converter(arg, &fd)) { goto exit; } return_value = select_devpoll_unregister_impl(self, fd); @@ -539,11 +539,6 @@ select_epoll(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto skip_optional_pos; } if (fastargs[0]) { - if (PyFloat_Check(fastargs[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } sizehint = _PyLong_AsInt(fastargs[0]); if (sizehint == -1 && PyErr_Occurred()) { goto exit; @@ -552,11 +547,6 @@ select_epoll(PyTypeObject *type, PyObject *args, PyObject *kwargs) goto skip_optional_pos; } } - if (PyFloat_Check(fastargs[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } flags = _PyLong_AsInt(fastargs[1]); if (flags == -1 && PyErr_Occurred()) { goto exit; @@ -636,11 +626,6 @@ select_epoll_fromfd(PyTypeObject *type, PyObject *arg) PyObject *return_value = NULL; int fd; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(arg); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -691,17 +676,12 @@ select_epoll_register(pyEpoll_Object *self, PyObject *const *args, Py_ssize_t na if (!args) { goto exit; } - if (!fildes_converter(args[0], &fd)) { + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { goto exit; } if (!noptargs) { goto skip_optional_pos; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } eventmask = (unsigned int)PyLong_AsUnsignedLongMask(args[1]); if (eventmask == (unsigned int)-1 && PyErr_Occurred()) { goto exit; @@ -749,12 +729,7 @@ select_epoll_modify(pyEpoll_Object *self, PyObject *const *args, Py_ssize_t narg if (!args) { goto exit; } - if (!fildes_converter(args[0], &fd)) { - goto exit; - } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { goto exit; } eventmask = (unsigned int)PyLong_AsUnsignedLongMask(args[1]); @@ -799,7 +774,7 @@ select_epoll_unregister(pyEpoll_Object *self, PyObject *const *args, Py_ssize_t if (!args) { goto exit; } - if (!fildes_converter(args[0], &fd)) { + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { goto exit; } return_value = select_epoll_unregister_impl(self, fd); @@ -858,11 +833,6 @@ select_epoll_poll(pyEpoll_Object *self, PyObject *const *args, Py_ssize_t nargs, goto skip_optional_pos; } } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } maxevents = _PyLong_AsInt(args[1]); if (maxevents == -1 && PyErr_Occurred()) { goto exit; @@ -971,11 +941,11 @@ select_kqueue(PyTypeObject *type, PyObject *args, PyObject *kwargs) { PyObject *return_value = NULL; - if ((type == _selectstate_global->kqueue_queue_Type) && + if ((type == _selectstate_by_type(type)->kqueue_queue_Type) && !_PyArg_NoPositional("kqueue", args)) { goto exit; } - if ((type == _selectstate_global->kqueue_queue_Type) && + if ((type == _selectstate_by_type(type)->kqueue_queue_Type) && !_PyArg_NoKeywords("kqueue", kwargs)) { goto exit; } @@ -1053,11 +1023,6 @@ select_kqueue_fromfd(PyTypeObject *type, PyObject *arg) PyObject *return_value = NULL; int fd; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } fd = _PyLong_AsInt(arg); if (fd == -1 && PyErr_Occurred()) { goto exit; @@ -1106,11 +1071,6 @@ select_kqueue_control(kqueue_queue_Object *self, PyObject *const *args, Py_ssize goto exit; } changelist = args[0]; - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } maxevents = _PyLong_AsInt(args[1]); if (maxevents == -1 && PyErr_Occurred()) { goto exit; @@ -1227,4 +1187,4 @@ exit: #ifndef SELECT_KQUEUE_CONTROL_METHODDEF #define SELECT_KQUEUE_CONTROL_METHODDEF #endif /* !defined(SELECT_KQUEUE_CONTROL_METHODDEF) */ -/*[clinic end generated code: output=d78e30f231a926d6 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a8fc031269d28454 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/sha1module.c.h b/contrib/tools/python3/src/Modules/clinic/sha1module.c.h index fc37b1ab88..3a3ab58c12 100644 --- a/contrib/tools/python3/src/Modules/clinic/sha1module.c.h +++ b/contrib/tools/python3/src/Modules/clinic/sha1module.c.h @@ -9,15 +9,26 @@ PyDoc_STRVAR(SHA1Type_copy__doc__, "Return a copy of the hash object."); #define SHA1TYPE_COPY_METHODDEF \ - {"copy", (PyCFunction)SHA1Type_copy, METH_NOARGS, SHA1Type_copy__doc__}, + {"copy", (PyCFunction)(void(*)(void))SHA1Type_copy, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, SHA1Type_copy__doc__}, static PyObject * -SHA1Type_copy_impl(SHA1object *self); +SHA1Type_copy_impl(SHA1object *self, PyTypeObject *cls); static PyObject * -SHA1Type_copy(SHA1object *self, PyObject *Py_UNUSED(ignored)) +SHA1Type_copy(SHA1object *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return SHA1Type_copy_impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = {":copy", _keywords, 0}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser + )) { + goto exit; + } + return_value = SHA1Type_copy_impl(self, cls); + +exit: + return return_value; } PyDoc_STRVAR(SHA1Type_digest__doc__, @@ -115,4 +126,4 @@ skip_optional_kwonly: exit: return return_value; } -/*[clinic end generated code: output=3ddd637ae17e14b3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=abf1ab2545cea5a2 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/sha256module.c.h b/contrib/tools/python3/src/Modules/clinic/sha256module.c.h index 2a788ea984..89205c4f14 100644 --- a/contrib/tools/python3/src/Modules/clinic/sha256module.c.h +++ b/contrib/tools/python3/src/Modules/clinic/sha256module.c.h @@ -9,15 +9,26 @@ PyDoc_STRVAR(SHA256Type_copy__doc__, "Return a copy of the hash object."); #define SHA256TYPE_COPY_METHODDEF \ - {"copy", (PyCFunction)SHA256Type_copy, METH_NOARGS, SHA256Type_copy__doc__}, + {"copy", (PyCFunction)(void(*)(void))SHA256Type_copy, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, SHA256Type_copy__doc__}, static PyObject * -SHA256Type_copy_impl(SHAobject *self); +SHA256Type_copy_impl(SHAobject *self, PyTypeObject *cls); static PyObject * -SHA256Type_copy(SHAobject *self, PyObject *Py_UNUSED(ignored)) +SHA256Type_copy(SHAobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return SHA256Type_copy_impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = {":copy", _keywords, 0}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser + )) { + goto exit; + } + return_value = SHA256Type_copy_impl(self, cls); + +exit: + return return_value; } PyDoc_STRVAR(SHA256Type_digest__doc__, @@ -166,4 +177,4 @@ skip_optional_kwonly: exit: return return_value; } -/*[clinic end generated code: output=c8cca8adbe72ec9a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b7283f75c9d08f30 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/sha512module.c.h b/contrib/tools/python3/src/Modules/clinic/sha512module.c.h index b8185b62bb..f1192d74f9 100644 --- a/contrib/tools/python3/src/Modules/clinic/sha512module.c.h +++ b/contrib/tools/python3/src/Modules/clinic/sha512module.c.h @@ -9,15 +9,26 @@ PyDoc_STRVAR(SHA512Type_copy__doc__, "Return a copy of the hash object."); #define SHA512TYPE_COPY_METHODDEF \ - {"copy", (PyCFunction)SHA512Type_copy, METH_NOARGS, SHA512Type_copy__doc__}, + {"copy", (PyCFunction)(void(*)(void))SHA512Type_copy, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, SHA512Type_copy__doc__}, static PyObject * -SHA512Type_copy_impl(SHAobject *self); +SHA512Type_copy_impl(SHAobject *self, PyTypeObject *cls); static PyObject * -SHA512Type_copy(SHAobject *self, PyObject *Py_UNUSED(ignored)) +SHA512Type_copy(SHAobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return SHA512Type_copy_impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = {":copy", _keywords, 0}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser + )) { + goto exit; + } + return_value = SHA512Type_copy_impl(self, cls); + +exit: + return return_value; } PyDoc_STRVAR(SHA512Type_digest__doc__, @@ -166,4 +177,4 @@ skip_optional_kwonly: exit: return return_value; } -/*[clinic end generated code: output=bbfa72d8703c82b5 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9ff9f11937fabf35 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/signalmodule.c.h b/contrib/tools/python3/src/Modules/clinic/signalmodule.c.h index 0fb25d5640..4c27314a80 100644 --- a/contrib/tools/python3/src/Modules/clinic/signalmodule.c.h +++ b/contrib/tools/python3/src/Modules/clinic/signalmodule.c.h @@ -2,6 +2,42 @@ preserve [clinic start generated code]*/ +PyDoc_STRVAR(signal_default_int_handler__doc__, +"default_int_handler($module, signalnum, frame, /)\n" +"--\n" +"\n" +"The default handler for SIGINT installed by Python.\n" +"\n" +"It raises KeyboardInterrupt."); + +#define SIGNAL_DEFAULT_INT_HANDLER_METHODDEF \ + {"default_int_handler", (PyCFunction)(void(*)(void))signal_default_int_handler, METH_FASTCALL, signal_default_int_handler__doc__}, + +static PyObject * +signal_default_int_handler_impl(PyObject *module, int signalnum, + PyObject *frame); + +static PyObject * +signal_default_int_handler(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int signalnum; + PyObject *frame; + + if (!_PyArg_CheckPositional("default_int_handler", nargs, 2, 2)) { + goto exit; + } + signalnum = _PyLong_AsInt(args[0]); + if (signalnum == -1 && PyErr_Occurred()) { + goto exit; + } + frame = args[1]; + return_value = signal_default_int_handler_impl(module, signalnum, frame); + +exit: + return return_value; +} + #if defined(HAVE_ALARM) PyDoc_STRVAR(signal_alarm__doc__, @@ -23,11 +59,6 @@ signal_alarm(PyObject *module, PyObject *arg) int seconds; long _return_value; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } seconds = _PyLong_AsInt(arg); if (seconds == -1 && PyErr_Occurred()) { goto exit; @@ -84,11 +115,6 @@ signal_raise_signal(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int signalnum; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } signalnum = _PyLong_AsInt(arg); if (signalnum == -1 && PyErr_Occurred()) { goto exit; @@ -128,11 +154,6 @@ signal_signal(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("signal", nargs, 2, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } signalnum = _PyLong_AsInt(args[0]); if (signalnum == -1 && PyErr_Occurred()) { goto exit; @@ -168,11 +189,6 @@ signal_getsignal(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int signalnum; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } signalnum = _PyLong_AsInt(arg); if (signalnum == -1 && PyErr_Occurred()) { goto exit; @@ -204,11 +220,6 @@ signal_strsignal(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int signalnum; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } signalnum = _PyLong_AsInt(arg); if (signalnum == -1 && PyErr_Occurred()) { goto exit; @@ -246,20 +257,10 @@ signal_siginterrupt(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("siginterrupt", nargs, 2, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } signalnum = _PyLong_AsInt(args[0]); if (signalnum == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } flag = _PyLong_AsInt(args[1]); if (flag == -1 && PyErr_Occurred()) { goto exit; @@ -303,11 +304,6 @@ signal_setitimer(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (!_PyArg_CheckPositional("setitimer", nargs, 2, 3)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } which = _PyLong_AsInt(args[0]); if (which == -1 && PyErr_Occurred()) { goto exit; @@ -346,11 +342,6 @@ signal_getitimer(PyObject *module, PyObject *arg) PyObject *return_value = NULL; int which; - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } which = _PyLong_AsInt(arg); if (which == -1 && PyErr_Occurred()) { goto exit; @@ -387,11 +378,6 @@ signal_pthread_sigmask(PyObject *module, PyObject *const *args, Py_ssize_t nargs if (!_PyArg_CheckPositional("pthread_sigmask", nargs, 2, 2)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } how = _PyLong_AsInt(args[0]); if (how == -1 && PyErr_Occurred()) { goto exit; @@ -594,11 +580,6 @@ signal_pthread_kill(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } thread_id = PyLong_AsUnsignedLongMask(args[0]); - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } signalnum = _PyLong_AsInt(args[1]); if (signalnum == -1 && PyErr_Occurred()) { goto exit; @@ -638,20 +619,10 @@ signal_pidfd_send_signal(PyObject *module, PyObject *const *args, Py_ssize_t nar if (!_PyArg_CheckPositional("pidfd_send_signal", nargs, 2, 4)) { goto exit; } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } pidfd = _PyLong_AsInt(args[0]); if (pidfd == -1 && PyErr_Occurred()) { goto exit; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } signalnum = _PyLong_AsInt(args[1]); if (signalnum == -1 && PyErr_Occurred()) { goto exit; @@ -663,11 +634,6 @@ signal_pidfd_send_signal(PyObject *module, PyObject *const *args, Py_ssize_t nar if (nargs < 4) { goto skip_optional; } - if (PyFloat_Check(args[3])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } flags = _PyLong_AsInt(args[3]); if (flags == -1 && PyErr_Occurred()) { goto exit; @@ -732,4 +698,4 @@ exit: #ifndef SIGNAL_PIDFD_SEND_SIGNAL_METHODDEF #define SIGNAL_PIDFD_SEND_SIGNAL_METHODDEF #endif /* !defined(SIGNAL_PIDFD_SEND_SIGNAL_METHODDEF) */ -/*[clinic end generated code: output=3c8b80f14df17563 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c353e686367bc384 input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/termios.c.h b/contrib/tools/python3/src/Modules/clinic/termios.c.h new file mode 100644 index 0000000000..a45c1f6426 --- /dev/null +++ b/contrib/tools/python3/src/Modules/clinic/termios.c.h @@ -0,0 +1,225 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(termios_tcgetattr__doc__, +"tcgetattr($module, fd, /)\n" +"--\n" +"\n" +"Get the tty attributes for file descriptor fd.\n" +"\n" +"Returns a list [iflag, oflag, cflag, lflag, ispeed, ospeed, cc]\n" +"where cc is a list of the tty special characters (each a string of\n" +"length 1, except the items with indices VMIN and VTIME, which are\n" +"integers when these fields are defined). The interpretation of the\n" +"flags and the speeds as well as the indexing in the cc array must be\n" +"done using the symbolic constants defined in this module."); + +#define TERMIOS_TCGETATTR_METHODDEF \ + {"tcgetattr", (PyCFunction)termios_tcgetattr, METH_O, termios_tcgetattr__doc__}, + +static PyObject * +termios_tcgetattr_impl(PyObject *module, int fd); + +static PyObject * +termios_tcgetattr(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int fd; + + if (!_PyLong_FileDescriptor_Converter(arg, &fd)) { + goto exit; + } + return_value = termios_tcgetattr_impl(module, fd); + +exit: + return return_value; +} + +PyDoc_STRVAR(termios_tcsetattr__doc__, +"tcsetattr($module, fd, when, attributes, /)\n" +"--\n" +"\n" +"Set the tty attributes for file descriptor fd.\n" +"\n" +"The attributes to be set are taken from the attributes argument, which\n" +"is a list like the one returned by tcgetattr(). The when argument\n" +"determines when the attributes are changed: termios.TCSANOW to\n" +"change immediately, termios.TCSADRAIN to change after transmitting all\n" +"queued output, or termios.TCSAFLUSH to change after transmitting all\n" +"queued output and discarding all queued input."); + +#define TERMIOS_TCSETATTR_METHODDEF \ + {"tcsetattr", (PyCFunction)(void(*)(void))termios_tcsetattr, METH_FASTCALL, termios_tcsetattr__doc__}, + +static PyObject * +termios_tcsetattr_impl(PyObject *module, int fd, int when, PyObject *term); + +static PyObject * +termios_tcsetattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + int when; + PyObject *term; + + if (!_PyArg_CheckPositional("tcsetattr", nargs, 3, 3)) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + when = _PyLong_AsInt(args[1]); + if (when == -1 && PyErr_Occurred()) { + goto exit; + } + term = args[2]; + return_value = termios_tcsetattr_impl(module, fd, when, term); + +exit: + return return_value; +} + +PyDoc_STRVAR(termios_tcsendbreak__doc__, +"tcsendbreak($module, fd, duration, /)\n" +"--\n" +"\n" +"Send a break on file descriptor fd.\n" +"\n" +"A zero duration sends a break for 0.25-0.5 seconds; a nonzero duration\n" +"has a system dependent meaning."); + +#define TERMIOS_TCSENDBREAK_METHODDEF \ + {"tcsendbreak", (PyCFunction)(void(*)(void))termios_tcsendbreak, METH_FASTCALL, termios_tcsendbreak__doc__}, + +static PyObject * +termios_tcsendbreak_impl(PyObject *module, int fd, int duration); + +static PyObject * +termios_tcsendbreak(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + int duration; + + if (!_PyArg_CheckPositional("tcsendbreak", nargs, 2, 2)) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + duration = _PyLong_AsInt(args[1]); + if (duration == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = termios_tcsendbreak_impl(module, fd, duration); + +exit: + return return_value; +} + +PyDoc_STRVAR(termios_tcdrain__doc__, +"tcdrain($module, fd, /)\n" +"--\n" +"\n" +"Wait until all output written to file descriptor fd has been transmitted."); + +#define TERMIOS_TCDRAIN_METHODDEF \ + {"tcdrain", (PyCFunction)termios_tcdrain, METH_O, termios_tcdrain__doc__}, + +static PyObject * +termios_tcdrain_impl(PyObject *module, int fd); + +static PyObject * +termios_tcdrain(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int fd; + + if (!_PyLong_FileDescriptor_Converter(arg, &fd)) { + goto exit; + } + return_value = termios_tcdrain_impl(module, fd); + +exit: + return return_value; +} + +PyDoc_STRVAR(termios_tcflush__doc__, +"tcflush($module, fd, queue, /)\n" +"--\n" +"\n" +"Discard queued data on file descriptor fd.\n" +"\n" +"The queue selector specifies which queue: termios.TCIFLUSH for the input\n" +"queue, termios.TCOFLUSH for the output queue, or termios.TCIOFLUSH for\n" +"both queues."); + +#define TERMIOS_TCFLUSH_METHODDEF \ + {"tcflush", (PyCFunction)(void(*)(void))termios_tcflush, METH_FASTCALL, termios_tcflush__doc__}, + +static PyObject * +termios_tcflush_impl(PyObject *module, int fd, int queue); + +static PyObject * +termios_tcflush(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + int queue; + + if (!_PyArg_CheckPositional("tcflush", nargs, 2, 2)) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + queue = _PyLong_AsInt(args[1]); + if (queue == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = termios_tcflush_impl(module, fd, queue); + +exit: + return return_value; +} + +PyDoc_STRVAR(termios_tcflow__doc__, +"tcflow($module, fd, action, /)\n" +"--\n" +"\n" +"Suspend or resume input or output on file descriptor fd.\n" +"\n" +"The action argument can be termios.TCOOFF to suspend output,\n" +"termios.TCOON to restart output, termios.TCIOFF to suspend input,\n" +"or termios.TCION to restart input."); + +#define TERMIOS_TCFLOW_METHODDEF \ + {"tcflow", (PyCFunction)(void(*)(void))termios_tcflow, METH_FASTCALL, termios_tcflow__doc__}, + +static PyObject * +termios_tcflow_impl(PyObject *module, int fd, int action); + +static PyObject * +termios_tcflow(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fd; + int action; + + if (!_PyArg_CheckPositional("tcflow", nargs, 2, 2)) { + goto exit; + } + if (!_PyLong_FileDescriptor_Converter(args[0], &fd)) { + goto exit; + } + action = _PyLong_AsInt(args[1]); + if (action == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = termios_tcflow_impl(module, fd, action); + +exit: + return return_value; +} +/*[clinic end generated code: output=a129179f1e2545cc input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/clinic/zlibmodule.c.h b/contrib/tools/python3/src/Modules/clinic/zlibmodule.c.h index 77ea04a353..14e955db64 100644 --- a/contrib/tools/python3/src/Modules/clinic/zlibmodule.c.h +++ b/contrib/tools/python3/src/Modules/clinic/zlibmodule.c.h @@ -44,11 +44,6 @@ zlib_compress(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec if (!noptargs) { goto skip_optional_pos; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } level = _PyLong_AsInt(args[1]); if (level == -1 && PyErr_Occurred()) { goto exit; @@ -112,11 +107,6 @@ zlib_decompress(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj goto skip_optional_pos; } if (args[1]) { - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } wbits = _PyLong_AsInt(args[1]); if (wbits == -1 && PyErr_Occurred()) { goto exit; @@ -125,8 +115,17 @@ zlib_decompress(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObj goto skip_optional_pos; } } - if (!ssize_t_converter(args[2], &bufsize)) { - goto exit; + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[2]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + bufsize = ival; } skip_optional_pos: return_value = zlib_decompress_impl(module, &data, wbits, bufsize); @@ -200,11 +199,6 @@ zlib_compressobj(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb goto skip_optional_pos; } if (args[0]) { - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } level = _PyLong_AsInt(args[0]); if (level == -1 && PyErr_Occurred()) { goto exit; @@ -214,11 +208,6 @@ zlib_compressobj(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb } } if (args[1]) { - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } method = _PyLong_AsInt(args[1]); if (method == -1 && PyErr_Occurred()) { goto exit; @@ -228,11 +217,6 @@ zlib_compressobj(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb } } if (args[2]) { - if (PyFloat_Check(args[2])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } wbits = _PyLong_AsInt(args[2]); if (wbits == -1 && PyErr_Occurred()) { goto exit; @@ -242,11 +226,6 @@ zlib_compressobj(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb } } if (args[3]) { - if (PyFloat_Check(args[3])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } memLevel = _PyLong_AsInt(args[3]); if (memLevel == -1 && PyErr_Occurred()) { goto exit; @@ -256,11 +235,6 @@ zlib_compressobj(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyOb } } if (args[4]) { - if (PyFloat_Check(args[4])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } strategy = _PyLong_AsInt(args[4]); if (strategy == -1 && PyErr_Occurred()) { goto exit; @@ -325,11 +299,6 @@ zlib_decompressobj(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py goto skip_optional_pos; } if (args[0]) { - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } wbits = _PyLong_AsInt(args[0]); if (wbits == -1 && PyErr_Occurred()) { goto exit; @@ -360,25 +329,25 @@ PyDoc_STRVAR(zlib_Compress_compress__doc__, "Call the flush() method to clear these buffers."); #define ZLIB_COMPRESS_COMPRESS_METHODDEF \ - {"compress", (PyCFunction)zlib_Compress_compress, METH_O, zlib_Compress_compress__doc__}, + {"compress", (PyCFunction)(void(*)(void))zlib_Compress_compress, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, zlib_Compress_compress__doc__}, static PyObject * -zlib_Compress_compress_impl(compobject *self, Py_buffer *data); +zlib_Compress_compress_impl(compobject *self, PyTypeObject *cls, + Py_buffer *data); static PyObject * -zlib_Compress_compress(compobject *self, PyObject *arg) +zlib_Compress_compress(compobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = {"y*:compress", _keywords, 0}; Py_buffer data = {NULL, NULL}; - if (PyObject_GetBuffer(arg, &data, PyBUF_SIMPLE) != 0) { - goto exit; - } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("compress", "argument", "contiguous buffer", arg); + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &data)) { goto exit; } - return_value = zlib_Compress_compress_impl(self, &data); + return_value = zlib_Compress_compress_impl(self, cls, &data); exit: /* Cleanup for data */ @@ -407,42 +376,26 @@ PyDoc_STRVAR(zlib_Decompress_decompress__doc__, "Call the flush() method to clear these buffers."); #define ZLIB_DECOMPRESS_DECOMPRESS_METHODDEF \ - {"decompress", (PyCFunction)(void(*)(void))zlib_Decompress_decompress, METH_FASTCALL|METH_KEYWORDS, zlib_Decompress_decompress__doc__}, + {"decompress", (PyCFunction)(void(*)(void))zlib_Decompress_decompress, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, zlib_Decompress_decompress__doc__}, static PyObject * -zlib_Decompress_decompress_impl(compobject *self, Py_buffer *data, - Py_ssize_t max_length); +zlib_Decompress_decompress_impl(compobject *self, PyTypeObject *cls, + Py_buffer *data, Py_ssize_t max_length); static PyObject * -zlib_Decompress_decompress(compobject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +zlib_Decompress_decompress(compobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"", "max_length", NULL}; - static _PyArg_Parser _parser = {NULL, _keywords, "decompress", 0}; - PyObject *argsbuf[2]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + static _PyArg_Parser _parser = {"y*|n:decompress", _keywords, 0}; Py_buffer data = {NULL, NULL}; Py_ssize_t max_length = 0; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); - if (!args) { + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &data, &max_length)) { goto exit; } - if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) { - goto exit; - } - if (!PyBuffer_IsContiguous(&data, 'C')) { - _PyArg_BadArgument("decompress", "argument 1", "contiguous buffer", args[0]); - goto exit; - } - if (!noptargs) { - goto skip_optional_pos; - } - if (!ssize_t_converter(args[1], &max_length)) { - goto exit; - } -skip_optional_pos: - return_value = zlib_Decompress_decompress_impl(self, &data, max_length); + return_value = zlib_Decompress_decompress_impl(self, cls, &data, max_length); exit: /* Cleanup for data */ @@ -466,34 +419,24 @@ PyDoc_STRVAR(zlib_Compress_flush__doc__, " can still be compressed."); #define ZLIB_COMPRESS_FLUSH_METHODDEF \ - {"flush", (PyCFunction)(void(*)(void))zlib_Compress_flush, METH_FASTCALL, zlib_Compress_flush__doc__}, + {"flush", (PyCFunction)(void(*)(void))zlib_Compress_flush, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, zlib_Compress_flush__doc__}, static PyObject * -zlib_Compress_flush_impl(compobject *self, int mode); +zlib_Compress_flush_impl(compobject *self, PyTypeObject *cls, int mode); static PyObject * -zlib_Compress_flush(compobject *self, PyObject *const *args, Py_ssize_t nargs) +zlib_Compress_flush(compobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = {"|i:flush", _keywords, 0}; int mode = Z_FINISH; - if (!_PyArg_CheckPositional("flush", nargs, 0, 1)) { - goto exit; - } - if (nargs < 1) { - goto skip_optional; - } - if (PyFloat_Check(args[0])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &mode)) { goto exit; } - mode = _PyLong_AsInt(args[0]); - if (mode == -1 && PyErr_Occurred()) { - goto exit; - } -skip_optional: - return_value = zlib_Compress_flush_impl(self, mode); + return_value = zlib_Compress_flush_impl(self, cls, mode); exit: return return_value; @@ -508,15 +451,26 @@ PyDoc_STRVAR(zlib_Compress_copy__doc__, "Return a copy of the compression object."); #define ZLIB_COMPRESS_COPY_METHODDEF \ - {"copy", (PyCFunction)zlib_Compress_copy, METH_NOARGS, zlib_Compress_copy__doc__}, + {"copy", (PyCFunction)(void(*)(void))zlib_Compress_copy, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, zlib_Compress_copy__doc__}, static PyObject * -zlib_Compress_copy_impl(compobject *self); +zlib_Compress_copy_impl(compobject *self, PyTypeObject *cls); static PyObject * -zlib_Compress_copy(compobject *self, PyObject *Py_UNUSED(ignored)) +zlib_Compress_copy(compobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return zlib_Compress_copy_impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = {":copy", _keywords, 0}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser + )) { + goto exit; + } + return_value = zlib_Compress_copy_impl(self, cls); + +exit: + return return_value; } #endif /* defined(HAVE_ZLIB_COPY) */ @@ -529,15 +483,26 @@ PyDoc_STRVAR(zlib_Compress___copy____doc__, "\n"); #define ZLIB_COMPRESS___COPY___METHODDEF \ - {"__copy__", (PyCFunction)zlib_Compress___copy__, METH_NOARGS, zlib_Compress___copy____doc__}, + {"__copy__", (PyCFunction)(void(*)(void))zlib_Compress___copy__, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, zlib_Compress___copy____doc__}, static PyObject * -zlib_Compress___copy___impl(compobject *self); +zlib_Compress___copy___impl(compobject *self, PyTypeObject *cls); static PyObject * -zlib_Compress___copy__(compobject *self, PyObject *Py_UNUSED(ignored)) +zlib_Compress___copy__(compobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return zlib_Compress___copy___impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = {":__copy__", _keywords, 0}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser + )) { + goto exit; + } + return_value = zlib_Compress___copy___impl(self, cls); + +exit: + return return_value; } #endif /* defined(HAVE_ZLIB_COPY) */ @@ -550,7 +515,29 @@ PyDoc_STRVAR(zlib_Compress___deepcopy____doc__, "\n"); #define ZLIB_COMPRESS___DEEPCOPY___METHODDEF \ - {"__deepcopy__", (PyCFunction)zlib_Compress___deepcopy__, METH_O, zlib_Compress___deepcopy____doc__}, + {"__deepcopy__", (PyCFunction)(void(*)(void))zlib_Compress___deepcopy__, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, zlib_Compress___deepcopy____doc__}, + +static PyObject * +zlib_Compress___deepcopy___impl(compobject *self, PyTypeObject *cls, + PyObject *memo); + +static PyObject * +zlib_Compress___deepcopy__(compobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = {"O:__deepcopy__", _keywords, 0}; + PyObject *memo; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &memo)) { + goto exit; + } + return_value = zlib_Compress___deepcopy___impl(self, cls, memo); + +exit: + return return_value; +} #endif /* defined(HAVE_ZLIB_COPY) */ @@ -563,15 +550,26 @@ PyDoc_STRVAR(zlib_Decompress_copy__doc__, "Return a copy of the decompression object."); #define ZLIB_DECOMPRESS_COPY_METHODDEF \ - {"copy", (PyCFunction)zlib_Decompress_copy, METH_NOARGS, zlib_Decompress_copy__doc__}, + {"copy", (PyCFunction)(void(*)(void))zlib_Decompress_copy, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, zlib_Decompress_copy__doc__}, static PyObject * -zlib_Decompress_copy_impl(compobject *self); +zlib_Decompress_copy_impl(compobject *self, PyTypeObject *cls); static PyObject * -zlib_Decompress_copy(compobject *self, PyObject *Py_UNUSED(ignored)) +zlib_Decompress_copy(compobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return zlib_Decompress_copy_impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = {":copy", _keywords, 0}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser + )) { + goto exit; + } + return_value = zlib_Decompress_copy_impl(self, cls); + +exit: + return return_value; } #endif /* defined(HAVE_ZLIB_COPY) */ @@ -584,15 +582,26 @@ PyDoc_STRVAR(zlib_Decompress___copy____doc__, "\n"); #define ZLIB_DECOMPRESS___COPY___METHODDEF \ - {"__copy__", (PyCFunction)zlib_Decompress___copy__, METH_NOARGS, zlib_Decompress___copy____doc__}, + {"__copy__", (PyCFunction)(void(*)(void))zlib_Decompress___copy__, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, zlib_Decompress___copy____doc__}, static PyObject * -zlib_Decompress___copy___impl(compobject *self); +zlib_Decompress___copy___impl(compobject *self, PyTypeObject *cls); static PyObject * -zlib_Decompress___copy__(compobject *self, PyObject *Py_UNUSED(ignored)) +zlib_Decompress___copy__(compobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return zlib_Decompress___copy___impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = {":__copy__", _keywords, 0}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser + )) { + goto exit; + } + return_value = zlib_Decompress___copy___impl(self, cls); + +exit: + return return_value; } #endif /* defined(HAVE_ZLIB_COPY) */ @@ -605,7 +614,29 @@ PyDoc_STRVAR(zlib_Decompress___deepcopy____doc__, "\n"); #define ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF \ - {"__deepcopy__", (PyCFunction)zlib_Decompress___deepcopy__, METH_O, zlib_Decompress___deepcopy____doc__}, + {"__deepcopy__", (PyCFunction)(void(*)(void))zlib_Decompress___deepcopy__, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, zlib_Decompress___deepcopy____doc__}, + +static PyObject * +zlib_Decompress___deepcopy___impl(compobject *self, PyTypeObject *cls, + PyObject *memo); + +static PyObject * +zlib_Decompress___deepcopy__(compobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = {"O:__deepcopy__", _keywords, 0}; + PyObject *memo; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &memo)) { + goto exit; + } + return_value = zlib_Decompress___deepcopy___impl(self, cls, memo); + +exit: + return return_value; +} #endif /* defined(HAVE_ZLIB_COPY) */ @@ -619,28 +650,25 @@ PyDoc_STRVAR(zlib_Decompress_flush__doc__, " the initial size of the output buffer."); #define ZLIB_DECOMPRESS_FLUSH_METHODDEF \ - {"flush", (PyCFunction)(void(*)(void))zlib_Decompress_flush, METH_FASTCALL, zlib_Decompress_flush__doc__}, + {"flush", (PyCFunction)(void(*)(void))zlib_Decompress_flush, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, zlib_Decompress_flush__doc__}, static PyObject * -zlib_Decompress_flush_impl(compobject *self, Py_ssize_t length); +zlib_Decompress_flush_impl(compobject *self, PyTypeObject *cls, + Py_ssize_t length); static PyObject * -zlib_Decompress_flush(compobject *self, PyObject *const *args, Py_ssize_t nargs) +zlib_Decompress_flush(compobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + static const char * const _keywords[] = {"", NULL}; + static _PyArg_Parser _parser = {"|n:flush", _keywords, 0}; Py_ssize_t length = DEF_BUF_SIZE; - if (!_PyArg_CheckPositional("flush", nargs, 0, 1)) { + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &length)) { goto exit; } - if (nargs < 1) { - goto skip_optional; - } - if (!ssize_t_converter(args[0], &length)) { - goto exit; - } -skip_optional: - return_value = zlib_Decompress_flush_impl(self, length); + return_value = zlib_Decompress_flush_impl(self, cls, length); exit: return return_value; @@ -683,11 +711,6 @@ zlib_adler32(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 2) { goto skip_optional; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } value = (unsigned int)PyLong_AsUnsignedLongMask(args[1]); if (value == (unsigned int)-1 && PyErr_Occurred()) { goto exit; @@ -741,11 +764,6 @@ zlib_crc32(PyObject *module, PyObject *const *args, Py_ssize_t nargs) if (nargs < 2) { goto skip_optional; } - if (PyFloat_Check(args[1])) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } value = (unsigned int)PyLong_AsUnsignedLongMask(args[1]); if (value == (unsigned int)-1 && PyErr_Occurred()) { goto exit; @@ -785,4 +803,4 @@ exit: #ifndef ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF #define ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF #endif /* !defined(ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF) */ -/*[clinic end generated code: output=faae38ef96b88b16 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=6736bae59fab268b input=a9049054013a1b77]*/ diff --git a/contrib/tools/python3/src/Modules/cmathmodule.c b/contrib/tools/python3/src/Modules/cmathmodule.c index 5eac4b4940..0f22049a17 100644 --- a/contrib/tools/python3/src/Modules/cmathmodule.c +++ b/contrib/tools/python3/src/Modules/cmathmodule.c @@ -1254,37 +1254,35 @@ static PyMethodDef cmath_methods[] = { {NULL, NULL} /* sentinel */ }; - -static struct PyModuleDef cmathmodule = { - PyModuleDef_HEAD_INIT, - "cmath", - module_doc, - -1, - cmath_methods, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit_cmath(void) +static int +cmath_exec(PyObject *mod) { - PyObject *m; - - m = PyModule_Create(&cmathmodule); - if (m == NULL) - return NULL; - - PyModule_AddObject(m, "pi", - PyFloat_FromDouble(Py_MATH_PI)); - PyModule_AddObject(m, "e", PyFloat_FromDouble(Py_MATH_E)); - PyModule_AddObject(m, "tau", PyFloat_FromDouble(Py_MATH_TAU)); /* 2pi */ - PyModule_AddObject(m, "inf", PyFloat_FromDouble(m_inf())); - PyModule_AddObject(m, "infj", PyComplex_FromCComplex(c_infj())); + if (PyModule_AddObject(mod, "pi", PyFloat_FromDouble(Py_MATH_PI)) < 0) { + return -1; + } + if (PyModule_AddObject(mod, "e", PyFloat_FromDouble(Py_MATH_E)) < 0) { + return -1; + } + // 2pi + if (PyModule_AddObject(mod, "tau", PyFloat_FromDouble(Py_MATH_TAU)) < 0) { + return -1; + } + if (PyModule_AddObject(mod, "inf", PyFloat_FromDouble(m_inf())) < 0) { + return -1; + } + + if (PyModule_AddObject(mod, "infj", + PyComplex_FromCComplex(c_infj())) < 0) { + return -1; + } #if !defined(PY_NO_SHORT_FLOAT_REPR) || defined(Py_NAN) - PyModule_AddObject(m, "nan", PyFloat_FromDouble(m_nan())); - PyModule_AddObject(m, "nanj", PyComplex_FromCComplex(c_nanj())); + if (PyModule_AddObject(mod, "nan", PyFloat_FromDouble(m_nan())) < 0) { + return -1; + } + if (PyModule_AddObject(mod, "nanj", + PyComplex_FromCComplex(c_nanj())) < 0) { + return -1; + } #endif /* initialize special value tables */ @@ -1401,5 +1399,25 @@ PyInit_cmath(void) C(INF,N) C(U,U) C(INF,-0.) C(INF,0.) C(U,U) C(INF,N) C(INF,N) C(N,N) C(N,N) C(N,0.) C(N,0.) C(N,N) C(N,N) C(N,N) }) - return m; + return 0; } + +static PyModuleDef_Slot cmath_slots[] = { + {Py_mod_exec, cmath_exec}, + {0, NULL} +}; + +static struct PyModuleDef cmathmodule = { + PyModuleDef_HEAD_INIT, + .m_name = "cmath", + .m_doc = module_doc, + .m_size = 0, + .m_methods = cmath_methods, + .m_slots = cmath_slots +}; + +PyMODINIT_FUNC +PyInit_cmath(void) +{ + return PyModuleDef_Init(&cmathmodule); +}
\ No newline at end of file diff --git a/contrib/tools/python3/src/Modules/config.c b/contrib/tools/python3/src/Modules/config.c index 2128f544e5..527f5889ee 100644 --- a/contrib/tools/python3/src/Modules/config.c +++ b/contrib/tools/python3/src/Modules/config.c @@ -58,7 +58,6 @@ extern PyObject* PyInit__multibytecodec(void); // _multibytecodec extern PyObject* PyInit__multiprocessing(void); // _multiprocessing extern PyObject* PyInit__opcode(void); // _opcode extern PyObject* PyInit__operator(void); // _operator -extern PyObject* PyInit__peg_parser(void); // _peg_parser extern PyObject* PyInit__pickle(void); // _pickle extern PyObject* PyInit__posixshmem(void); // _posixshmem #if !defined(_MSC_VER) @@ -95,16 +94,15 @@ extern PyObject* PyInit_faulthandler(void); // faulthandler #if !defined(_MSC_VER) extern PyObject* PyInit_fcntl(void); // fcntl #endif +#if defined(_MSC_VER) +extern PyObject* PyInit_nt(void); // nt +#endif #if !defined(_MSC_VER) extern PyObject* PyInit_grp(void); // grp #endif extern PyObject* PyInit_itertools(void); // itertools extern PyObject* PyInit_math(void); // math extern PyObject* PyInit_mmap(void); // mmap -#if defined(_MSC_VER) -extern PyObject* PyInit_nt(void); // nt -#endif -extern PyObject* PyInit_parser(void); // parser #if !defined(_MSC_VER) extern PyObject* PyInit_posix(void); // posix #endif @@ -192,7 +190,6 @@ struct _inittab _PyImport_Inittab[] = { {"_multiprocessing", PyInit__multiprocessing}, {"_opcode", PyInit__opcode}, {"_operator", PyInit__operator}, - {"_peg_parser", PyInit__peg_parser}, {"_pickle", PyInit__pickle}, {"_posixshmem", PyInit__posixshmem}, #if !defined(_MSC_VER) @@ -225,6 +222,9 @@ struct _inittab _PyImport_Inittab[] = { {"binascii", PyInit_binascii}, {"cmath", PyInit_cmath}, {"errno", PyInit_errno}, +#if defined(_MSC_VER) + {"nt", PyInit_nt}, +#endif {"faulthandler", PyInit_faulthandler}, #if !defined(_MSC_VER) {"fcntl", PyInit_fcntl}, @@ -235,10 +235,6 @@ struct _inittab _PyImport_Inittab[] = { {"itertools", PyInit_itertools}, {"math", PyInit_math}, {"mmap", PyInit_mmap}, -#if defined(_MSC_VER) - {"nt", PyInit_nt}, -#endif - {"parser", PyInit_parser}, #if !defined(_MSC_VER) {"posix", PyInit_posix}, #endif diff --git a/contrib/tools/python3/src/Modules/faulthandler.c b/contrib/tools/python3/src/Modules/faulthandler.c index 16f98ace3b..4af8702068 100644 --- a/contrib/tools/python3/src/Modules/faulthandler.c +++ b/contrib/tools/python3/src/Modules/faulthandler.c @@ -1,6 +1,8 @@ #include "Python.h" -#include "pycore_initconfig.h" -#include "pycore_traceback.h" +#include "pycore_initconfig.h" // _PyStatus_ERR +#include "pycore_pyerrors.h" // _Py_DumpExtensionModules +#include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_traceback.h" // _Py_DumpTracebackThreads #include <signal.h> #include <object.h> #include <frameobject.h> @@ -229,7 +231,7 @@ faulthandler_get_fileno(PyObject **file_ptr) static PyThreadState* get_thread_state(void) { - PyThreadState *tstate = _PyThreadState_UncheckedGet(); + PyThreadState *tstate = _PyThreadState_GET(); if (tstate == NULL) { /* just in case but very unlikely... */ PyErr_SetString(PyExc_RuntimeError, @@ -371,6 +373,8 @@ faulthandler_fatal_error(int signum) faulthandler_dump_traceback(fd, fatal_error.all_threads, fatal_error.interp); + _Py_DumpExtensionModules(fd, fatal_error.interp); + errno = save_errno; #ifdef MS_WINDOWS if (signum == SIGSEGV) { @@ -1148,25 +1152,6 @@ faulthandler_sigabrt(PyObject *self, PyObject *args) Py_RETURN_NONE; } -static PyObject * -faulthandler_fatal_error_py(PyObject *self, PyObject *args) -{ - char *message; - int release_gil = 0; - if (!PyArg_ParseTuple(args, "y|i:fatal_error", &message, &release_gil)) - return NULL; - faulthandler_suppress_crash_report(); - if (release_gil) { - Py_BEGIN_ALLOW_THREADS - Py_FatalError(message); - Py_END_ALLOW_THREADS - } - else { - Py_FatalError(message); - } - Py_RETURN_NONE; -} - #if defined(FAULTHANDLER_USE_ALT_STACK) #define FAULTHANDLER_STACK_OVERFLOW @@ -1303,8 +1288,6 @@ static PyMethodDef module_methods[] = { PyDoc_STR("_sigabrt(): raise a SIGABRT signal")}, {"_sigfpe", (PyCFunction)faulthandler_sigfpe, METH_NOARGS, PyDoc_STR("_sigfpe(): raise a SIGFPE signal")}, - {"_fatal_error", faulthandler_fatal_error_py, METH_VARARGS, - PyDoc_STR("_fatal_error(message): call Py_FatalError(message)")}, #ifdef FAULTHANDLER_STACK_OVERFLOW {"_stack_overflow", faulthandler_stack_overflow, METH_NOARGS, PyDoc_STR("_stack_overflow(): recursive call to raise a stack overflow")}, @@ -1316,59 +1299,55 @@ static PyMethodDef module_methods[] = { {NULL, NULL} /* sentinel */ }; -static struct PyModuleDef module_def = { - PyModuleDef_HEAD_INIT, - "faulthandler", - module_doc, - 0, /* non-negative size to be able to unload the module */ - module_methods, - NULL, - faulthandler_traverse, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit_faulthandler(void) -{ - PyObject *m = PyModule_Create(&module_def); - if (m == NULL) - return NULL; - +static int +PyExec_faulthandler(PyObject *module) { /* Add constants for unit tests */ #ifdef MS_WINDOWS /* RaiseException() codes (prefixed by an underscore) */ - if (PyModule_AddIntConstant(m, "_EXCEPTION_ACCESS_VIOLATION", + if (PyModule_AddIntConstant(module, "_EXCEPTION_ACCESS_VIOLATION", EXCEPTION_ACCESS_VIOLATION)) { - goto error; + return -1; } - if (PyModule_AddIntConstant(m, "_EXCEPTION_INT_DIVIDE_BY_ZERO", + if (PyModule_AddIntConstant(module, "_EXCEPTION_INT_DIVIDE_BY_ZERO", EXCEPTION_INT_DIVIDE_BY_ZERO)) { - goto error; + return -1; } - if (PyModule_AddIntConstant(m, "_EXCEPTION_STACK_OVERFLOW", + if (PyModule_AddIntConstant(module, "_EXCEPTION_STACK_OVERFLOW", EXCEPTION_STACK_OVERFLOW)) { - goto error; + return -1; } /* RaiseException() flags (prefixed by an underscore) */ - if (PyModule_AddIntConstant(m, "_EXCEPTION_NONCONTINUABLE", + if (PyModule_AddIntConstant(module, "_EXCEPTION_NONCONTINUABLE", EXCEPTION_NONCONTINUABLE)) { - goto error; + return -1; } - if (PyModule_AddIntConstant(m, "_EXCEPTION_NONCONTINUABLE_EXCEPTION", + if (PyModule_AddIntConstant(module, "_EXCEPTION_NONCONTINUABLE_EXCEPTION", EXCEPTION_NONCONTINUABLE_EXCEPTION)) { - goto error; + return -1; } #endif + return 0; +} - return m; +static PyModuleDef_Slot faulthandler_slots[] = { + {Py_mod_exec, PyExec_faulthandler}, + {0, NULL} +}; -#ifdef MS_WINDOWS -error: - Py_DECREF(m); - return NULL; -#endif +static struct PyModuleDef module_def = { + PyModuleDef_HEAD_INIT, + .m_name = "faulthandler", + .m_doc = module_doc, + .m_methods = module_methods, + .m_traverse = faulthandler_traverse, + .m_slots = faulthandler_slots +}; + +PyMODINIT_FUNC +PyInit_faulthandler(void) +{ + return PyModuleDef_Init(&module_def); } static int diff --git a/contrib/tools/python3/src/Modules/fcntlmodule.c b/contrib/tools/python3/src/Modules/fcntlmodule.c index 43f9b22f67..cdf0f9bf37 100644 --- a/contrib/tools/python3/src/Modules/fcntlmodule.c +++ b/contrib/tools/python3/src/Modules/fcntlmodule.c @@ -20,24 +20,12 @@ module fcntl [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=124b58387c158179]*/ -static int -conv_descriptor(PyObject *object, int *target) -{ - int fd = PyObject_AsFileDescriptor(object); - - if (fd < 0) - return 0; - *target = fd; - return 1; -} - -/* Must come after conv_descriptor definition. */ #include "clinic/fcntlmodule.c.h" /*[clinic input] fcntl.fcntl - fd: object(type='int', converter='conv_descriptor') + fd: fildes cmd as code: int arg: object(c_default='NULL') = 0 / @@ -57,7 +45,7 @@ corresponding to the return value of the fcntl call in the C code. static PyObject * fcntl_fcntl_impl(PyObject *module, int fd, int code, PyObject *arg) -/*[clinic end generated code: output=888fc93b51c295bd input=8cefbe59b29efbe2]*/ +/*[clinic end generated code: output=888fc93b51c295bd input=7955340198e5f334]*/ { unsigned int int_arg = 0; int ret; @@ -116,7 +104,7 @@ fcntl_fcntl_impl(PyObject *module, int fd, int code, PyObject *arg) /*[clinic input] fcntl.ioctl - fd: object(type='int', converter='conv_descriptor') + fd: fildes request as code: unsigned_int(bitwise=True) arg as ob_arg: object(c_default='NULL') = 0 mutate_flag as mutate_arg: bool = True @@ -155,7 +143,7 @@ code. static PyObject * fcntl_ioctl_impl(PyObject *module, int fd, unsigned int code, PyObject *ob_arg, int mutate_arg) -/*[clinic end generated code: output=7f7f5840c65991be input=ede70c433cccbbb2]*/ +/*[clinic end generated code: output=7f7f5840c65991be input=967b4a4cbeceb0a8]*/ { #define IOCTL_BUFSZ 1024 /* We use the unsigned non-checked 'I' format for the 'code' parameter @@ -280,7 +268,7 @@ fcntl_ioctl_impl(PyObject *module, int fd, unsigned int code, /*[clinic input] fcntl.flock - fd: object(type='int', converter='conv_descriptor') + fd: fildes operation as code: int / @@ -292,7 +280,7 @@ function is emulated using fcntl()). static PyObject * fcntl_flock_impl(PyObject *module, int fd, int code) -/*[clinic end generated code: output=84059e2b37d2fc64 input=b70a0a41ca22a8a0]*/ +/*[clinic end generated code: output=84059e2b37d2fc64 input=0bfc00f795953452]*/ { int ret; int async_err = 0; @@ -346,7 +334,7 @@ fcntl_flock_impl(PyObject *module, int fd, int code) /*[clinic input] fcntl.lockf - fd: object(type='int', converter='conv_descriptor') + fd: fildes cmd as code: int len as lenobj: object(c_default='NULL') = 0 start as startobj: object(c_default='NULL') = 0 @@ -380,7 +368,7 @@ starts. `whence` is as with fileobj.seek(), specifically: static PyObject * fcntl_lockf_impl(PyObject *module, int fd, int code, PyObject *lenobj, PyObject *startobj, int whence) -/*[clinic end generated code: output=4985e7a172e7461a input=3a5dc01b04371f1a]*/ +/*[clinic end generated code: output=4985e7a172e7461a input=5480479fc63a04b8]*/ { int ret; int async_err = 0; @@ -577,6 +565,14 @@ all_ins(PyObject* m) if (PyModule_AddIntMacro(m, F_SHLCK)) return -1; #endif +/* Linux specifics */ +#ifdef F_SETPIPE_SZ + if (PyModule_AddIntMacro(m, F_SETPIPE_SZ)) return -1; +#endif +#ifdef F_GETPIPE_SZ + if (PyModule_AddIntMacro(m, F_GETPIPE_SZ)) return -1; +#endif + /* OS X specifics */ #ifdef F_FULLFSYNC if (PyModule_AddIntMacro(m, F_FULLFSYNC)) return -1; @@ -662,34 +658,31 @@ all_ins(PyObject* m) return 0; } +static int +fcntl_exec(PyObject *module) +{ + if (all_ins(module) < 0) { + return -1; + } + return 0; +} + +static PyModuleDef_Slot fcntl_slots[] = { + {Py_mod_exec, fcntl_exec}, + {0, NULL} +}; static struct PyModuleDef fcntlmodule = { PyModuleDef_HEAD_INIT, - "fcntl", - module_doc, - -1, - fcntl_methods, - NULL, - NULL, - NULL, - NULL + .m_name = "fcntl", + .m_doc = module_doc, + .m_size = 0, + .m_methods = fcntl_methods, + .m_slots = fcntl_slots, }; PyMODINIT_FUNC PyInit_fcntl(void) { - PyObject *m; - - /* Create the module and add the functions and documentation */ - m = PyModule_Create(&fcntlmodule); - if (m == NULL) - return NULL; - - /* Add some symbolic constants to the module */ - if (all_ins(m) < 0) { - Py_DECREF(m); - return NULL; - } - - return m; + return PyModuleDef_Init(&fcntlmodule); } diff --git a/contrib/tools/python3/src/Modules/gcmodule.c b/contrib/tools/python3/src/Modules/gcmodule.c index 3cf1a00b00..805a159d53 100644 --- a/contrib/tools/python3/src/Modules/gcmodule.c +++ b/contrib/tools/python3/src/Modules/gcmodule.c @@ -31,7 +31,6 @@ #include "pycore_pyerrors.h" #include "pycore_pystate.h" // _PyThreadState_GET() #include "pydtrace.h" -#include "pytime.h" // _PyTime_GetMonotonicClock() typedef struct _gc_runtime_state GCState; @@ -128,6 +127,15 @@ gc_decref(PyGC_Head *g) #define GEN_HEAD(gcstate, n) (&(gcstate)->generations[n].head) + +static GCState * +get_gc_state(void) +{ + PyInterpreterState *interp = _PyInterpreterState_GET(); + return &interp->gc; +} + + void _PyGC_InitState(GCState *gcstate) { @@ -153,15 +161,20 @@ _PyGC_InitState(GCState *gcstate) PyStatus -_PyGC_Init(PyThreadState *tstate) +_PyGC_Init(PyInterpreterState *interp) { - GCState *gcstate = &tstate->interp->gc; + GCState *gcstate = &interp->gc; + + gcstate->garbage = PyList_New(0); if (gcstate->garbage == NULL) { - gcstate->garbage = PyList_New(0); - if (gcstate->garbage == NULL) { - return _PyStatus_NO_MEMORY(); - } + return _PyStatus_NO_MEMORY(); } + + gcstate->callbacks = PyList_New(0); + if (gcstate->callbacks == NULL) { + return _PyStatus_NO_MEMORY(); + } + return _PyStatus_OK(); } @@ -1023,15 +1036,15 @@ delete_garbage(PyThreadState *tstate, GCState *gcstate, * Clearing the free lists may give back memory to the OS earlier. */ static void -clear_freelists(void) +clear_freelists(PyInterpreterState *interp) { - _PyFrame_ClearFreeList(); - _PyTuple_ClearFreeList(); - _PyFloat_ClearFreeList(); - _PyList_ClearFreeList(); - _PyDict_ClearFreeList(); - _PyAsyncGen_ClearFreeLists(); - _PyContext_ClearFreeList(); + _PyFrame_ClearFreeList(interp); + _PyTuple_ClearFreeList(interp); + _PyFloat_ClearFreeList(interp); + _PyList_ClearFreeList(interp); + _PyDict_ClearFreeList(interp); + _PyAsyncGen_ClearFreeLists(interp); + _PyContext_ClearFreeList(interp); } // Show stats for objects in each generations @@ -1043,7 +1056,7 @@ show_stats_each_generations(GCState *gcstate) for (int i = 0; i < NUM_GENERATIONS && pos < sizeof(buf); i++) { pos += PyOS_snprintf(buf+pos, sizeof(buf)-pos, - " %"PY_FORMAT_SIZE_T"d", + " %zd", gc_list_size(GEN_HEAD(gcstate, i))); } @@ -1167,8 +1180,9 @@ handle_resurrected_objects(PyGC_Head *unreachable, PyGC_Head* still_unreachable, /* This is the main function. Read this to understand how the * collection process works. */ static Py_ssize_t -collect(PyThreadState *tstate, int generation, - Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable, int nofail) +gc_collect_main(PyThreadState *tstate, int generation, + Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable, + int nofail) { int i; Py_ssize_t m = 0; /* # objects collected */ @@ -1181,6 +1195,19 @@ collect(PyThreadState *tstate, int generation, _PyTime_t t1 = 0; /* initialize to prevent a compiler warning */ GCState *gcstate = &tstate->interp->gc; + // gc_collect_main() must not be called before _PyGC_Init + // or after _PyGC_Fini() + assert(gcstate->garbage != NULL); + assert(!_PyErr_Occurred(tstate)); + +#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS + if (tstate->interp->config._isolated_interpreter) { + // bpo-40533: The garbage collector must not be run on parallel on + // Python objects shared by multiple interpreters. + return 0; + } +#endif + if (gcstate->debug & DEBUG_STATS) { PySys_WriteStderr("gc: collecting generation %d...\n", generation); show_stats_each_generations(gcstate); @@ -1282,8 +1309,7 @@ collect(PyThreadState *tstate, int generation, if (gcstate->debug & DEBUG_STATS) { double d = _PyTime_AsSecondsDouble(_PyTime_GetMonotonicClock() - t1); PySys_WriteStderr( - "gc: done, %" PY_FORMAT_SIZE_T "d unreachable, " - "%" PY_FORMAT_SIZE_T "d uncollectable, %.4fs elapsed\n", + "gc: done, %zd unreachable, %zd uncollectable, %.4fs elapsed\n", n+m, n, d); } @@ -1297,7 +1323,7 @@ collect(PyThreadState *tstate, int generation, /* Clear free list only during the collection of the highest * generation */ if (generation == NUM_GENERATIONS-1) { - clear_freelists(); + clear_freelists(tstate->interp); } if (_PyErr_Occurred(tstate)) { @@ -1379,19 +1405,19 @@ invoke_gc_callback(PyThreadState *tstate, const char *phase, * progress callbacks. */ static Py_ssize_t -collect_with_callback(PyThreadState *tstate, int generation) +gc_collect_with_callback(PyThreadState *tstate, int generation) { assert(!_PyErr_Occurred(tstate)); Py_ssize_t result, collected, uncollectable; invoke_gc_callback(tstate, "start", generation, 0, 0); - result = collect(tstate, generation, &collected, &uncollectable, 0); + result = gc_collect_main(tstate, generation, &collected, &uncollectable, 0); invoke_gc_callback(tstate, "stop", generation, collected, uncollectable); assert(!_PyErr_Occurred(tstate)); return result; } static Py_ssize_t -collect_generations(PyThreadState *tstate) +gc_collect_generations(PyThreadState *tstate) { GCState *gcstate = &tstate->interp->gc; /* Find the oldest generation (highest numbered) where the count @@ -1439,7 +1465,7 @@ collect_generations(PyThreadState *tstate) if (i == NUM_GENERATIONS - 1 && gcstate->long_lived_pending < gcstate->long_lived_total / 4) continue; - n = collect_with_callback(tstate, i); + n = gc_collect_with_callback(tstate, i); break; } } @@ -1458,9 +1484,7 @@ static PyObject * gc_enable_impl(PyObject *module) /*[clinic end generated code: output=45a427e9dce9155c input=81ac4940ca579707]*/ { - PyThreadState *tstate = _PyThreadState_GET(); - GCState *gcstate = &tstate->interp->gc; - gcstate->enabled = 1; + PyGC_Enable(); Py_RETURN_NONE; } @@ -1474,9 +1498,7 @@ static PyObject * gc_disable_impl(PyObject *module) /*[clinic end generated code: output=97d1030f7aa9d279 input=8c2e5a14e800d83b]*/ { - PyThreadState *tstate = _PyThreadState_GET(); - GCState *gcstate = &tstate->interp->gc; - gcstate->enabled = 0; + PyGC_Disable(); Py_RETURN_NONE; } @@ -1490,9 +1512,7 @@ static int gc_isenabled_impl(PyObject *module) /*[clinic end generated code: output=1874298331c49130 input=30005e0422373b31]*/ { - PyThreadState *tstate = _PyThreadState_GET(); - GCState *gcstate = &tstate->interp->gc; - return gcstate->enabled; + return PyGC_IsEnabled(); } /*[clinic input] @@ -1528,7 +1548,7 @@ gc_collect_impl(PyObject *module, int generation) } else { gcstate->collecting = 1; - n = collect_with_callback(tstate, generation); + n = gc_collect_with_callback(tstate, generation); gcstate->collecting = 0; } return n; @@ -1556,8 +1576,7 @@ static PyObject * gc_set_debug_impl(PyObject *module, int flags) /*[clinic end generated code: output=7c8366575486b228 input=5e5ce15e84fbed15]*/ { - PyThreadState *tstate = _PyThreadState_GET(); - GCState *gcstate = &tstate->interp->gc; + GCState *gcstate = get_gc_state(); gcstate->debug = flags; Py_RETURN_NONE; } @@ -1572,8 +1591,7 @@ static int gc_get_debug_impl(PyObject *module) /*[clinic end generated code: output=91242f3506cd1e50 input=91a101e1c3b98366]*/ { - PyThreadState *tstate = _PyThreadState_GET(); - GCState *gcstate = &tstate->interp->gc; + GCState *gcstate = get_gc_state(); return gcstate->debug; } @@ -1586,8 +1604,7 @@ PyDoc_STRVAR(gc_set_thresh__doc__, static PyObject * gc_set_threshold(PyObject *self, PyObject *args) { - PyThreadState *tstate = _PyThreadState_GET(); - GCState *gcstate = &tstate->interp->gc; + GCState *gcstate = get_gc_state(); if (!PyArg_ParseTuple(args, "i|ii:set_threshold", &gcstate->generations[0].threshold, &gcstate->generations[1].threshold, @@ -1610,8 +1627,7 @@ static PyObject * gc_get_threshold_impl(PyObject *module) /*[clinic end generated code: output=7902bc9f41ecbbd8 input=286d79918034d6e6]*/ { - PyThreadState *tstate = _PyThreadState_GET(); - GCState *gcstate = &tstate->interp->gc; + GCState *gcstate = get_gc_state(); return Py_BuildValue("(iii)", gcstate->generations[0].threshold, gcstate->generations[1].threshold, @@ -1628,8 +1644,7 @@ static PyObject * gc_get_count_impl(PyObject *module) /*[clinic end generated code: output=354012e67b16398f input=a392794a08251751]*/ { - PyThreadState *tstate = _PyThreadState_GET(); - GCState *gcstate = &tstate->interp->gc; + GCState *gcstate = get_gc_state(); return Py_BuildValue("(iii)", gcstate->generations[0].count, gcstate->generations[1].count, @@ -1672,9 +1687,6 @@ Return the list of objects that directly refer to any of objs."); static PyObject * gc_get_referrers(PyObject *self, PyObject *args) { - PyThreadState *tstate = _PyThreadState_GET(); - int i; - if (PySys_Audit("gc.get_referrers", "(O)", args) < 0) { return NULL; } @@ -1684,8 +1696,8 @@ gc_get_referrers(PyObject *self, PyObject *args) return NULL; } - GCState *gcstate = &tstate->interp->gc; - for (i = 0; i < NUM_GENERATIONS; i++) { + GCState *gcstate = get_gc_state(); + for (int i = 0; i < NUM_GENERATIONS; i++) { if (!(gc_referrers_for(args, GEN_HEAD(gcstate, i), result))) { Py_DECREF(result); return NULL; @@ -1811,11 +1823,10 @@ gc_get_stats_impl(PyObject *module) { int i; struct gc_generation_stats stats[NUM_GENERATIONS], *st; - PyThreadState *tstate = _PyThreadState_GET(); /* To get consistent values despite allocations while constructing the result list, we use a snapshot of the running stats. */ - GCState *gcstate = &tstate->interp->gc; + GCState *gcstate = get_gc_state(); for (i = 0; i < NUM_GENERATIONS; i++) { stats[i] = gcstate->generation_stats[i]; } @@ -1906,8 +1917,7 @@ static PyObject * gc_freeze_impl(PyObject *module) /*[clinic end generated code: output=502159d9cdc4c139 input=b602b16ac5febbe5]*/ { - PyThreadState *tstate = _PyThreadState_GET(); - GCState *gcstate = &tstate->interp->gc; + GCState *gcstate = get_gc_state(); for (int i = 0; i < NUM_GENERATIONS; ++i) { gc_list_merge(GEN_HEAD(gcstate, i), &gcstate->permanent_generation.head); gcstate->generations[i].count = 0; @@ -1927,8 +1937,7 @@ static PyObject * gc_unfreeze_impl(PyObject *module) /*[clinic end generated code: output=1c15f2043b25e169 input=2dd52b170f4cef6c]*/ { - PyThreadState *tstate = _PyThreadState_GET(); - GCState *gcstate = &tstate->interp->gc; + GCState *gcstate = get_gc_state(); gc_list_merge(&gcstate->permanent_generation.head, GEN_HEAD(gcstate, NUM_GENERATIONS-1)); Py_RETURN_NONE; @@ -1944,8 +1953,7 @@ static Py_ssize_t gc_get_freeze_count_impl(PyObject *module) /*[clinic end generated code: output=61cbd9f43aa032e1 input=45ffbc65cfe2a6ed]*/ { - PyThreadState *tstate = _PyThreadState_GET(); - GCState *gcstate = &tstate->interp->gc; + GCState *gcstate = get_gc_state(); return gc_list_size(&gcstate->permanent_generation.head); } @@ -1996,63 +2004,79 @@ static PyMethodDef GcMethods[] = { {NULL, NULL} /* Sentinel */ }; -static struct PyModuleDef gcmodule = { - PyModuleDef_HEAD_INIT, - "gc", /* m_name */ - gc__doc__, /* m_doc */ - -1, /* m_size */ - GcMethods, /* m_methods */ - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL /* m_free */ -}; - -PyMODINIT_FUNC -PyInit_gc(void) +static int +gcmodule_exec(PyObject *module) { - PyThreadState *tstate = _PyThreadState_GET(); - GCState *gcstate = &tstate->interp->gc; - - PyObject *m = PyModule_Create(&gcmodule); - - if (m == NULL) { - return NULL; - } + GCState *gcstate = get_gc_state(); - if (gcstate->garbage == NULL) { - gcstate->garbage = PyList_New(0); - if (gcstate->garbage == NULL) { - return NULL; - } - } - Py_INCREF(gcstate->garbage); - if (PyModule_AddObject(m, "garbage", gcstate->garbage) < 0) { - return NULL; - } - - if (gcstate->callbacks == NULL) { - gcstate->callbacks = PyList_New(0); - if (gcstate->callbacks == NULL) { - return NULL; - } + /* garbage and callbacks are initialized by _PyGC_Init() early in + * interpreter lifecycle. */ + assert(gcstate->garbage != NULL); + if (PyModule_AddObjectRef(module, "garbage", gcstate->garbage) < 0) { + return -1; } - Py_INCREF(gcstate->callbacks); - if (PyModule_AddObject(m, "callbacks", gcstate->callbacks) < 0) { - return NULL; + assert(gcstate->callbacks != NULL); + if (PyModule_AddObjectRef(module, "callbacks", gcstate->callbacks) < 0) { + return -1; } -#define ADD_INT(NAME) if (PyModule_AddIntConstant(m, #NAME, NAME) < 0) { return NULL; } +#define ADD_INT(NAME) if (PyModule_AddIntConstant(module, #NAME, NAME) < 0) { return -1; } ADD_INT(DEBUG_STATS); ADD_INT(DEBUG_COLLECTABLE); ADD_INT(DEBUG_UNCOLLECTABLE); ADD_INT(DEBUG_SAVEALL); ADD_INT(DEBUG_LEAK); #undef ADD_INT - return m; + return 0; +} + +static PyModuleDef_Slot gcmodule_slots[] = { + {Py_mod_exec, gcmodule_exec}, + {0, NULL} +}; + +static struct PyModuleDef gcmodule = { + PyModuleDef_HEAD_INIT, + .m_name = "gc", + .m_doc = gc__doc__, + .m_size = 0, // per interpreter state, see: get_gc_state() + .m_methods = GcMethods, + .m_slots = gcmodule_slots +}; + +PyMODINIT_FUNC +PyInit_gc(void) +{ + return PyModuleDef_Init(&gcmodule); +} + +/* C API for controlling the state of the garbage collector */ +int +PyGC_Enable(void) +{ + GCState *gcstate = get_gc_state(); + int old_state = gcstate->enabled; + gcstate->enabled = 1; + return old_state; +} + +int +PyGC_Disable(void) +{ + GCState *gcstate = get_gc_state(); + int old_state = gcstate->enabled; + gcstate->enabled = 0; + return old_state; } -/* API to invoke gc.collect() from C */ +int +PyGC_IsEnabled(void) +{ + GCState *gcstate = get_gc_state(); + return gcstate->enabled; +} + +/* Public API to invoke gc.collect() from C */ Py_ssize_t PyGC_Collect(void) { @@ -2072,7 +2096,7 @@ PyGC_Collect(void) PyObject *exc, *value, *tb; gcstate->collecting = 1; _PyErr_Fetch(tstate, &exc, &value, &tb); - n = collect_with_callback(tstate, NUM_GENERATIONS - 1); + n = gc_collect_with_callback(tstate, NUM_GENERATIONS - 1); _PyErr_Restore(tstate, exc, value, tb); gcstate->collecting = 0; } @@ -2081,41 +2105,30 @@ PyGC_Collect(void) } Py_ssize_t -_PyGC_CollectIfEnabled(void) +_PyGC_CollectNoFail(PyThreadState *tstate) { - return PyGC_Collect(); -} - -Py_ssize_t -_PyGC_CollectNoFail(void) -{ - PyThreadState *tstate = _PyThreadState_GET(); - assert(!_PyErr_Occurred(tstate)); - - GCState *gcstate = &tstate->interp->gc; - Py_ssize_t n; - /* Ideally, this function is only called on interpreter shutdown, and therefore not recursively. Unfortunately, when there are daemon threads, a daemon thread can start a cyclic garbage collection during interpreter shutdown (and then never finish it). See http://bugs.python.org/issue8713#msg195178 for an example. */ + GCState *gcstate = &tstate->interp->gc; if (gcstate->collecting) { - n = 0; - } - else { - gcstate->collecting = 1; - n = collect(tstate, NUM_GENERATIONS - 1, NULL, NULL, 1); - gcstate->collecting = 0; + return 0; } + + Py_ssize_t n; + gcstate->collecting = 1; + n = gc_collect_main(tstate, NUM_GENERATIONS - 1, NULL, NULL, 1); + gcstate->collecting = 0; return n; } void -_PyGC_DumpShutdownStats(PyThreadState *tstate) +_PyGC_DumpShutdownStats(PyInterpreterState *interp) { - GCState *gcstate = &tstate->interp->gc; + GCState *gcstate = &interp->gc; if (!(gcstate->debug & DEBUG_SAVEALL) && gcstate->garbage != NULL && PyList_GET_SIZE(gcstate->garbage) > 0) { const char *message; @@ -2162,13 +2175,13 @@ gc_fini_untrack(PyGC_Head *list) void -_PyGC_Fini(PyThreadState *tstate) +_PyGC_Fini(PyInterpreterState *interp) { - GCState *gcstate = &tstate->interp->gc; + GCState *gcstate = &interp->gc; Py_CLEAR(gcstate->garbage); Py_CLEAR(gcstate->callbacks); - if (!_Py_IsMainInterpreter(tstate)) { + if (!_Py_IsMainInterpreter(interp)) { // bpo-46070: Explicitly untrack all objects currently tracked by the // GC. Otherwise, if an object is used later by another interpreter, // calling PyObject_GC_UnTrack() on the object crashs if the previous @@ -2275,7 +2288,7 @@ _PyObject_GC_Alloc(int use_calloc, size_t basicsize) !_PyErr_Occurred(tstate)) { gcstate->collecting = 1; - collect_generations(tstate); + gc_collect_generations(tstate); gcstate->collecting = 0; } PyObject *op = FROM_GC(g); @@ -2298,8 +2311,10 @@ PyObject * _PyObject_GC_New(PyTypeObject *tp) { PyObject *op = _PyObject_GC_Malloc(_PyObject_SIZE(tp)); - if (op != NULL) - op = PyObject_INIT(op, tp); + if (op == NULL) { + return NULL; + } + _PyObject_Init(op, tp); return op; } @@ -2315,8 +2330,10 @@ _PyObject_GC_NewVar(PyTypeObject *tp, Py_ssize_t nitems) } size = _PyObject_VAR_SIZE(tp, nitems); op = (PyVarObject *) _PyObject_GC_Malloc(size); - if (op != NULL) - op = PyObject_INIT_VAR(op, tp, nitems); + if (op == NULL) { + return NULL; + } + _PyObject_InitVar(op, tp, nitems); return op; } @@ -2330,7 +2347,7 @@ _PyObject_GC_Resize(PyVarObject *op, Py_ssize_t nitems) } PyGC_Head *g = AS_GC(op); - g = (PyGC_Head *)PyObject_REALLOC(g, sizeof(PyGC_Head) + basicsize); + g = (PyGC_Head *)PyObject_Realloc(g, sizeof(PyGC_Head) + basicsize); if (g == NULL) return (PyVarObject *)PyErr_NoMemory(); op = (PyVarObject *) FROM_GC(g); @@ -2345,12 +2362,11 @@ PyObject_GC_Del(void *op) if (_PyObject_GC_IS_TRACKED(op)) { gc_list_remove(g); } - PyThreadState *tstate = _PyThreadState_GET(); - GCState *gcstate = &tstate->interp->gc; + GCState *gcstate = get_gc_state(); if (gcstate->generations[0].count > 0) { gcstate->generations[0].count--; } - PyObject_FREE(g); + PyObject_Free(g); } int diff --git a/contrib/tools/python3/src/Modules/getpath.c b/contrib/tools/python3/src/Modules/getpath.c index 5014dde930..519a7d5424 100644 --- a/contrib/tools/python3/src/Modules/getpath.c +++ b/contrib/tools/python3/src/Modules/getpath.c @@ -1325,11 +1325,6 @@ calculate_zip_path(PyCalculatePath *calculate) goto done; } - /* Replace "00" with version */ - size_t len = wcslen(calculate->zip_path); - calculate->zip_path[len - 6] = VERSION[0]; - calculate->zip_path[len - 5] = VERSION[2]; - res = _PyStatus_OK(); done: diff --git a/contrib/tools/python3/src/Modules/grpmodule.c b/contrib/tools/python3/src/Modules/grpmodule.c index cdb3ae859b..f6298ca0ee 100644 --- a/contrib/tools/python3/src/Modules/grpmodule.c +++ b/contrib/tools/python3/src/Modules/grpmodule.c @@ -46,20 +46,19 @@ get_grp_state(PyObject *module) return (grpmodulestate *)state; } -#define modulestate_global get_grp_state(PyState_FindModule(&grpmodule)) - static struct PyModuleDef grpmodule; #define DEFAULT_BUFFER_SIZE 1024 static PyObject * -mkgrent(struct group *p) +mkgrent(PyObject *module, struct group *p) { int setIndex = 0; PyObject *v, *w; char **member; - if ((v = PyStructSequence_New(modulestate_global->StructGrpType)) == NULL) + v = PyStructSequence_New(get_grp_state(module)->StructGrpType); + if (v == NULL) return NULL; if ((w = PyList_New(0)) == NULL) { @@ -111,30 +110,14 @@ static PyObject * grp_getgrgid_impl(PyObject *module, PyObject *id) /*[clinic end generated code: output=30797c289504a1ba input=15fa0e2ccf5cda25]*/ { - PyObject *py_int_id, *retval = NULL; + PyObject *retval = NULL; int nomem = 0; char *buf = NULL, *buf2 = NULL; gid_t gid; struct group *p; if (!_Py_Gid_Converter(id, &gid)) { - if (!PyErr_ExceptionMatches(PyExc_TypeError)) { - return NULL; - } - PyErr_Clear(); - if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, - "group id must be int, not %.200", - Py_TYPE(id)->tp_name) < 0) { - return NULL; - } - py_int_id = PyNumber_Long(id); - if (!py_int_id) - return NULL; - if (!_Py_Gid_Converter(py_int_id, &gid)) { - Py_DECREF(py_int_id); - return NULL; - } - Py_DECREF(py_int_id); + return NULL; } #ifdef HAVE_GETGRGID_R int status; @@ -186,7 +169,7 @@ grp_getgrgid_impl(PyObject *module, PyObject *id) Py_DECREF(gid_obj); return NULL; } - retval = mkgrent(p); + retval = mkgrent(module, p); #ifdef HAVE_GETGRGID_R PyMem_RawFree(buf); #endif @@ -264,7 +247,7 @@ grp_getgrnam_impl(PyObject *module, PyObject *name) } goto out; } - retval = mkgrent(p); + retval = mkgrent(module, p); out: PyMem_RawFree(buf); Py_DECREF(bytes); @@ -291,7 +274,7 @@ grp_getgrall_impl(PyObject *module) return NULL; setgrent(); while ((p = getgrent()) != NULL) { - PyObject *v = mkgrent(p); + PyObject *v = mkgrent(module, p); if (v == NULL || PyList_Append(d, v) != 0) { Py_XDECREF(v); Py_DECREF(d); @@ -327,6 +310,26 @@ users are not explicitly listed as members of the groups they are in\n\ according to the password database. Check both databases to get\n\ complete membership information.)"); +static int +grpmodule_exec(PyObject *module) +{ + grpmodulestate *state = get_grp_state(module); + + state->StructGrpType = PyStructSequence_NewType(&struct_group_type_desc); + if (state->StructGrpType == NULL) { + return -1; + } + if (PyModule_AddType(module, state->StructGrpType) < 0) { + return -1; + } + return 0; +} + +static PyModuleDef_Slot grpmodule_slots[] = { + {Py_mod_exec, grpmodule_exec}, + {0, NULL} +}; + static int grpmodule_traverse(PyObject *m, visitproc visit, void *arg) { Py_VISIT(get_grp_state(m)->StructGrpType); return 0; @@ -342,37 +345,19 @@ static void grpmodule_free(void *m) { } static struct PyModuleDef grpmodule = { - PyModuleDef_HEAD_INIT, - "grp", - grp__doc__, - sizeof(grpmodulestate), - grp_methods, - NULL, - grpmodule_traverse, - grpmodule_clear, - grpmodule_free, + PyModuleDef_HEAD_INIT, + .m_name = "grp", + .m_doc = grp__doc__, + .m_size = sizeof(grpmodulestate), + .m_methods = grp_methods, + .m_slots = grpmodule_slots, + .m_traverse = grpmodule_traverse, + .m_clear = grpmodule_clear, + .m_free = grpmodule_free, }; PyMODINIT_FUNC PyInit_grp(void) { - PyObject *m; - if ((m = PyState_FindModule(&grpmodule)) != NULL) { - Py_INCREF(m); - return m; - } - - if ((m = PyModule_Create(&grpmodule)) == NULL) { - return NULL; - } - - grpmodulestate *state = PyModule_GetState(m); - state->StructGrpType = PyStructSequence_NewType(&struct_group_type_desc); - if (state->StructGrpType == NULL) { - return NULL; - } - - Py_INCREF(state->StructGrpType); - PyModule_AddObject(m, "struct_group", (PyObject *) state->StructGrpType); - return m; + return PyModuleDef_Init(&grpmodule); } diff --git a/contrib/tools/python3/src/Modules/itertoolsmodule.c b/contrib/tools/python3/src/Modules/itertoolsmodule.c index fae5560ab7..f8e2c45aec 100644 --- a/contrib/tools/python3/src/Modules/itertoolsmodule.c +++ b/contrib/tools/python3/src/Modules/itertoolsmodule.c @@ -1,8 +1,10 @@ + #define PY_SSIZE_T_CLEAN #include "Python.h" -#include "pycore_tupleobject.h" +#include "pycore_long.h" // _PyLong_GetZero() #include "pycore_object.h" // _PyObject_GC_TRACK() +#include "pycore_tuple.h" // _PyTuple_ITEMS() #include <stddef.h> // offsetof() /* Itertools module written and maintained @@ -27,8 +29,9 @@ class itertools.accumulate "accumulateobject *" "&accumulate_type" class itertools.compress "compressobject *" "&compress_type" class itertools.filterfalse "filterfalseobject *" "&filterfalse_type" class itertools.count "countobject *" "&count_type" +class itertools.pairwise "pairwiseobject *" "&pairwise_type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ea05c93c6d94726a]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=6498ed21fbe1bf94]*/ static PyTypeObject groupby_type; static PyTypeObject _grouper_type; @@ -45,9 +48,140 @@ static PyTypeObject accumulate_type; static PyTypeObject compress_type; static PyTypeObject filterfalse_type; static PyTypeObject count_type; +static PyTypeObject pairwise_type; #include "clinic/itertoolsmodule.c.h" +/* pairwise object ***********************************************************/ + +typedef struct { + PyObject_HEAD + PyObject *it; + PyObject *old; +} pairwiseobject; + +/*[clinic input] +@classmethod +itertools.pairwise.__new__ as pairwise_new + iterable: object + / +Return an iterator of overlapping pairs taken from the input iterator. + + s -> (s0,s1), (s1,s2), (s2, s3), ... + +[clinic start generated code]*/ + +static PyObject * +pairwise_new_impl(PyTypeObject *type, PyObject *iterable) +/*[clinic end generated code: output=9f0267062d384456 input=6e7c3cddb431a8d6]*/ +{ + PyObject *it; + pairwiseobject *po; + + it = PyObject_GetIter(iterable); + if (it == NULL) { + return NULL; + } + po = (pairwiseobject *)type->tp_alloc(type, 0); + if (po == NULL) { + Py_DECREF(it); + return NULL; + } + po->it = it; + po->old = NULL; + return (PyObject *)po; +} + +static void +pairwise_dealloc(pairwiseobject *po) +{ + PyObject_GC_UnTrack(po); + Py_XDECREF(po->it); + Py_XDECREF(po->old); + Py_TYPE(po)->tp_free(po); +} + +static int +pairwise_traverse(pairwiseobject *po, visitproc visit, void *arg) +{ + Py_VISIT(po->it); + Py_VISIT(po->old); + return 0; +} + +static PyObject * +pairwise_next(pairwiseobject *po) +{ + PyObject *it = po->it; + PyObject *old = po->old; + PyObject *new, *result; + + if (it == NULL) { + return NULL; + } + if (old == NULL) { + po->old = old = (*Py_TYPE(it)->tp_iternext)(it); + if (old == NULL) { + Py_CLEAR(po->it); + return NULL; + } + } + new = (*Py_TYPE(it)->tp_iternext)(it); + if (new == NULL) { + Py_CLEAR(po->it); + Py_CLEAR(po->old); + return NULL; + } + /* Future optimization: Reuse the result tuple as we do in enumerate() */ + result = PyTuple_Pack(2, old, new); + Py_SETREF(po->old, new); + return result; +} + +static PyTypeObject pairwise_type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "itertools.pairwise", /* tp_name */ + sizeof(pairwiseobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)pairwise_dealloc, /* tp_dealloc */ + 0, /* tp_vectorcall_offset */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_as_async */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_BASETYPE, /* tp_flags */ + pairwise_new__doc__, /* tp_doc */ + (traverseproc)pairwise_traverse, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)pairwise_next, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + pairwise_new, /* tp_new */ + PyObject_GC_Del, /* tp_free */ +}; + /* groupby object ************************************************************/ @@ -1001,8 +1135,7 @@ cycle_dealloc(cycleobject *lz) static int cycle_traverse(cycleobject *lz, visitproc visit, void *arg) { - if (lz->it) - Py_VISIT(lz->it); + Py_VISIT(lz->it); Py_VISIT(lz->saved); return 0; } @@ -4063,13 +4196,14 @@ itertools_count_impl(PyTypeObject *type, PyObject *long_cnt, } } else { cnt = 0; - long_cnt = _PyLong_Zero; + long_cnt = _PyLong_GetZero(); } Py_INCREF(long_cnt); /* If not specified, step defaults to 1 */ - if (long_step == NULL) - long_step = _PyLong_One; + if (long_step == NULL) { + long_step = _PyLong_GetOne(); + } Py_INCREF(long_step); assert(long_cnt != NULL && long_step != NULL); @@ -4692,6 +4826,7 @@ groupby(iterable[, keyfunc]) --> sub-iterators grouped by value of keyfunc(v)\n\ filterfalse(pred, seq) --> elements of seq where pred(elem) is False\n\ islice(seq, [start,] stop [, step]) --> elements from\n\ seq[start:stop:step]\n\ +pairwise(s) --> (s[0],s[1]), (s[1],s[2]), (s[2], s[3]), ...\n\ starmap(fun, seq) --> fun(*seq[0]), fun(*seq[1]), ...\n\ tee(it, n=2) --> (it1, it2 , ... itn) splits one iterator into n\n\ takewhile(pred, seq) --> seq[0], seq[1], until pred fails\n\ @@ -4721,6 +4856,7 @@ itertoolsmodule_exec(PyObject *m) &filterfalse_type, &count_type, &ziplongest_type, + &pairwise_type, &permutations_type, &product_type, &repeat_type, diff --git a/contrib/tools/python3/src/Modules/main.c b/contrib/tools/python3/src/Modules/main.c index 1eec0f96c0..1ae2b34cac 100644 --- a/contrib/tools/python3/src/Modules/main.c +++ b/contrib/tools/python3/src/Modules/main.c @@ -88,7 +88,7 @@ static inline int config_run_code(const PyConfig *config) } -/* Return non-zero is stdin is a TTY or if -i command line option is used */ +/* Return non-zero if stdin is a TTY or if -i command line option is used */ static int stdin_is_interactive(const PyConfig *config) { @@ -224,7 +224,7 @@ pymain_import_readline(const PyConfig *config) static int -pymain_run_command(wchar_t *command, PyCompilerFlags *cf) +pymain_run_command(wchar_t *command) { PyObject *unicode, *bytes; int ret; @@ -244,7 +244,9 @@ pymain_run_command(wchar_t *command, PyCompilerFlags *cf) goto error; } - ret = PyRun_SimpleStringFlags(PyBytes_AsString(bytes), cf); + PyCompilerFlags cf = _PyCompilerFlags_INIT; + cf.cf_flags |= PyCF_IGNORE_COOKIE; + ret = PyRun_SimpleStringFlags(PyBytes_AsString(bytes), &cf); Py_DECREF(bytes); return (ret != 0); @@ -306,29 +308,23 @@ pymain_run_module(const wchar_t *modname, int set_argv0) static int -pymain_run_file(const PyConfig *config, PyCompilerFlags *cf) +pymain_run_file_obj(PyObject *program_name, PyObject *filename, + int skip_source_first_line) { - const wchar_t *filename = config->run_filename; - if (PySys_Audit("cpython.run_file", "u", filename) < 0) { + if (PySys_Audit("cpython.run_file", "O", filename) < 0) { return pymain_exit_err_print(); } - FILE *fp = _Py_wfopen(filename, L"rb"); + + FILE *fp = _Py_fopen_obj(filename, "rb"); if (fp == NULL) { - char *cfilename_buffer; - const char *cfilename; - int err = errno; - cfilename_buffer = _Py_EncodeLocaleRaw(filename, NULL); - if (cfilename_buffer != NULL) - cfilename = cfilename_buffer; - else - cfilename = "<unprintable file name>"; - fprintf(stderr, "%ls: can't open file '%s': [Errno %d] %s\n", - config->program_name, cfilename, err, strerror(err)); - PyMem_RawFree(cfilename_buffer); + // Ignore the OSError + PyErr_Clear(); + PySys_FormatStderr("%S: can't open file %R: [Errno %d] %s\n", + program_name, filename, errno, strerror(errno)); return 2; } - if (config->skip_source_first_line) { + if (skip_source_first_line) { int ch; /* Push back first newline so line numbers remain the same */ while ((ch = getc(fp)) != EOF) { @@ -341,104 +337,97 @@ pymain_run_file(const PyConfig *config, PyCompilerFlags *cf) struct _Py_stat_struct sb; if (_Py_fstat_noraise(fileno(fp), &sb) == 0 && S_ISDIR(sb.st_mode)) { - fprintf(stderr, - "%ls: '%ls' is a directory, cannot continue\n", - config->program_name, filename); + PySys_FormatStderr("%S: %R is a directory, cannot continue\n", + program_name, filename); fclose(fp); return 1; } - /* call pending calls like signal handlers (SIGINT) */ + // Call pending calls like signal handlers (SIGINT) if (Py_MakePendingCalls() == -1) { fclose(fp); return pymain_exit_err_print(); } - PyObject *unicode, *bytes = NULL; - const char *filename_str; + /* PyRun_AnyFileExFlags(closeit=1) calls fclose(fp) before running code */ + PyCompilerFlags cf = _PyCompilerFlags_INIT; + int run = _PyRun_AnyFileObject(fp, filename, 1, &cf); + return (run != 0); +} - unicode = PyUnicode_FromWideChar(filename, wcslen(filename)); - if (unicode != NULL) { - bytes = PyUnicode_EncodeFSDefault(unicode); - Py_DECREF(unicode); - } - if (bytes != NULL) { - filename_str = PyBytes_AsString(bytes); +static int +pymain_run_file(const PyConfig *config) +{ + PyObject *filename = PyUnicode_FromWideChar(config->run_filename, -1); + if (filename == NULL) { + PyErr_Print(); + return -1; } - else { - PyErr_Clear(); - filename_str = "<filename encoding error>"; + PyObject *program_name = PyUnicode_FromWideChar(config->program_name, -1); + if (program_name == NULL) { + Py_DECREF(filename); + PyErr_Print(); + return -1; } - /* PyRun_AnyFileExFlags(closeit=1) calls fclose(fp) before running code */ - int run = PyRun_AnyFileExFlags(fp, filename_str, 1, cf); - Py_XDECREF(bytes); - return (run != 0); + int res = pymain_run_file_obj(program_name, filename, + config->skip_source_first_line); + Py_DECREF(filename); + Py_DECREF(program_name); + return res; } static int -pymain_run_startup(PyConfig *config, PyCompilerFlags *cf, int *exitcode) +pymain_run_startup(PyConfig *config, int *exitcode) { int ret; - PyObject *startup_obj = NULL; if (!config->use_environment) { return 0; } + PyObject *startup = NULL; #ifdef MS_WINDOWS - const wchar_t *wstartup = _wgetenv(L"PYTHONSTARTUP"); - if (wstartup == NULL || wstartup[0] == L'\0') { + const wchar_t *env = _wgetenv(L"PYTHONSTARTUP"); + if (env == NULL || env[0] == L'\0') { return 0; } - PyObject *startup_bytes = NULL; - startup_obj = PyUnicode_FromWideChar(wstartup, wcslen(wstartup)); - if (startup_obj == NULL) { - goto error; - } - startup_bytes = PyUnicode_EncodeFSDefault(startup_obj); - if (startup_bytes == NULL) { + startup = PyUnicode_FromWideChar(env, wcslen(env)); + if (startup == NULL) { goto error; } - const char *startup = PyBytes_AS_STRING(startup_bytes); #else - const char *startup = _Py_GetEnv(config->use_environment, "PYTHONSTARTUP"); - if (startup == NULL) { + const char *env = _Py_GetEnv(config->use_environment, "PYTHONSTARTUP"); + if (env == NULL) { return 0; } - startup_obj = PyUnicode_DecodeFSDefault(startup); - if (startup_obj == NULL) { + startup = PyUnicode_DecodeFSDefault(env); + if (startup == NULL) { goto error; } #endif - if (PySys_Audit("cpython.run_startup", "O", startup_obj) < 0) { + if (PySys_Audit("cpython.run_startup", "O", startup) < 0) { goto error; } -#ifdef MS_WINDOWS - FILE *fp = _Py_wfopen(wstartup, L"r"); -#else - FILE *fp = _Py_fopen(startup, "r"); -#endif + FILE *fp = _Py_fopen_obj(startup, "r"); if (fp == NULL) { int save_errno = errno; PyErr_Clear(); PySys_WriteStderr("Could not open PYTHONSTARTUP\n"); errno = save_errno; - PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, startup_obj, NULL); + PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, startup, NULL); goto error; } - (void) PyRun_SimpleFileExFlags(fp, startup, 0, cf); + PyCompilerFlags cf = _PyCompilerFlags_INIT; + (void) _PyRun_SimpleFileObject(fp, startup, 0, &cf); PyErr_Clear(); fclose(fp); ret = 0; done: -#ifdef MS_WINDOWS - Py_XDECREF(startup_bytes); -#endif - Py_XDECREF(startup_obj); + Py_XDECREF(startup); return ret; error: @@ -485,14 +474,14 @@ error: static int -pymain_run_stdin(PyConfig *config, PyCompilerFlags *cf) +pymain_run_stdin(PyConfig *config) { if (stdin_is_interactive(config)) { config->inspect = 0; Py_InspectFlag = 0; /* do exit on SystemExit */ int exitcode; - if (pymain_run_startup(config, cf, &exitcode)) { + if (pymain_run_startup(config, &exitcode)) { return exitcode; } @@ -510,13 +499,14 @@ pymain_run_stdin(PyConfig *config, PyCompilerFlags *cf) return pymain_exit_err_print(); } - int run = PyRun_AnyFileExFlags(stdin, "<stdin>", 0, cf); + PyCompilerFlags cf = _PyCompilerFlags_INIT; + int run = PyRun_AnyFileExFlags(stdin, "<stdin>", 0, &cf); return (run != 0); } static void -pymain_repl(PyConfig *config, PyCompilerFlags *cf, int *exitcode) +pymain_repl(PyConfig *config, int *exitcode) { /* Check this environment variable at the end, to give programs the opportunity to set it from Python. */ @@ -535,7 +525,8 @@ pymain_repl(PyConfig *config, PyCompilerFlags *cf, int *exitcode) return; } - int res = PyRun_AnyFileFlags(stdin, "<stdin>", cf); + PyCompilerFlags cf = _PyCompilerFlags_INIT; + int res = PyRun_AnyFileFlags(stdin, "<stdin>", &cf); *exitcode = (res != 0); } @@ -581,13 +572,11 @@ pymain_run_python(int *exitcode) } } - PyCompilerFlags cf = _PyCompilerFlags_INIT; - pymain_header(config); pymain_import_readline(config); if (config->run_command) { - *exitcode = pymain_run_command(config->run_command, &cf); + *exitcode = pymain_run_command(config->run_command); } else if (config->run_module) { *exitcode = pymain_run_module(config->run_module, 1); @@ -596,13 +585,13 @@ pymain_run_python(int *exitcode) *exitcode = pymain_run_module(L"__main__", 0); } else if (config->run_filename != NULL) { - *exitcode = pymain_run_file(config, &cf); + *exitcode = pymain_run_file(config); } else { - *exitcode = pymain_run_stdin(config, &cf); + *exitcode = pymain_run_stdin(config); } - pymain_repl(config, &cf, exitcode); + pymain_repl(config, exitcode); goto done; error: diff --git a/contrib/tools/python3/src/Modules/mathmodule.c b/contrib/tools/python3/src/Modules/mathmodule.c index 1f16849a3e..4534176adc 100644 --- a/contrib/tools/python3/src/Modules/mathmodule.c +++ b/contrib/tools/python3/src/Modules/mathmodule.c @@ -53,7 +53,9 @@ raised for division by zero and mod by zero. */ #include "Python.h" +#include "pycore_bitutils.h" // _Py_bit_length() #include "pycore_dtoa.h" +#include "pycore_long.h" // _PyLong_GetZero() #include "_math.h" #include "clinic/mathmodule.c.h" @@ -843,13 +845,15 @@ math_gcd(PyObject *module, PyObject * const *args, Py_ssize_t nargs) Py_SETREF(res, PyNumber_Absolute(res)); return res; } + + PyObject *one = _PyLong_GetOne(); // borrowed ref for (i = 1; i < nargs; i++) { - x = PyNumber_Index(args[i]); + x = _PyNumber_Index(args[i]); if (x == NULL) { Py_DECREF(res); return NULL; } - if (res == _PyLong_One) { + if (res == one) { /* Fast path: just check arguments. It is okay to use identity comparison here. */ Py_DECREF(x); @@ -916,13 +920,15 @@ math_lcm(PyObject *module, PyObject * const *args, Py_ssize_t nargs) Py_SETREF(res, PyNumber_Absolute(res)); return res; } + + PyObject *zero = _PyLong_GetZero(); // borrowed ref for (i = 1; i < nargs; i++) { x = PyNumber_Index(args[i]); if (x == NULL) { Py_DECREF(res); return NULL; } - if (res == _PyLong_Zero) { + if (res == zero) { /* Fast path: just check arguments. It is okay to use identity comparison here. */ Py_DECREF(x); @@ -1732,7 +1738,7 @@ math_isqrt(PyObject *module, PyObject *n) uint64_t m, u; PyObject *a = NULL, *b; - n = PyNumber_Index(n); + n = _PyNumber_Index(n); if (n == NULL) { return NULL; } @@ -1840,7 +1846,7 @@ math_isqrt(PyObject *module, PyObject *n) } if (a_too_large) { - Py_SETREF(a, PyNumber_Subtract(a, _PyLong_One)); + Py_SETREF(a, PyNumber_Subtract(a, _PyLong_GetOne())); } Py_DECREF(n); return a; @@ -1877,7 +1883,7 @@ math_isqrt(PyObject *module, PyObject *n) * (1) * * (1) * * (1 * 3 * 5) * - * (1 * 3 * 5 * 7 * 9) + * (1 * 3 * 5 * 7 * 9) * * (1 * 3 * 5 * 7 * 9 * 11 * 13 * 15 * 17 * 19) * * Here i goes from large to small: the first term corresponds to i=4 (any @@ -2056,37 +2062,9 @@ math_factorial(PyObject *module, PyObject *arg) { long x, two_valuation; int overflow; - PyObject *result, *odd_part, *pyint_form; - - if (PyFloat_Check(arg)) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "Using factorial() with floats is deprecated", - 1) < 0) - { - return NULL; - } - PyObject *lx; - double dx = PyFloat_AS_DOUBLE((PyFloatObject *)arg); - if (!(Py_IS_FINITE(dx) && dx == floor(dx))) { - PyErr_SetString(PyExc_ValueError, - "factorial() only accepts integral values"); - return NULL; - } - lx = PyLong_FromDouble(dx); - if (lx == NULL) - return NULL; - x = PyLong_AsLongAndOverflow(lx, &overflow); - Py_DECREF(lx); - } - else { - pyint_form = PyNumber_Index(arg); - if (pyint_form == NULL) { - return NULL; - } - x = PyLong_AsLongAndOverflow(pyint_form, &overflow); - Py_DECREF(pyint_form); - } + PyObject *result, *odd_part; + x = PyLong_AsLongAndOverflow(arg, &overflow); if (x == -1 && PyErr_Occurred()) { return NULL; } @@ -2435,40 +2413,108 @@ math_fmod_impl(PyObject *module, double x, double y) } /* -Given an *n* length *vec* of values and a value *max*, compute: +Given a *vec* of values, compute the vector norm: - max * sqrt(sum((x / max) ** 2 for x in vec)) + sqrt(sum(x ** 2 for x in vec)) -The value of the *max* variable must be non-negative and -equal to the absolute value of the largest magnitude -entry in the vector. If n==0, then *max* should be 0.0. +The *max* variable should be equal to the largest fabs(x). +The *n* variable is the length of *vec*. +If n==0, then *max* should be 0.0. If an infinity is present in the vec, *max* should be INF. - The *found_nan* variable indicates whether some member of the *vec* is a NaN. -To improve accuracy and to increase the number of cases where -vector_norm() is commutative, we use a variant of Neumaier -summation specialized to exploit that we always know that -|csum| >= |x|. - -The *csum* variable tracks the cumulative sum and *frac* tracks -the cumulative fractional errors at each step. Since this -variant assumes that |csum| >= |x| at each step, we establish -the precondition by starting the accumulation from 1.0 which -represents the largest possible value of (x/max)**2. - -After the loop is finished, the initial 1.0 is subtracted out -for a net zero effect on the final sum. Since *csum* will be -greater than 1.0, the subtraction of 1.0 will not cause -fractional digits to be dropped from *csum*. +To avoid overflow/underflow and to achieve high accuracy giving results +that are almost always correctly rounded, four techniques are used: + +* lossless scaling using a power-of-two scaling factor +* accurate squaring using Veltkamp-Dekker splitting [1] +* compensated summation using a variant of the Neumaier algorithm [2] +* differential correction of the square root [3] + +The usual presentation of the Neumaier summation algorithm has an +expensive branch depending on which operand has the larger +magnitude. We avoid this cost by arranging the calculation so that +fabs(csum) is always as large as fabs(x). + +To establish the invariant, *csum* is initialized to 1.0 which is +always larger than x**2 after scaling or after division by *max*. +After the loop is finished, the initial 1.0 is subtracted out for a +net zero effect on the final sum. Since *csum* will be greater than +1.0, the subtraction of 1.0 will not cause fractional digits to be +dropped from *csum*. + +To get the full benefit from compensated summation, the largest +addend should be in the range: 0.5 <= |x| <= 1.0. Accordingly, +scaling or division by *max* should not be skipped even if not +otherwise needed to prevent overflow or loss of precision. + +The assertion that hi*hi <= 1.0 is a bit subtle. Each vector element +gets scaled to a magnitude below 1.0. The Veltkamp-Dekker splitting +algorithm gives a *hi* value that is correctly rounded to half +precision. When a value at or below 1.0 is correctly rounded, it +never goes above 1.0. And when values at or below 1.0 are squared, +they remain at or below 1.0, thus preserving the summation invariant. + +Another interesting assertion is that csum+lo*lo == csum. In the loop, +each scaled vector element has a magnitude less than 1.0. After the +Veltkamp split, *lo* has a maximum value of 2**-27. So the maximum +value of *lo* squared is 2**-54. The value of ulp(1.0)/2.0 is 2**-53. +Given that csum >= 1.0, we have: + lo**2 <= 2**-54 < 2**-53 == 1/2*ulp(1.0) <= ulp(csum)/2 +Since lo**2 is less than 1/2 ulp(csum), we have csum+lo*lo == csum. + +To minimize loss of information during the accumulation of fractional +values, each term has a separate accumulator. This also breaks up +sequential dependencies in the inner loop so the CPU can maximize +floating point throughput. [4] On a 2.6 GHz Haswell, adding one +dimension has an incremental cost of only 5ns -- for example when +moving from hypot(x,y) to hypot(x,y,z). + +The square root differential correction is needed because a +correctly rounded square root of a correctly rounded sum of +squares can still be off by as much as one ulp. + +The differential correction starts with a value *x* that is +the difference between the square of *h*, the possibly inaccurately +rounded square root, and the accurately computed sum of squares. +The correction is the first order term of the Maclaurin series +expansion of sqrt(h**2 + x) == h + x/(2*h) + O(x**2). [5] + +Essentially, this differential correction is equivalent to one +refinement step in Newton's divide-and-average square root +algorithm, effectively doubling the number of accurate bits. +This technique is used in Dekker's SQRT2 algorithm and again in +Borges' ALGORITHM 4 and 5. + +Without proof for all cases, hypot() cannot claim to be always +correctly rounded. However for n <= 1000, prior to the final addition +that rounds the overall result, the internal accuracy of "h" together +with its correction of "x / (2.0 * h)" is at least 100 bits. [6] +Also, hypot() was tested against a Decimal implementation with +prec=300. After 100 million trials, no incorrectly rounded examples +were found. In addition, perfect commutativity (all permutations are +exactly equal) was verified for 1 billion random inputs with n=5. [7] + +References: + +1. Veltkamp-Dekker splitting: http://csclub.uwaterloo.ca/~pbarfuss/dekker1971.pdf +2. Compensated summation: http://www.ti3.tu-harburg.de/paper/rump/Ru08b.pdf +3. Square root differential correction: https://arxiv.org/pdf/1904.09481.pdf +4. Data dependency graph: https://bugs.python.org/file49439/hypot.png +5. https://www.wolframalpha.com/input/?i=Maclaurin+series+sqrt%28h**2+%2B+x%29+at+x%3D0 +6. Analysis of internal accuracy: https://bugs.python.org/file49484/best_frac.py +7. Commutativity test: https://bugs.python.org/file49448/test_hypot_commutativity.py */ static inline double vector_norm(Py_ssize_t n, double *vec, double max, int found_nan) { - double x, csum = 1.0, oldcsum, frac = 0.0; + const double T27 = 134217729.0; /* ldexp(1.0, 27) + 1.0) */ + double x, scale, oldcsum, csum = 1.0, frac1 = 0.0, frac2 = 0.0, frac3 = 0.0; + double t, hi, lo, h; + int max_e; Py_ssize_t i; if (Py_IS_INFINITY(max)) { @@ -2480,17 +2526,83 @@ vector_norm(Py_ssize_t n, double *vec, double max, int found_nan) if (max == 0.0 || n <= 1) { return max; } + frexp(max, &max_e); + if (max_e >= -1023) { + scale = ldexp(1.0, -max_e); + assert(max * scale >= 0.5); + assert(max * scale < 1.0); + for (i=0 ; i < n ; i++) { + x = vec[i]; + assert(Py_IS_FINITE(x) && fabs(x) <= max); + + x *= scale; + assert(fabs(x) < 1.0); + + t = x * T27; + hi = t - (t - x); + lo = x - hi; + assert(hi + lo == x); + + x = hi * hi; + assert(x <= 1.0); + assert(fabs(csum) >= fabs(x)); + oldcsum = csum; + csum += x; + frac1 += (oldcsum - csum) + x; + + x = 2.0 * hi * lo; + assert(fabs(csum) >= fabs(x)); + oldcsum = csum; + csum += x; + frac2 += (oldcsum - csum) + x; + + assert(csum + lo * lo == csum); + frac3 += lo * lo; + } + h = sqrt(csum - 1.0 + (frac1 + frac2 + frac3)); + + x = h; + t = x * T27; + hi = t - (t - x); + lo = x - hi; + assert (hi + lo == x); + + x = -hi * hi; + assert(fabs(csum) >= fabs(x)); + oldcsum = csum; + csum += x; + frac1 += (oldcsum - csum) + x; + + x = -2.0 * hi * lo; + assert(fabs(csum) >= fabs(x)); + oldcsum = csum; + csum += x; + frac2 += (oldcsum - csum) + x; + + x = -lo * lo; + assert(fabs(csum) >= fabs(x)); + oldcsum = csum; + csum += x; + frac3 += (oldcsum - csum) + x; + + x = csum - 1.0 + (frac1 + frac2 + frac3); + return (h + x / (2.0 * h)) / scale; + } + /* When max_e < -1023, ldexp(1.0, -max_e) overflows. + So instead of multiplying by a scale, we just divide by *max*. + */ for (i=0 ; i < n ; i++) { x = vec[i]; assert(Py_IS_FINITE(x) && fabs(x) <= max); x /= max; x = x*x; + assert(x <= 1.0); + assert(fabs(csum) >= fabs(x)); oldcsum = csum; csum += x; - assert(csum >= x); - frac += (oldcsum - csum) + x; + frac1 += (oldcsum - csum) + x; } - return max * sqrt(csum - 1.0 + frac); + return max * sqrt(csum - 1.0 + frac1); } #define NUM_STACK_ELEMS 16 @@ -2973,7 +3085,7 @@ math_prod_impl(PyObject *module, PyObject *iterable, PyObject *start) } if (result == NULL) { - result = _PyLong_One; + result = _PyLong_GetOne(); } Py_INCREF(result); #ifndef SLOW_PROD @@ -3135,24 +3247,11 @@ math_perm_impl(PyObject *module, PyObject *n, PyObject *k) if (n == NULL) { return NULL; } - if (!PyLong_CheckExact(n)) { - Py_SETREF(n, _PyLong_Copy((PyLongObject *)n)); - if (n == NULL) { - return NULL; - } - } k = PyNumber_Index(k); if (k == NULL) { Py_DECREF(n); return NULL; } - if (!PyLong_CheckExact(k)) { - Py_SETREF(k, _PyLong_Copy((PyLongObject *)k)); - if (k == NULL) { - Py_DECREF(n); - return NULL; - } - } if (Py_SIZE(n) < 0) { PyErr_SetString(PyExc_ValueError, @@ -3197,10 +3296,10 @@ math_perm_impl(PyObject *module, PyObject *n, PyObject *k) goto done; } - factor = n; - Py_INCREF(factor); + factor = Py_NewRef(n); + PyObject *one = _PyLong_GetOne(); // borrowed ref for (i = 1; i < factors; ++i) { - Py_SETREF(factor, PyNumber_Subtract(factor, _PyLong_One)); + Py_SETREF(factor, PyNumber_Subtract(factor, one)); if (factor == NULL) { goto error; } @@ -3258,24 +3357,11 @@ math_comb_impl(PyObject *module, PyObject *n, PyObject *k) if (n == NULL) { return NULL; } - if (!PyLong_CheckExact(n)) { - Py_SETREF(n, _PyLong_Copy((PyLongObject *)n)); - if (n == NULL) { - return NULL; - } - } k = PyNumber_Index(k); if (k == NULL) { Py_DECREF(n); return NULL; } - if (!PyLong_CheckExact(k)) { - Py_SETREF(k, _PyLong_Copy((PyLongObject *)k)); - if (k == NULL) { - Py_DECREF(n); - return NULL; - } - } if (Py_SIZE(n) < 0) { PyErr_SetString(PyExc_ValueError, @@ -3332,10 +3418,10 @@ math_comb_impl(PyObject *module, PyObject *n, PyObject *k) goto done; } - factor = n; - Py_INCREF(factor); + factor = Py_NewRef(n); + PyObject *one = _PyLong_GetOne(); // borrowed ref for (i = 1; i < factors; ++i) { - Py_SETREF(factor, PyNumber_Subtract(factor, _PyLong_One)); + Py_SETREF(factor, PyNumber_Subtract(factor, one)); if (factor == NULL) { goto error; } @@ -3390,6 +3476,12 @@ math_nextafter_impl(PyObject *module, double x, double y) Bug fixed in bos.adt.libm 7.2.2.0 by APAR IV95512. */ return PyFloat_FromDouble(y); } + if (Py_IS_NAN(x)) { + return PyFloat_FromDouble(x); + } + if (Py_IS_NAN(y)) { + return PyFloat_FromDouble(y); + } #endif return PyFloat_FromDouble(nextafter(x, y)); } diff --git a/contrib/tools/python3/src/Modules/md5module.c b/contrib/tools/python3/src/Modules/md5module.c index 6ed843376a..b50d2e5b0b 100644 --- a/contrib/tools/python3/src/Modules/md5module.c +++ b/contrib/tools/python3/src/Modules/md5module.c @@ -211,7 +211,7 @@ static void md5_compress(struct md5_state *md5, const unsigned char *buf) /** Initialize the hash state - @param sha1 The hash state you wish to initialize + @param md5 The hash state you wish to initialize */ static void md5_init(struct md5_state *md5) @@ -227,7 +227,7 @@ md5_init(struct md5_state *md5) /** Process a block of memory though the hash - @param sha1 The hash state + @param md5 The hash state @param in The data to hash @param inlen The length of the data (octets) */ @@ -263,7 +263,7 @@ md5_process(struct md5_state *md5, const unsigned char *in, Py_ssize_t inlen) /** Terminate the hash to get the digest - @param sha1 The hash state + @param md5 The hash state @param out [out] The destination of the hash (16 bytes) */ static void @@ -318,22 +318,41 @@ md5_done(struct md5_state *md5, unsigned char *out) * ------------------------------------------------------------------------ */ -static PyTypeObject MD5type; +typedef struct { + PyTypeObject* md5_type; +} MD5State; +static inline MD5State* +md5_get_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (MD5State *)state; +} static MD5object * -newMD5object(void) +newMD5object(MD5State * st) { - return (MD5object *)PyObject_New(MD5object, &MD5type); + MD5object *md5 = (MD5object *)PyObject_GC_New(MD5object, st->md5_type); + PyObject_GC_Track(md5); + return md5; } - /* Internal methods for a hash object */ +static int +MD5_traverse(PyObject *ptr, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(ptr)); + return 0; +} static void MD5_dealloc(PyObject *ptr) { - PyObject_Del(ptr); + PyTypeObject *tp = Py_TYPE(ptr); + PyObject_GC_UnTrack(ptr); + PyObject_GC_Del(ptr); + Py_DECREF(tp); } @@ -342,16 +361,19 @@ MD5_dealloc(PyObject *ptr) /*[clinic input] MD5Type.copy + cls: defining_class + Return a copy of the hash object. [clinic start generated code]*/ static PyObject * -MD5Type_copy_impl(MD5object *self) -/*[clinic end generated code: output=596eb36852f02071 input=2c09e6d2493f3079]*/ +MD5Type_copy_impl(MD5object *self, PyTypeObject *cls) +/*[clinic end generated code: output=bf055e08244bf5ee input=d89087dcfb2a8620]*/ { - MD5object *newobj; + MD5State *st = PyType_GetModuleState(cls); - if ((newobj = newMD5object())==NULL) + MD5object *newobj; + if ((newobj = newMD5object(st))==NULL) return NULL; newobj->hash_state = self->hash_state; @@ -445,7 +467,6 @@ md5_get_digest_size(PyObject *self, void *closure) return PyLong_FromLong(MD5_DIGESTSIZE); } - static PyGetSetDef MD5_getseters[] = { {"block_size", (getter)MD5_get_block_size, NULL, @@ -462,40 +483,21 @@ static PyGetSetDef MD5_getseters[] = { {NULL} /* Sentinel */ }; -static PyTypeObject MD5type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_md5.md5", /*tp_name*/ - sizeof(MD5object), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - MD5_dealloc, /*tp_dealloc*/ - 0, /*tp_vectorcall_offset*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_as_async*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - MD5_methods, /* tp_methods */ - NULL, /* tp_members */ - MD5_getseters, /* tp_getset */ +static PyType_Slot md5_type_slots[] = { + {Py_tp_dealloc, MD5_dealloc}, + {Py_tp_methods, MD5_methods}, + {Py_tp_getset, MD5_getseters}, + {Py_tp_traverse, MD5_traverse}, + {0,0} }; +static PyType_Spec md5_type_spec = { + .name = "_md5.md5", + .basicsize = sizeof(MD5object), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC), + .slots = md5_type_slots +}; /* The single module-level function: new() */ @@ -519,7 +521,8 @@ _md5_md5_impl(PyObject *module, PyObject *string, int usedforsecurity) if (string) GET_BUFFER_VIEW_OR_ERROUT(string, &buf); - if ((new = newMD5object()) == NULL) { + MD5State *st = md5_get_state(module); + if ((new = newMD5object(st)) == NULL) { if (string) PyBuffer_Release(&buf); return NULL; @@ -549,37 +552,69 @@ static struct PyMethodDef MD5_functions[] = { {NULL, NULL} /* Sentinel */ }; +static int +_md5_traverse(PyObject *module, visitproc visit, void *arg) +{ + MD5State *state = md5_get_state(module); + Py_VISIT(state->md5_type); + return 0; +} + +static int +_md5_clear(PyObject *module) +{ + MD5State *state = md5_get_state(module); + Py_CLEAR(state->md5_type); + return 0; +} + +static void +_md5_free(void *module) +{ + _md5_clear((PyObject *)module); +} /* Initialize this module. */ +static int +md5_exec(PyObject *m) +{ + MD5State *st = md5_get_state(m); + + st->md5_type = (PyTypeObject *)PyType_FromModuleAndSpec( + m, &md5_type_spec, NULL); + + if (st->md5_type == NULL) { + return -1; + } + + Py_INCREF((PyObject *)st->md5_type); + if (PyModule_AddObject(m, "MD5Type", (PyObject *)st->md5_type) < 0) { + Py_DECREF(st->md5_type); + return -1; + } + + return 0; +} + +static PyModuleDef_Slot _md5_slots[] = { + {Py_mod_exec, md5_exec}, + {0, NULL} +}; + static struct PyModuleDef _md5module = { PyModuleDef_HEAD_INIT, - "_md5", - NULL, - -1, - MD5_functions, - NULL, - NULL, - NULL, - NULL + .m_name = "_md5", + .m_size = sizeof(MD5State), + .m_methods = MD5_functions, + .m_slots = _md5_slots, + .m_traverse = _md5_traverse, + .m_clear = _md5_clear, + .m_free = _md5_free, }; PyMODINIT_FUNC PyInit__md5(void) { - PyObject *m; - - Py_SET_TYPE(&MD5type, &PyType_Type); - if (PyType_Ready(&MD5type) < 0) { - return NULL; - } - - m = PyModule_Create(&_md5module); - if (m == NULL) { - return NULL; - } - - Py_INCREF((PyObject *)&MD5type); - PyModule_AddObject(m, "MD5Type", (PyObject *)&MD5type); - return m; + return PyModuleDef_Init(&_md5module); } diff --git a/contrib/tools/python3/src/Modules/mmapmodule.c b/contrib/tools/python3/src/Modules/mmapmodule.c index a3e22d0a51..6397b0d4b8 100644 --- a/contrib/tools/python3/src/Modules/mmapmodule.c +++ b/contrib/tools/python3/src/Modules/mmapmodule.c @@ -20,6 +20,7 @@ #define PY_SSIZE_T_CLEAN #include <Python.h> +#include "structmember.h" // PyMemberDef #include <stddef.h> // offsetof() #ifndef MS_WINDOWS @@ -113,10 +114,31 @@ typedef struct { access_mode access; } mmap_object; +typedef struct { + PyTypeObject *mmap_object_type; +} mmap_state; + +static mmap_state * +get_mmap_state(PyObject *module) +{ + mmap_state *state = PyModule_GetState(module); + assert(state); + return state; +} + +static int +mmap_object_traverse(mmap_object *m_obj, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(m_obj)); + return 0; +} static void mmap_object_dealloc(mmap_object *m_obj) { + PyTypeObject *tp = Py_TYPE(m_obj); + PyObject_GC_UnTrack(m_obj); + #ifdef MS_WINDOWS Py_BEGIN_ALLOW_THREADS if (m_obj->data != NULL) @@ -142,7 +164,9 @@ mmap_object_dealloc(mmap_object *m_obj) if (m_obj->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) m_obj); - Py_TYPE(m_obj)->tp_free((PyObject*)m_obj); + + tp->tp_free(m_obj); + Py_DECREF(tp); } static PyObject * @@ -793,6 +817,11 @@ mmap_madvise_method(mmap_object *self, PyObject *args) } #endif // HAVE_MADVISE +static struct PyMemberDef mmap_object_members[] = { + {"__weaklistoffset__", T_PYSSIZET, offsetof(mmap_object, weakreflist), READONLY}, + {NULL}, +}; + static struct PyMethodDef mmap_object_methods[] = { {"close", (PyCFunction) mmap_close_method, METH_NOARGS}, {"find", (PyCFunction) mmap_find_method, METH_VARARGS}, @@ -1035,27 +1064,6 @@ mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value) } } -static PySequenceMethods mmap_as_sequence = { - (lenfunc)mmap_length, /*sq_length*/ - 0, /*sq_concat*/ - 0, /*sq_repeat*/ - (ssizeargfunc)mmap_item, /*sq_item*/ - 0, /*sq_slice*/ - (ssizeobjargproc)mmap_ass_item, /*sq_ass_item*/ - 0, /*sq_ass_slice*/ -}; - -static PyMappingMethods mmap_as_mapping = { - (lenfunc)mmap_length, - (binaryfunc)mmap_subscript, - (objobjargproc)mmap_ass_subscript, -}; - -static PyBufferProcs mmap_as_buffer = { - (getbufferproc)mmap_buffer_getbuf, - (releasebufferproc)mmap_buffer_releasebuf, -}; - static PyObject * new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict); @@ -1083,47 +1091,39 @@ The default value is MAP_SHARED.\n\ To map anonymous memory, pass -1 as the fileno (both versions)."); -static PyTypeObject mmap_object_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "mmap.mmap", /* tp_name */ - sizeof(mmap_object), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)mmap_object_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)mmap__repr__method, /* tp_repr */ - 0, /* tp_as_number */ - &mmap_as_sequence, /* tp_as_sequence */ - &mmap_as_mapping, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - &mmap_as_buffer, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - mmap_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(mmap_object, weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - mmap_object_methods, /* tp_methods */ - 0, /* tp_members */ - mmap_object_getset, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - new_mmap_object, /* tp_new */ - PyObject_Del, /* tp_free */ +static PyType_Slot mmap_object_slots[] = { + {Py_tp_new, new_mmap_object}, + {Py_tp_dealloc, mmap_object_dealloc}, + {Py_tp_repr, mmap__repr__method}, + {Py_tp_doc, (void *)mmap_doc}, + {Py_tp_methods, mmap_object_methods}, + {Py_tp_members, mmap_object_members}, + {Py_tp_getset, mmap_object_getset}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_traverse, mmap_object_traverse}, + + /* as sequence */ + {Py_sq_length, mmap_length}, + {Py_sq_item, mmap_item}, + {Py_sq_ass_item, mmap_ass_item}, + + /* as mapping */ + {Py_mp_length, mmap_length}, + {Py_mp_subscript, mmap_subscript}, + {Py_mp_ass_subscript, mmap_ass_subscript}, + + /* as buffer */ + {Py_bf_getbuffer, mmap_buffer_getbuf}, + {Py_bf_releasebuffer, mmap_buffer_releasebuf}, + {0, NULL}, +}; + +static PyType_Spec mmap_object_spec = { + .name = "mmap.mmap", + .basicsize = sizeof(mmap_object), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), + .slots = mmap_object_slots, }; @@ -1378,13 +1378,10 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict) */ if (fileno != -1 && fileno != 0) { /* Ensure that fileno is within the CRT's valid range */ - _Py_BEGIN_SUPPRESS_IPH - fh = (HANDLE)_get_osfhandle(fileno); - _Py_END_SUPPRESS_IPH - if (fh==(HANDLE)-1) { - PyErr_SetFromErrno(PyExc_OSError); + fh = _Py_get_osfhandle(fileno); + if (fh == INVALID_HANDLE_VALUE) return NULL; - } + /* Win9x appears to need us seeked to zero */ lseek(fileno, 0, SEEK_SET); } @@ -1509,154 +1506,201 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict) } #endif /* MS_WINDOWS */ -static void -setint(PyObject *d, const char *name, long value) +static int +mmap_traverse(PyObject *module, visitproc visit, void *arg) { - PyObject *o = PyLong_FromLong(value); - if (o) { - PyDict_SetItemString(d, name, o); - Py_DECREF(o); - } + mmap_state *state = get_mmap_state(module); + Py_VISIT(state->mmap_object_type); + return 0; } +static int +mmap_clear(PyObject *module) +{ + mmap_state *state = get_mmap_state(module); + Py_CLEAR(state->mmap_object_type); + return 0; +} -static struct PyModuleDef mmapmodule = { - PyModuleDef_HEAD_INIT, - "mmap", - NULL, - -1, - NULL, - NULL, - NULL, - NULL, - NULL -}; +static void +mmap_free(void *module) +{ + mmap_clear((PyObject *)module); +} -PyMODINIT_FUNC -PyInit_mmap(void) +static int +mmap_exec(PyObject *module) { - PyObject *dict, *module; + mmap_state *state = get_mmap_state(module); - if (PyType_Ready(&mmap_object_type) < 0) - return NULL; + Py_INCREF(PyExc_OSError); + if (PyModule_AddObject(module, "error", PyExc_OSError) < 0) { + Py_DECREF(PyExc_OSError); + return -1; + } + + state->mmap_object_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, + &mmap_object_spec, + NULL); + if (state->mmap_object_type == NULL) { + return -1; + } + if (PyModule_AddType(module, state->mmap_object_type) < 0) { + return -1; + } + +#define ADD_INT_MACRO(module, constant) \ + do { \ + if (PyModule_AddIntConstant(module, #constant, constant) < 0) { \ + return -1; \ + } \ + } while (0) - module = PyModule_Create(&mmapmodule); - if (module == NULL) - return NULL; - dict = PyModule_GetDict(module); - if (!dict) - return NULL; - PyDict_SetItemString(dict, "error", PyExc_OSError); - PyDict_SetItemString(dict, "mmap", (PyObject*) &mmap_object_type); #ifdef PROT_EXEC - setint(dict, "PROT_EXEC", PROT_EXEC); + ADD_INT_MACRO(module, PROT_EXEC); #endif #ifdef PROT_READ - setint(dict, "PROT_READ", PROT_READ); + ADD_INT_MACRO(module, PROT_READ); #endif #ifdef PROT_WRITE - setint(dict, "PROT_WRITE", PROT_WRITE); + ADD_INT_MACRO(module, PROT_WRITE); #endif #ifdef MAP_SHARED - setint(dict, "MAP_SHARED", MAP_SHARED); + ADD_INT_MACRO(module, MAP_SHARED); #endif #ifdef MAP_PRIVATE - setint(dict, "MAP_PRIVATE", MAP_PRIVATE); + ADD_INT_MACRO(module, MAP_PRIVATE); #endif #ifdef MAP_DENYWRITE - setint(dict, "MAP_DENYWRITE", MAP_DENYWRITE); + ADD_INT_MACRO(module, MAP_DENYWRITE); #endif #ifdef MAP_EXECUTABLE - setint(dict, "MAP_EXECUTABLE", MAP_EXECUTABLE); + ADD_INT_MACRO(module, MAP_EXECUTABLE); #endif #ifdef MAP_ANONYMOUS - setint(dict, "MAP_ANON", MAP_ANONYMOUS); - setint(dict, "MAP_ANONYMOUS", MAP_ANONYMOUS); + if (PyModule_AddIntConstant(module, "MAP_ANON", MAP_ANONYMOUS) < 0 ) { + return -1; + } + ADD_INT_MACRO(module, MAP_ANONYMOUS); #endif +#ifdef MAP_POPULATE + ADD_INT_MACRO(module, MAP_POPULATE); +#endif + if (PyModule_AddIntConstant(module, "PAGESIZE", (long)my_getpagesize()) < 0 ) { + return -1; + } - setint(dict, "PAGESIZE", (long)my_getpagesize()); - - setint(dict, "ALLOCATIONGRANULARITY", (long)my_getallocationgranularity()); + if (PyModule_AddIntConstant(module, "ALLOCATIONGRANULARITY", (long)my_getallocationgranularity()) < 0 ) { + return -1; + } - setint(dict, "ACCESS_DEFAULT", ACCESS_DEFAULT); - setint(dict, "ACCESS_READ", ACCESS_READ); - setint(dict, "ACCESS_WRITE", ACCESS_WRITE); - setint(dict, "ACCESS_COPY", ACCESS_COPY); + ADD_INT_MACRO(module, ACCESS_DEFAULT); + ADD_INT_MACRO(module, ACCESS_READ); + ADD_INT_MACRO(module, ACCESS_WRITE); + ADD_INT_MACRO(module, ACCESS_COPY); #ifdef HAVE_MADVISE // Conventional advice values #ifdef MADV_NORMAL - setint(dict, "MADV_NORMAL", MADV_NORMAL); + ADD_INT_MACRO(module, MADV_NORMAL); #endif #ifdef MADV_RANDOM - setint(dict, "MADV_RANDOM", MADV_RANDOM); + ADD_INT_MACRO(module, MADV_RANDOM); #endif #ifdef MADV_SEQUENTIAL - setint(dict, "MADV_SEQUENTIAL", MADV_SEQUENTIAL); + ADD_INT_MACRO(module, MADV_SEQUENTIAL); #endif #ifdef MADV_WILLNEED - setint(dict, "MADV_WILLNEED", MADV_WILLNEED); + ADD_INT_MACRO(module, MADV_WILLNEED); #endif #ifdef MADV_DONTNEED - setint(dict, "MADV_DONTNEED", MADV_DONTNEED); + ADD_INT_MACRO(module, MADV_DONTNEED); #endif // Linux-specific advice values #ifdef MADV_REMOVE - setint(dict, "MADV_REMOVE", MADV_REMOVE); + ADD_INT_MACRO(module, MADV_REMOVE); #endif #ifdef MADV_DONTFORK - setint(dict, "MADV_DONTFORK", MADV_DONTFORK); + ADD_INT_MACRO(module, MADV_DONTFORK); #endif #ifdef MADV_DOFORK - setint(dict, "MADV_DOFORK", MADV_DOFORK); + ADD_INT_MACRO(module, MADV_DOFORK); #endif #ifdef MADV_HWPOISON - setint(dict, "MADV_HWPOISON", MADV_HWPOISON); + ADD_INT_MACRO(module, MADV_HWPOISON); #endif #ifdef MADV_MERGEABLE - setint(dict, "MADV_MERGEABLE", MADV_MERGEABLE); + ADD_INT_MACRO(module, MADV_MERGEABLE); #endif #ifdef MADV_UNMERGEABLE - setint(dict, "MADV_UNMERGEABLE", MADV_UNMERGEABLE); + ADD_INT_MACRO(module, MADV_UNMERGEABLE); #endif #ifdef MADV_SOFT_OFFLINE - setint(dict, "MADV_SOFT_OFFLINE", MADV_SOFT_OFFLINE); + ADD_INT_MACRO(module, MADV_SOFT_OFFLINE); #endif #ifdef MADV_HUGEPAGE - setint(dict, "MADV_HUGEPAGE", MADV_HUGEPAGE); + ADD_INT_MACRO(module, MADV_HUGEPAGE); #endif #ifdef MADV_NOHUGEPAGE - setint(dict, "MADV_NOHUGEPAGE", MADV_NOHUGEPAGE); + ADD_INT_MACRO(module, MADV_NOHUGEPAGE); #endif #ifdef MADV_DONTDUMP - setint(dict, "MADV_DONTDUMP", MADV_DONTDUMP); + ADD_INT_MACRO(module, MADV_DONTDUMP); #endif #ifdef MADV_DODUMP - setint(dict, "MADV_DODUMP", MADV_DODUMP); + ADD_INT_MACRO(module, MADV_DODUMP); #endif #ifdef MADV_FREE // (Also present on FreeBSD and macOS.) - setint(dict, "MADV_FREE", MADV_FREE); + ADD_INT_MACRO(module, MADV_FREE); #endif // FreeBSD-specific #ifdef MADV_NOSYNC - setint(dict, "MADV_NOSYNC", MADV_NOSYNC); + ADD_INT_MACRO(module, MADV_NOSYNC); #endif #ifdef MADV_AUTOSYNC - setint(dict, "MADV_AUTOSYNC", MADV_AUTOSYNC); + ADD_INT_MACRO(module, MADV_AUTOSYNC); #endif #ifdef MADV_NOCORE - setint(dict, "MADV_NOCORE", MADV_NOCORE); + ADD_INT_MACRO(module, MADV_NOCORE); #endif #ifdef MADV_CORE - setint(dict, "MADV_CORE", MADV_CORE); + ADD_INT_MACRO(module, MADV_CORE); #endif #ifdef MADV_PROTECT - setint(dict, "MADV_PROTECT", MADV_PROTECT); + ADD_INT_MACRO(module, MADV_PROTECT); +#endif + + // Darwin-specific +#ifdef MADV_FREE_REUSABLE // (As MADV_FREE but reclaims more faithful for task_info/Activity Monitor...) + ADD_INT_MACRO(module, MADV_FREE_REUSABLE); +#endif +#ifdef MADV_FREE_REUSE // (Reuse pages previously tagged as reusable) + ADD_INT_MACRO(module, MADV_FREE_REUSE); #endif #endif // HAVE_MADVISE + return 0; +} - return module; +static PyModuleDef_Slot mmap_slots[] = { + {Py_mod_exec, mmap_exec}, + {0, NULL} +}; + +static struct PyModuleDef mmapmodule = { + PyModuleDef_HEAD_INIT, + .m_name = "mmap", + .m_size = sizeof(mmap_state), + .m_slots = mmap_slots, + .m_traverse = mmap_traverse, + .m_clear = mmap_clear, + .m_free = mmap_free, +}; + +PyMODINIT_FUNC +PyInit_mmap(void) +{ + return PyModuleDef_Init(&mmapmodule); } diff --git a/contrib/tools/python3/src/Modules/overlapped.c b/contrib/tools/python3/src/Modules/overlapped.c index cd7869fa8a..7c4570896b 100644 --- a/contrib/tools/python3/src/Modules/overlapped.c +++ b/contrib/tools/python3/src/Modules/overlapped.c @@ -37,6 +37,36 @@ #define T_HANDLE T_POINTER +/*[python input] +class OVERLAPPED_converter(CConverter): + type = 'OVERLAPPED *' + format_unit = '"F_POINTER"' + +class HANDLE_converter(CConverter): + type = 'HANDLE' + format_unit = '"F_HANDLE"' + +class ULONG_PTR_converter(CConverter): + type = 'ULONG_PTR' + format_unit = '"F_ULONG_PTR"' + +class DWORD_converter(CConverter): + type = 'DWORD' + format_unit = 'k' + +class BOOL_converter(CConverter): + type = 'BOOL' + format_unit = 'i' +[python start generated code]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=83bb8c2c2514f2a8]*/ + +/*[clinic input] +module _overlapped +class _overlapped.Overlapped "OverlappedObject *" "&OverlappedType" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=92e5a799db35b96c]*/ + + enum {TYPE_NONE, TYPE_NOT_STARTED, TYPE_READ, TYPE_READINTO, TYPE_WRITE, TYPE_ACCEPT, TYPE_CONNECT, TYPE_DISCONNECT, TYPE_CONNECT_NAMED_PIPE, TYPE_WAIT_NAMED_PIPE_AND_CONNECT, TYPE_TRANSMIT_FILE, TYPE_READ_FROM, @@ -70,6 +100,19 @@ typedef struct { }; } OverlappedObject; +typedef struct { + PyTypeObject *overlapped_type; +} OverlappedState; + +static inline OverlappedState* +overlapped_get_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (OverlappedState *)state; +} + + /* * Map Windows error codes to subclasses of OSError */ @@ -150,25 +193,27 @@ initialize_function_pointers(void) * Completion port stuff */ -PyDoc_STRVAR( - CreateIoCompletionPort_doc, - "CreateIoCompletionPort(handle, port, key, concurrency) -> port\n\n" - "Create a completion port or register a handle with a port."); +/*[clinic input] +_overlapped.CreateIoCompletionPort + + handle as FileHandle: HANDLE + port as ExistingCompletionPort: HANDLE + key as CompletionKey: ULONG_PTR + concurrency as NumberOfConcurrentThreads: DWORD + / + +Create a completion port or register a handle with a port. +[clinic start generated code]*/ static PyObject * -overlapped_CreateIoCompletionPort(PyObject *self, PyObject *args) +_overlapped_CreateIoCompletionPort_impl(PyObject *module, HANDLE FileHandle, + HANDLE ExistingCompletionPort, + ULONG_PTR CompletionKey, + DWORD NumberOfConcurrentThreads) +/*[clinic end generated code: output=24ede2b0f05e5433 input=847bae4d0efe1976]*/ { - HANDLE FileHandle; - HANDLE ExistingCompletionPort; - ULONG_PTR CompletionKey; - DWORD NumberOfConcurrentThreads; HANDLE ret; - if (!PyArg_ParseTuple(args, F_HANDLE F_HANDLE F_ULONG_PTR F_DWORD, - &FileHandle, &ExistingCompletionPort, &CompletionKey, - &NumberOfConcurrentThreads)) - return NULL; - Py_BEGIN_ALLOW_THREADS ret = CreateIoCompletionPort(FileHandle, ExistingCompletionPort, CompletionKey, NumberOfConcurrentThreads); @@ -179,26 +224,30 @@ overlapped_CreateIoCompletionPort(PyObject *self, PyObject *args) return Py_BuildValue(F_HANDLE, ret); } -PyDoc_STRVAR( - GetQueuedCompletionStatus_doc, - "GetQueuedCompletionStatus(port, msecs) -> (err, bytes, key, address)\n\n" - "Get a message from completion port. Wait for up to msecs milliseconds."); +/*[clinic input] +_overlapped.GetQueuedCompletionStatus + + port as CompletionPort: HANDLE + msecs as Milliseconds: DWORD + / + +Get a message from completion port. + +Wait for up to msecs milliseconds. +[clinic start generated code]*/ static PyObject * -overlapped_GetQueuedCompletionStatus(PyObject *self, PyObject *args) +_overlapped_GetQueuedCompletionStatus_impl(PyObject *module, + HANDLE CompletionPort, + DWORD Milliseconds) +/*[clinic end generated code: output=68314171628dddb7 input=94a042d14c4f6410]*/ { - HANDLE CompletionPort = NULL; DWORD NumberOfBytes = 0; ULONG_PTR CompletionKey = 0; OVERLAPPED *Overlapped = NULL; - DWORD Milliseconds; DWORD err; BOOL ret; - if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD, - &CompletionPort, &Milliseconds)) - return NULL; - Py_BEGIN_ALLOW_THREADS ret = GetQueuedCompletionStatus(CompletionPort, &NumberOfBytes, &CompletionKey, &Overlapped, Milliseconds); @@ -215,25 +264,28 @@ overlapped_GetQueuedCompletionStatus(PyObject *self, PyObject *args) err, NumberOfBytes, CompletionKey, Overlapped); } -PyDoc_STRVAR( - PostQueuedCompletionStatus_doc, - "PostQueuedCompletionStatus(port, bytes, key, address) -> None\n\n" - "Post a message to completion port."); +/*[clinic input] +_overlapped.PostQueuedCompletionStatus + + port as CompletionPort: HANDLE + bytes as NumberOfBytes: DWORD + key as CompletionKey: ULONG_PTR + address as Overlapped: OVERLAPPED + / + +Post a message to completion port. +[clinic start generated code]*/ static PyObject * -overlapped_PostQueuedCompletionStatus(PyObject *self, PyObject *args) +_overlapped_PostQueuedCompletionStatus_impl(PyObject *module, + HANDLE CompletionPort, + DWORD NumberOfBytes, + ULONG_PTR CompletionKey, + OVERLAPPED *Overlapped) +/*[clinic end generated code: output=93e73f2933a43e9e input=e936202d87937aca]*/ { - HANDLE CompletionPort; - DWORD NumberOfBytes; - ULONG_PTR CompletionKey; - OVERLAPPED *Overlapped; BOOL ret; - if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD F_ULONG_PTR F_POINTER, - &CompletionPort, &NumberOfBytes, &CompletionKey, - &Overlapped)) - return NULL; - Py_BEGIN_ALLOW_THREADS ret = PostQueuedCompletionStatus(CompletionPort, NumberOfBytes, CompletionKey, Overlapped); @@ -264,26 +316,27 @@ PostToQueueCallback(PVOID lpParameter, BOOLEAN TimerOrWaitFired) PyMem_RawFree(p); } -PyDoc_STRVAR( - RegisterWaitWithQueue_doc, - "RegisterWaitWithQueue(Object, CompletionPort, Overlapped, Timeout)\n" - " -> WaitHandle\n\n" - "Register wait for Object; when complete CompletionPort is notified.\n"); +/*[clinic input] +_overlapped.RegisterWaitWithQueue + + Object: HANDLE + CompletionPort: HANDLE + Overlapped: OVERLAPPED + Timeout as Milliseconds: DWORD + / + +Register wait for Object; when complete CompletionPort is notified. +[clinic start generated code]*/ static PyObject * -overlapped_RegisterWaitWithQueue(PyObject *self, PyObject *args) +_overlapped_RegisterWaitWithQueue_impl(PyObject *module, HANDLE Object, + HANDLE CompletionPort, + OVERLAPPED *Overlapped, + DWORD Milliseconds) +/*[clinic end generated code: output=c2ace732e447fe45 input=2dd4efee44abe8ee]*/ { HANDLE NewWaitObject; - HANDLE Object; - ULONG Milliseconds; - struct PostCallbackData data, *pdata; - - if (!PyArg_ParseTuple(args, F_HANDLE F_HANDLE F_POINTER F_DWORD, - &Object, - &data.CompletionPort, - &data.Overlapped, - &Milliseconds)) - return NULL; + struct PostCallbackData data = {CompletionPort, Overlapped}, *pdata; /* Use PyMem_RawMalloc() rather than PyMem_Malloc(), since PostToQueueCallback() will call PyMem_Free() from a new C thread @@ -305,20 +358,21 @@ overlapped_RegisterWaitWithQueue(PyObject *self, PyObject *args) return Py_BuildValue(F_HANDLE, NewWaitObject); } -PyDoc_STRVAR( - UnregisterWait_doc, - "UnregisterWait(WaitHandle) -> None\n\n" - "Unregister wait handle.\n"); +/*[clinic input] +_overlapped.UnregisterWait + + WaitHandle: HANDLE + / + +Unregister wait handle. +[clinic start generated code]*/ static PyObject * -overlapped_UnregisterWait(PyObject *self, PyObject *args) +_overlapped_UnregisterWait_impl(PyObject *module, HANDLE WaitHandle) +/*[clinic end generated code: output=ec90cd955a9a617d input=a56709544cb2df0f]*/ { - HANDLE WaitHandle; BOOL ret; - if (!PyArg_ParseTuple(args, F_HANDLE, &WaitHandle)) - return NULL; - Py_BEGIN_ALLOW_THREADS ret = UnregisterWait(WaitHandle); Py_END_ALLOW_THREADS @@ -328,20 +382,23 @@ overlapped_UnregisterWait(PyObject *self, PyObject *args) Py_RETURN_NONE; } -PyDoc_STRVAR( - UnregisterWaitEx_doc, - "UnregisterWaitEx(WaitHandle, Event) -> None\n\n" - "Unregister wait handle.\n"); +/*[clinic input] +_overlapped.UnregisterWaitEx + + WaitHandle: HANDLE + Event: HANDLE + / + +Unregister wait handle. +[clinic start generated code]*/ static PyObject * -overlapped_UnregisterWaitEx(PyObject *self, PyObject *args) +_overlapped_UnregisterWaitEx_impl(PyObject *module, HANDLE WaitHandle, + HANDLE Event) +/*[clinic end generated code: output=2e3d84c1d5f65b92 input=953cddc1de50fab9]*/ { - HANDLE WaitHandle, Event; BOOL ret; - if (!PyArg_ParseTuple(args, F_HANDLE F_HANDLE, &WaitHandle, &Event)) - return NULL; - Py_BEGIN_ALLOW_THREADS ret = UnregisterWaitEx(WaitHandle, Event); Py_END_ALLOW_THREADS @@ -355,26 +412,28 @@ overlapped_UnregisterWaitEx(PyObject *self, PyObject *args) * Event functions -- currently only used by tests */ -PyDoc_STRVAR( - CreateEvent_doc, - "CreateEvent(EventAttributes, ManualReset, InitialState, Name)" - " -> Handle\n\n" - "Create an event. EventAttributes must be None.\n"); +/*[clinic input] +_overlapped.CreateEvent + + EventAttributes: object + ManualReset: BOOL + InitialState: BOOL + Name: Py_UNICODE(accept={str, NoneType}) + / + +Create an event. + +EventAttributes must be None. +[clinic start generated code]*/ static PyObject * -overlapped_CreateEvent(PyObject *self, PyObject *args) +_overlapped_CreateEvent_impl(PyObject *module, PyObject *EventAttributes, + BOOL ManualReset, BOOL InitialState, + const Py_UNICODE *Name) +/*[clinic end generated code: output=8e04f0916c17b13d input=dbc36ae14375ba24]*/ { - PyObject *EventAttributes; - BOOL ManualReset; - BOOL InitialState; - Py_UNICODE *Name; HANDLE Event; - if (!PyArg_ParseTuple(args, "O" F_BOOL F_BOOL "Z", - &EventAttributes, &ManualReset, - &InitialState, &Name)) - return NULL; - if (EventAttributes != Py_None) { PyErr_SetString(PyExc_ValueError, "EventAttributes must be None"); return NULL; @@ -389,20 +448,21 @@ overlapped_CreateEvent(PyObject *self, PyObject *args) return Py_BuildValue(F_HANDLE, Event); } -PyDoc_STRVAR( - SetEvent_doc, - "SetEvent(Handle) -> None\n\n" - "Set event.\n"); +/*[clinic input] +_overlapped.SetEvent + + Handle: HANDLE + / + +Set event. +[clinic start generated code]*/ static PyObject * -overlapped_SetEvent(PyObject *self, PyObject *args) +_overlapped_SetEvent_impl(PyObject *module, HANDLE Handle) +/*[clinic end generated code: output=5b8d974216b0e569 input=d8b0d26eb7391e80]*/ { - HANDLE Handle; BOOL ret; - if (!PyArg_ParseTuple(args, F_HANDLE, &Handle)) - return NULL; - Py_BEGIN_ALLOW_THREADS ret = SetEvent(Handle); Py_END_ALLOW_THREADS @@ -412,20 +472,21 @@ overlapped_SetEvent(PyObject *self, PyObject *args) Py_RETURN_NONE; } -PyDoc_STRVAR( - ResetEvent_doc, - "ResetEvent(Handle) -> None\n\n" - "Reset event.\n"); +/*[clinic input] +_overlapped.ResetEvent + + Handle: HANDLE + / + +Reset event. +[clinic start generated code]*/ static PyObject * -overlapped_ResetEvent(PyObject *self, PyObject *args) +_overlapped_ResetEvent_impl(PyObject *module, HANDLE Handle) +/*[clinic end generated code: output=066537a8405cddb2 input=d4e089c9ba84ff2f]*/ { - HANDLE Handle; BOOL ret; - if (!PyArg_ParseTuple(args, F_HANDLE, &Handle)) - return NULL; - Py_BEGIN_ALLOW_THREADS ret = ResetEvent(Handle); Py_END_ALLOW_THREADS @@ -439,36 +500,40 @@ overlapped_ResetEvent(PyObject *self, PyObject *args) * Bind socket handle to local port without doing slow getaddrinfo() */ -PyDoc_STRVAR( - BindLocal_doc, - "BindLocal(handle, family) -> None\n\n" - "Bind a socket handle to an arbitrary local port.\n" - "family should AF_INET or AF_INET6.\n"); +/*[clinic input] +_overlapped.BindLocal + + handle as Socket: HANDLE + family as Family: int + / + +Bind a socket handle to an arbitrary local port. + +family should be AF_INET or AF_INET6. +[clinic start generated code]*/ static PyObject * -overlapped_BindLocal(PyObject *self, PyObject *args) +_overlapped_BindLocal_impl(PyObject *module, HANDLE Socket, int Family) +/*[clinic end generated code: output=edb93862697aed9c input=a0e7b5c2f541170c]*/ { - SOCKET Socket; - int Family; BOOL ret; - if (!PyArg_ParseTuple(args, F_HANDLE "i", &Socket, &Family)) - return NULL; - if (Family == AF_INET) { struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = 0; addr.sin_addr.S_un.S_addr = INADDR_ANY; - ret = bind(Socket, (SOCKADDR*)&addr, sizeof(addr)) != SOCKET_ERROR; + ret = bind((SOCKET)Socket, (SOCKADDR*)&addr, sizeof(addr)) + != SOCKET_ERROR; } else if (Family == AF_INET6) { struct sockaddr_in6 addr; memset(&addr, 0, sizeof(addr)); addr.sin6_family = AF_INET6; addr.sin6_port = 0; addr.sin6_addr = in6addr_any; - ret = bind(Socket, (SOCKADDR*)&addr, sizeof(addr)) != SOCKET_ERROR; + ret = bind((SOCKET)Socket, (SOCKADDR*)&addr, sizeof(addr)) + != SOCKET_ERROR; } else { PyErr_SetString(PyExc_ValueError, "expected tuple of length 2 or 4"); return NULL; @@ -483,21 +548,23 @@ overlapped_BindLocal(PyObject *self, PyObject *args) * Windows equivalent of os.strerror() -- compare _ctypes/callproc.c */ -PyDoc_STRVAR( - FormatMessage_doc, - "FormatMessage(error_code) -> error_message\n\n" - "Return error message for an error code."); +/*[clinic input] +_overlapped.FormatMessage + + error_code as code: DWORD + / + +Return error message for an error code. +[clinic start generated code]*/ static PyObject * -overlapped_FormatMessage(PyObject *ignore, PyObject *args) +_overlapped_FormatMessage_impl(PyObject *module, DWORD code) +/*[clinic end generated code: output=02c964ff22407c6b input=644bb5b80326179e]*/ { - DWORD code, n; + DWORD n; WCHAR *lpMsgBuf; PyObject *res; - if (!PyArg_ParseTuple(args, F_DWORD, &code)) - return NULL; - n = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, @@ -537,19 +604,20 @@ mark_as_completed(OVERLAPPED *ov) * for overlapped I/O */ -PyDoc_STRVAR( - Overlapped_doc, - "Overlapped object"); +/*[clinic input] +@classmethod +_overlapped.Overlapped.__new__ + + event: HANDLE(c_default='INVALID_HANDLE_VALUE') = _overlapped.INVALID_HANDLE_VALUE + +OVERLAPPED structure wrapper. +[clinic start generated code]*/ static PyObject * -Overlapped_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +_overlapped_Overlapped_impl(PyTypeObject *type, HANDLE event) +/*[clinic end generated code: output=6da60504a18eb421 input=26b8a7429e629e95]*/ { OverlappedObject *self; - HANDLE event = INVALID_HANDLE_VALUE; - static char *kwlist[] = {"event", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|" F_HANDLE, kwlist, &event)) - return NULL; if (event == INVALID_HANDLE_VALUE) { event = CreateEvent(NULL, TRUE, FALSE, NULL); @@ -651,8 +719,11 @@ Overlapped_dealloc(OverlappedObject *self) } Overlapped_clear(self); - PyObject_Del(self); SetLastError(olderr); + + PyTypeObject *tp = Py_TYPE(self); + PyObject_Free(self); + Py_DECREF(tp); } @@ -719,13 +790,15 @@ unparse_address(LPSOCKADDR Address, DWORD Length) } } -PyDoc_STRVAR( - Overlapped_cancel_doc, - "cancel() -> None\n\n" - "Cancel overlapped operation"); +/*[clinic input] +_overlapped.Overlapped.cancel + +Cancel overlapped operation. +[clinic start generated code]*/ static PyObject * -Overlapped_cancel(OverlappedObject *self, PyObject *Py_UNUSED(ignored)) +_overlapped_Overlapped_cancel_impl(OverlappedObject *self) +/*[clinic end generated code: output=54ad7aeece89901c input=80eb67c7b57dbcf1]*/ { BOOL ret = TRUE; @@ -748,25 +821,27 @@ Overlapped_cancel(OverlappedObject *self, PyObject *Py_UNUSED(ignored)) Py_RETURN_NONE; } -PyDoc_STRVAR( - Overlapped_getresult_doc, - "getresult(wait=False) -> result\n\n" - "Retrieve result of operation. If wait is true then it blocks\n" - "until the operation is finished. If wait is false and the\n" - "operation is still pending then an error is raised."); +/*[clinic input] +_overlapped.Overlapped.getresult + + wait: BOOL(c_default='FALSE') = False + / + +Retrieve result of operation. + +If wait is true then it blocks until the operation is finished. If wait +is false and the operation is still pending then an error is raised. +[clinic start generated code]*/ static PyObject * -Overlapped_getresult(OverlappedObject *self, PyObject *args) +_overlapped_Overlapped_getresult_impl(OverlappedObject *self, BOOL wait) +/*[clinic end generated code: output=8c9bd04d08994f6c input=aa5b03e9897ca074]*/ { - BOOL wait = FALSE; DWORD transferred = 0; BOOL ret; DWORD err; PyObject *addr; - if (!PyArg_ParseTuple(args, "|" F_BOOL, &wait)) - return NULL; - if (self->type == TYPE_NONE) { PyErr_SetString(PyExc_ValueError, "operation not yet attempted"); return NULL; @@ -878,21 +953,23 @@ do_ReadFile(OverlappedObject *self, HANDLE handle, } } -PyDoc_STRVAR( - Overlapped_ReadFile_doc, - "ReadFile(handle, size) -> Overlapped[message]\n\n" - "Start overlapped read"); +/*[clinic input] +_overlapped.Overlapped.ReadFile + + handle: HANDLE + size: DWORD + / + +Start overlapped read. +[clinic start generated code]*/ static PyObject * -Overlapped_ReadFile(OverlappedObject *self, PyObject *args) +_overlapped_Overlapped_ReadFile_impl(OverlappedObject *self, HANDLE handle, + DWORD size) +/*[clinic end generated code: output=4c8557e16941e4ae input=98c495baa0342425]*/ { - HANDLE handle; - DWORD size; PyObject *buf; - if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD, &handle, &size)) - return NULL; - if (self->type != TYPE_NONE) { PyErr_SetString(PyExc_ValueError, "operation already attempted"); return NULL; @@ -912,20 +989,21 @@ Overlapped_ReadFile(OverlappedObject *self, PyObject *args) return do_ReadFile(self, handle, PyBytes_AS_STRING(buf), size); } -PyDoc_STRVAR( - Overlapped_ReadFileInto_doc, - "ReadFileInto(handle, buf) -> Overlapped[bytes_transferred]\n\n" - "Start overlapped receive"); +/*[clinic input] +_overlapped.Overlapped.ReadFileInto -static PyObject * -Overlapped_ReadFileInto(OverlappedObject *self, PyObject *args) -{ - HANDLE handle; - PyObject *bufobj; + handle: HANDLE + buf as bufobj: object + / - if (!PyArg_ParseTuple(args, F_HANDLE "O", &handle, &bufobj)) - return NULL; +Start overlapped receive. +[clinic start generated code]*/ +static PyObject * +_overlapped_Overlapped_ReadFileInto_impl(OverlappedObject *self, + HANDLE handle, PyObject *bufobj) +/*[clinic end generated code: output=1e9e712e742e5b2a input=16f6cc268d1d0387]*/ +{ if (self->type != TYPE_NONE) { PyErr_SetString(PyExc_ValueError, "operation already attempted"); return NULL; @@ -981,23 +1059,24 @@ do_WSARecv(OverlappedObject *self, HANDLE handle, } } -PyDoc_STRVAR( - Overlapped_WSARecv_doc, - "RecvFile(handle, size, flags) -> Overlapped[message]\n\n" - "Start overlapped receive"); +/*[clinic input] +_overlapped.Overlapped.WSARecv + + handle: HANDLE + size: DWORD + flags: DWORD = 0 + / + +Start overlapped receive. +[clinic start generated code]*/ static PyObject * -Overlapped_WSARecv(OverlappedObject *self, PyObject *args) +_overlapped_Overlapped_WSARecv_impl(OverlappedObject *self, HANDLE handle, + DWORD size, DWORD flags) +/*[clinic end generated code: output=3a5e9c61ff040906 input=8c04e506cc3d741a]*/ { - HANDLE handle; - DWORD size; - DWORD flags = 0; PyObject *buf; - if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD "|" F_DWORD, - &handle, &size, &flags)) - return NULL; - if (self->type != TYPE_NONE) { PyErr_SetString(PyExc_ValueError, "operation already attempted"); return NULL; @@ -1017,22 +1096,23 @@ Overlapped_WSARecv(OverlappedObject *self, PyObject *args) return do_WSARecv(self, handle, PyBytes_AS_STRING(buf), size, flags); } -PyDoc_STRVAR( - Overlapped_WSARecvInto_doc, - "WSARecvInto(handle, buf, flags) -> Overlapped[bytes_transferred]\n\n" - "Start overlapped receive"); +/*[clinic input] +_overlapped.Overlapped.WSARecvInto -static PyObject * -Overlapped_WSARecvInto(OverlappedObject *self, PyObject *args) -{ - HANDLE handle; - PyObject *bufobj; - DWORD flags; + handle: HANDLE + buf as bufobj: object + flags: DWORD + / - if (!PyArg_ParseTuple(args, F_HANDLE "O" F_DWORD, - &handle, &bufobj, &flags)) - return NULL; +Start overlapped receive. +[clinic start generated code]*/ +static PyObject * +_overlapped_Overlapped_WSARecvInto_impl(OverlappedObject *self, + HANDLE handle, PyObject *bufobj, + DWORD flags) +/*[clinic end generated code: output=9a438abc436fe87c input=4f87c38fc381d525]*/ +{ if (self->type != TYPE_NONE) { PyErr_SetString(PyExc_ValueError, "operation already attempted"); return NULL; @@ -1056,23 +1136,25 @@ Overlapped_WSARecvInto(OverlappedObject *self, PyObject *args) (DWORD)self->user_buffer.len, flags); } -PyDoc_STRVAR( - Overlapped_WriteFile_doc, - "WriteFile(handle, buf) -> Overlapped[bytes_transferred]\n\n" - "Start overlapped write"); +/*[clinic input] +_overlapped.Overlapped.WriteFile + + handle: HANDLE + buf as bufobj: object + / + +Start overlapped write. +[clinic start generated code]*/ static PyObject * -Overlapped_WriteFile(OverlappedObject *self, PyObject *args) +_overlapped_Overlapped_WriteFile_impl(OverlappedObject *self, HANDLE handle, + PyObject *bufobj) +/*[clinic end generated code: output=c376230b6120d877 input=b8d9a7608d8a1e72]*/ { - HANDLE handle; - PyObject *bufobj; DWORD written; BOOL ret; DWORD err; - if (!PyArg_ParseTuple(args, F_HANDLE "O", &handle, &bufobj)) - return NULL; - if (self->type != TYPE_NONE) { PyErr_SetString(PyExc_ValueError, "operation already attempted"); return NULL; @@ -1109,26 +1191,27 @@ Overlapped_WriteFile(OverlappedObject *self, PyObject *args) } } -PyDoc_STRVAR( - Overlapped_WSASend_doc, - "WSASend(handle, buf, flags) -> Overlapped[bytes_transferred]\n\n" - "Start overlapped send"); +/*[clinic input] +_overlapped.Overlapped.WSASend + + handle: HANDLE + buf as bufobj: object + flags: DWORD + / + +Start overlapped send. +[clinic start generated code]*/ static PyObject * -Overlapped_WSASend(OverlappedObject *self, PyObject *args) +_overlapped_Overlapped_WSASend_impl(OverlappedObject *self, HANDLE handle, + PyObject *bufobj, DWORD flags) +/*[clinic end generated code: output=316031c7467040cc input=932e7cba6d18f708]*/ { - HANDLE handle; - PyObject *bufobj; - DWORD flags; DWORD written; WSABUF wsabuf; int ret; DWORD err; - if (!PyArg_ParseTuple(args, F_HANDLE "O" F_DWORD, - &handle, &bufobj, &flags)) - return NULL; - if (self->type != TYPE_NONE) { PyErr_SetString(PyExc_ValueError, "operation already attempted"); return NULL; @@ -1166,26 +1249,28 @@ Overlapped_WSASend(OverlappedObject *self, PyObject *args) } } -PyDoc_STRVAR( - Overlapped_AcceptEx_doc, - "AcceptEx(listen_handle, accept_handle) -> Overlapped[address_as_bytes]\n\n" - "Start overlapped wait for client to connect"); +/*[clinic input] +_overlapped.Overlapped.AcceptEx + + listen_handle as ListenSocket: HANDLE + accept_handle as AcceptSocket: HANDLE + / + +Start overlapped wait for client to connect. +[clinic start generated code]*/ static PyObject * -Overlapped_AcceptEx(OverlappedObject *self, PyObject *args) +_overlapped_Overlapped_AcceptEx_impl(OverlappedObject *self, + HANDLE ListenSocket, + HANDLE AcceptSocket) +/*[clinic end generated code: output=9a7381d4232af889 input=b83473224fc3a1c5]*/ { - SOCKET ListenSocket; - SOCKET AcceptSocket; DWORD BytesReceived; DWORD size; PyObject *buf; BOOL ret; DWORD err; - if (!PyArg_ParseTuple(args, F_HANDLE F_HANDLE, - &ListenSocket, &AcceptSocket)) - return NULL; - if (self->type != TYPE_NONE) { PyErr_SetString(PyExc_ValueError, "operation already attempted"); return NULL; @@ -1197,12 +1282,13 @@ Overlapped_AcceptEx(OverlappedObject *self, PyObject *args) return NULL; self->type = TYPE_ACCEPT; - self->handle = (HANDLE)ListenSocket; + self->handle = ListenSocket; self->allocated_buffer = buf; Py_BEGIN_ALLOW_THREADS - ret = Py_AcceptEx(ListenSocket, AcceptSocket, PyBytes_AS_STRING(buf), - 0, size, size, &BytesReceived, &self->overlapped); + ret = Py_AcceptEx((SOCKET)ListenSocket, (SOCKET)AcceptSocket, + PyBytes_AS_STRING(buf), 0, size, size, &BytesReceived, + &self->overlapped); Py_END_ALLOW_THREADS self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError(); @@ -1220,6 +1306,7 @@ Overlapped_AcceptEx(OverlappedObject *self, PyObject *args) static int parse_address(PyObject *obj, SOCKADDR *Address, int Length) { + PyObject *Host_obj; Py_UNICODE *Host; unsigned short Port; unsigned long FlowInfo; @@ -1227,57 +1314,92 @@ parse_address(PyObject *obj, SOCKADDR *Address, int Length) memset(Address, 0, Length); - if (PyArg_ParseTuple(obj, "uH", &Host, &Port)) - { + switch (PyTuple_GET_SIZE(obj)) { + case 2: { + if (!PyArg_ParseTuple(obj, "UH", &Host_obj, &Port)) { + return -1; + } +#if USE_UNICODE_WCHAR_CACHE + Host = (wchar_t *)_PyUnicode_AsUnicode(Host_obj); +#else /* USE_UNICODE_WCHAR_CACHE */ + Host = PyUnicode_AsWideCharString(Host_obj, NULL); +#endif /* USE_UNICODE_WCHAR_CACHE */ + if (Host == NULL) { + return -1; + } Address->sa_family = AF_INET; if (WSAStringToAddressW(Host, AF_INET, NULL, Address, &Length) < 0) { SetFromWindowsErr(WSAGetLastError()); - return -1; + Length = -1; } - ((SOCKADDR_IN*)Address)->sin_port = htons(Port); + else { + ((SOCKADDR_IN*)Address)->sin_port = htons(Port); + } +#if !USE_UNICODE_WCHAR_CACHE + PyMem_Free(Host); +#endif /* USE_UNICODE_WCHAR_CACHE */ return Length; } - else if (PyArg_ParseTuple(obj, - "uHkk;ConnectEx(): illegal address_as_bytes " - "argument", &Host, &Port, &FlowInfo, &ScopeId)) - { - PyErr_Clear(); + case 4: { + if (!PyArg_ParseTuple(obj, + "UHkk;ConnectEx(): illegal address_as_bytes argument", + &Host_obj, &Port, &FlowInfo, &ScopeId)) + { + return -1; + } +#if USE_UNICODE_WCHAR_CACHE + Host = (wchar_t *)_PyUnicode_AsUnicode(Host_obj); +#else /* USE_UNICODE_WCHAR_CACHE */ + Host = PyUnicode_AsWideCharString(Host_obj, NULL); +#endif /* USE_UNICODE_WCHAR_CACHE */ + if (Host == NULL) { + return -1; + } Address->sa_family = AF_INET6; if (WSAStringToAddressW(Host, AF_INET6, NULL, Address, &Length) < 0) { SetFromWindowsErr(WSAGetLastError()); - return -1; + Length = -1; + } + else { + ((SOCKADDR_IN6*)Address)->sin6_port = htons(Port); + ((SOCKADDR_IN6*)Address)->sin6_flowinfo = FlowInfo; + ((SOCKADDR_IN6*)Address)->sin6_scope_id = ScopeId; } - ((SOCKADDR_IN6*)Address)->sin6_port = htons(Port); - ((SOCKADDR_IN6*)Address)->sin6_flowinfo = FlowInfo; - ((SOCKADDR_IN6*)Address)->sin6_scope_id = ScopeId; +#if !USE_UNICODE_WCHAR_CACHE + PyMem_Free(Host); +#endif /* USE_UNICODE_WCHAR_CACHE */ return Length; } - - return -1; + default: + PyErr_SetString(PyExc_ValueError, "illegal address_as_bytes argument"); + return -1; + } } -PyDoc_STRVAR( - Overlapped_ConnectEx_doc, - "ConnectEx(client_handle, address_as_bytes) -> Overlapped[None]\n\n" - "Start overlapped connect. client_handle should be unbound."); +/*[clinic input] +_overlapped.Overlapped.ConnectEx + + client_handle as ConnectSocket: HANDLE + address_as_bytes as AddressObj: object(subclass_of='&PyTuple_Type') + / + +Start overlapped connect. + +client_handle should be unbound. +[clinic start generated code]*/ static PyObject * -Overlapped_ConnectEx(OverlappedObject *self, PyObject *args) +_overlapped_Overlapped_ConnectEx_impl(OverlappedObject *self, + HANDLE ConnectSocket, + PyObject *AddressObj) +/*[clinic end generated code: output=5aebbbdb4f022833 input=d6bbd2d84b156fc1]*/ { - SOCKET ConnectSocket; - PyObject *AddressObj; char AddressBuf[sizeof(struct sockaddr_in6)]; SOCKADDR *Address = (SOCKADDR*)AddressBuf; int Length; BOOL ret; DWORD err; - if (!PyArg_ParseTuple(args, F_HANDLE "O!:ConnectEx", - &ConnectSocket, &PyTuple_Type, &AddressObj)) - { - return NULL; - } - if (self->type != TYPE_NONE) { PyErr_SetString(PyExc_ValueError, "operation already attempted"); return NULL; @@ -1289,10 +1411,10 @@ Overlapped_ConnectEx(OverlappedObject *self, PyObject *args) return NULL; self->type = TYPE_CONNECT; - self->handle = (HANDLE)ConnectSocket; + self->handle = ConnectSocket; Py_BEGIN_ALLOW_THREADS - ret = Py_ConnectEx(ConnectSocket, Address, Length, + ret = Py_ConnectEx((SOCKET)ConnectSocket, Address, Length, NULL, 0, NULL, &self->overlapped); Py_END_ALLOW_THREADS @@ -1307,32 +1429,33 @@ Overlapped_ConnectEx(OverlappedObject *self, PyObject *args) } } -PyDoc_STRVAR( - Overlapped_DisconnectEx_doc, - "DisconnectEx(handle, flags) -> Overlapped[None]\n\n" - "Start overlapped connect. client_handle should be unbound."); +/*[clinic input] +_overlapped.Overlapped.DisconnectEx + + handle as Socket: HANDLE + flags: DWORD + / + +[clinic start generated code]*/ static PyObject * -Overlapped_DisconnectEx(OverlappedObject *self, PyObject *args) +_overlapped_Overlapped_DisconnectEx_impl(OverlappedObject *self, + HANDLE Socket, DWORD flags) +/*[clinic end generated code: output=8d64ddb8c93c2126 input=680845cdcdf820eb]*/ { - SOCKET Socket; - DWORD flags; BOOL ret; DWORD err; - if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD, &Socket, &flags)) - return NULL; - if (self->type != TYPE_NONE) { PyErr_SetString(PyExc_ValueError, "operation already attempted"); return NULL; } self->type = TYPE_DISCONNECT; - self->handle = (HANDLE)Socket; + self->handle = Socket; Py_BEGIN_ALLOW_THREADS - ret = Py_DisconnectEx(Socket, &self->overlapped, flags, 0); + ret = Py_DisconnectEx((SOCKET)Socket, &self->overlapped, flags, 0); Py_END_ALLOW_THREADS self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError(); @@ -1346,48 +1469,45 @@ Overlapped_DisconnectEx(OverlappedObject *self, PyObject *args) } } -PyDoc_STRVAR( - Overlapped_TransmitFile_doc, - "TransmitFile(socket, file, offset, offset_high, " - "count_to_write, count_per_send, flags) " - "-> Overlapped[None]\n\n" - "Transmit file data over a connected socket."); +/*[clinic input] +_overlapped.Overlapped.TransmitFile + + socket as Socket: HANDLE + file as File: HANDLE + offset: DWORD + offset_high: DWORD + count_to_write: DWORD + count_per_send: DWORD + flags: DWORD + / + +Transmit file data over a connected socket. +[clinic start generated code]*/ static PyObject * -Overlapped_TransmitFile(OverlappedObject *self, PyObject *args) +_overlapped_Overlapped_TransmitFile_impl(OverlappedObject *self, + HANDLE Socket, HANDLE File, + DWORD offset, DWORD offset_high, + DWORD count_to_write, + DWORD count_per_send, DWORD flags) +/*[clinic end generated code: output=03f3ca5512e678fd input=7e6f97b391f60e8c]*/ { - SOCKET Socket; - HANDLE File; - DWORD offset; - DWORD offset_high; - DWORD count_to_write; - DWORD count_per_send; - DWORD flags; BOOL ret; DWORD err; - if (!PyArg_ParseTuple(args, - F_HANDLE F_HANDLE F_DWORD F_DWORD - F_DWORD F_DWORD F_DWORD, - &Socket, &File, &offset, &offset_high, - &count_to_write, &count_per_send, - &flags)) - return NULL; - if (self->type != TYPE_NONE) { PyErr_SetString(PyExc_ValueError, "operation already attempted"); return NULL; } self->type = TYPE_TRANSMIT_FILE; - self->handle = (HANDLE)Socket; + self->handle = Socket; self->overlapped.Offset = offset; self->overlapped.OffsetHigh = offset_high; Py_BEGIN_ALLOW_THREADS - ret = Py_TransmitFile(Socket, File, count_to_write, count_per_send, - &self->overlapped, - NULL, flags); + ret = Py_TransmitFile((SOCKET)Socket, File, count_to_write, + count_per_send, &self->overlapped, NULL, flags); Py_END_ALLOW_THREADS self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError(); @@ -1401,21 +1521,23 @@ Overlapped_TransmitFile(OverlappedObject *self, PyObject *args) } } -PyDoc_STRVAR( - Overlapped_ConnectNamedPipe_doc, - "ConnectNamedPipe(handle) -> Overlapped[None]\n\n" - "Start overlapped wait for a client to connect."); +/*[clinic input] +_overlapped.Overlapped.ConnectNamedPipe + + handle as Pipe: HANDLE + / + +Start overlapped wait for a client to connect. +[clinic start generated code]*/ static PyObject * -Overlapped_ConnectNamedPipe(OverlappedObject *self, PyObject *args) +_overlapped_Overlapped_ConnectNamedPipe_impl(OverlappedObject *self, + HANDLE Pipe) +/*[clinic end generated code: output=3e69adfe55818abe input=8b0d4cef8a72f7bc]*/ { - HANDLE Pipe; BOOL ret; DWORD err; - if (!PyArg_ParseTuple(args, F_HANDLE, &Pipe)) - return NULL; - if (self->type != TYPE_NONE) { PyErr_SetString(PyExc_ValueError, "operation already attempted"); return NULL; @@ -1442,25 +1564,22 @@ Overlapped_ConnectNamedPipe(OverlappedObject *self, PyObject *args) } } -PyDoc_STRVAR( - ConnectPipe_doc, - "ConnectPipe(addr) -> pipe_handle\n\n" - "Connect to the pipe for asynchronous I/O (overlapped)."); +/*[clinic input] +_overlapped.Overlapped.ConnectPipe + + addr as Address: Py_UNICODE + / + +Connect to the pipe for asynchronous I/O (overlapped). +[clinic start generated code]*/ static PyObject * -overlapped_ConnectPipe(PyObject *self, PyObject *args) +_overlapped_Overlapped_ConnectPipe_impl(OverlappedObject *self, + const Py_UNICODE *Address) +/*[clinic end generated code: output=3cc9661667d459d4 input=167c06a274efcefc]*/ { - PyObject *AddressObj; - wchar_t *Address; HANDLE PipeHandle; - if (!PyArg_ParseTuple(args, "U", &AddressObj)) - return NULL; - - Address = PyUnicode_AsWideCharString(AddressObj, NULL); - if (Address == NULL) - return NULL; - Py_BEGIN_ALLOW_THREADS PipeHandle = CreateFileW(Address, GENERIC_READ | GENERIC_WRITE, @@ -1468,7 +1587,6 @@ overlapped_ConnectPipe(PyObject *self, PyObject *args) FILE_FLAG_OVERLAPPED, NULL); Py_END_ALLOW_THREADS - PyMem_Free(Address); if (PipeHandle == INVALID_HANDLE_VALUE) return SetFromWindowsErr(0); return Py_BuildValue(F_HANDLE, PipeHandle); @@ -1503,41 +1621,39 @@ Overlapped_traverse(OverlappedObject *self, visitproc visit, void *arg) } break; case TYPE_READ_FROM: - if(self->read_from.result) { - Py_VISIT(self->read_from.result); - } - if(self->read_from.allocated_buffer) { - Py_VISIT(self->read_from.allocated_buffer); - } + Py_VISIT(self->read_from.result); + Py_VISIT(self->read_from.allocated_buffer); } return 0; } // UDP functions -PyDoc_STRVAR( - WSAConnect_doc, - "WSAConnect(client_handle, address_as_bytes) -> Overlapped[None]\n\n" - "Bind a remote address to a connectionless (UDP) socket"); - /* * Note: WSAConnect does not support Overlapped I/O so this function should * _only_ be used for connectionless sockets (UDP). */ + +/*[clinic input] +_overlapped.WSAConnect + + client_handle as ConnectSocket: HANDLE + address_as_bytes as AddressObj: object + / + +Bind a remote address to a connectionless (UDP) socket. +[clinic start generated code]*/ + static PyObject * -overlapped_WSAConnect(PyObject *self, PyObject *args) +_overlapped_WSAConnect_impl(PyObject *module, HANDLE ConnectSocket, + PyObject *AddressObj) +/*[clinic end generated code: output=ea0b4391e94dad63 input=169f8075e9ae7fa4]*/ { - SOCKET ConnectSocket; - PyObject *AddressObj; char AddressBuf[sizeof(struct sockaddr_in6)]; SOCKADDR *Address = (SOCKADDR*)AddressBuf; int Length; int err; - if (!PyArg_ParseTuple(args, F_HANDLE "O", &ConnectSocket, &AddressObj)) { - return NULL; - } - Length = sizeof(AddressBuf); Length = parse_address(AddressObj, Address, Length); if (Length < 0) { @@ -1547,7 +1663,7 @@ overlapped_WSAConnect(PyObject *self, PyObject *args) Py_BEGIN_ALLOW_THREADS // WSAConnect does not support overlapped I/O so this call will // successfully complete immediately. - err = WSAConnect(ConnectSocket, Address, Length, + err = WSAConnect((SOCKET)ConnectSocket, Address, Length, NULL, NULL, NULL, NULL); Py_END_ALLOW_THREADS @@ -1559,19 +1675,24 @@ overlapped_WSAConnect(PyObject *self, PyObject *args) } } -PyDoc_STRVAR( - Overlapped_WSASendTo_doc, - "WSASendTo(handle, buf, flags, address_as_bytes) -> " - "Overlapped[bytes_transferred]\n\n" - "Start overlapped sendto over a connectionless (UDP) socket"); +/*[clinic input] +_overlapped.Overlapped.WSASendTo + + handle: HANDLE + buf as bufobj: object + flags: DWORD + address_as_bytes as AddressObj: object + / + +Start overlapped sendto over a connectionless (UDP) socket. +[clinic start generated code]*/ static PyObject * -Overlapped_WSASendTo(OverlappedObject *self, PyObject *args) +_overlapped_Overlapped_WSASendTo_impl(OverlappedObject *self, HANDLE handle, + PyObject *bufobj, DWORD flags, + PyObject *AddressObj) +/*[clinic end generated code: output=fe0ff55eb60d65e1 input=f709e6ecebd9bc18]*/ { - HANDLE handle; - PyObject *bufobj; - DWORD flags; - PyObject *AddressObj; char AddressBuf[sizeof(struct sockaddr_in6)]; SOCKADDR *Address = (SOCKADDR*)AddressBuf; int AddressLength; @@ -1580,12 +1701,6 @@ Overlapped_WSASendTo(OverlappedObject *self, PyObject *args) int ret; DWORD err; - if (!PyArg_ParseTuple(args, F_HANDLE "O" F_DWORD "O", - &handle, &bufobj, &flags, &AddressObj)) - { - return NULL; - } - // Parse the "to" address AddressLength = sizeof(AddressBuf); AddressLength = parse_address(AddressObj, Address, AddressLength); @@ -1640,24 +1755,29 @@ PyDoc_STRVAR( "RecvFile(handle, size, flags) -> Overlapped[(message, (host, port))]\n\n" "Start overlapped receive"); +/*[clinic input] +_overlapped.Overlapped.WSARecvFrom + + handle: HANDLE + size: DWORD + flags: DWORD = 0 + / + +Start overlapped receive. +[clinic start generated code]*/ + static PyObject * -Overlapped_WSARecvFrom(OverlappedObject *self, PyObject *args) +_overlapped_Overlapped_WSARecvFrom_impl(OverlappedObject *self, + HANDLE handle, DWORD size, + DWORD flags) +/*[clinic end generated code: output=13832a2025b86860 input=1b2663fa130e0286]*/ { - HANDLE handle; - DWORD size; - DWORD flags = 0; DWORD nread; PyObject *buf; WSABUF wsabuf; int ret; DWORD err; - if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD "|" F_DWORD, - &handle, &size, &flags)) - { - return NULL; - } - if (self->type != TYPE_NONE) { PyErr_SetString(PyExc_ValueError, "operation already attempted"); return NULL; @@ -1703,38 +1823,24 @@ Overlapped_WSARecvFrom(OverlappedObject *self, PyObject *args) } } +#include "clinic/overlapped.c.h" static PyMethodDef Overlapped_methods[] = { - {"getresult", (PyCFunction) Overlapped_getresult, - METH_VARARGS, Overlapped_getresult_doc}, - {"cancel", (PyCFunction) Overlapped_cancel, - METH_NOARGS, Overlapped_cancel_doc}, - {"ReadFile", (PyCFunction) Overlapped_ReadFile, - METH_VARARGS, Overlapped_ReadFile_doc}, - {"ReadFileInto", (PyCFunction) Overlapped_ReadFileInto, - METH_VARARGS, Overlapped_ReadFileInto_doc}, - {"WSARecv", (PyCFunction) Overlapped_WSARecv, - METH_VARARGS, Overlapped_WSARecv_doc}, - {"WSARecvInto", (PyCFunction) Overlapped_WSARecvInto, - METH_VARARGS, Overlapped_WSARecvInto_doc}, - {"WriteFile", (PyCFunction) Overlapped_WriteFile, - METH_VARARGS, Overlapped_WriteFile_doc}, - {"WSASend", (PyCFunction) Overlapped_WSASend, - METH_VARARGS, Overlapped_WSASend_doc}, - {"AcceptEx", (PyCFunction) Overlapped_AcceptEx, - METH_VARARGS, Overlapped_AcceptEx_doc}, - {"ConnectEx", (PyCFunction) Overlapped_ConnectEx, - METH_VARARGS, Overlapped_ConnectEx_doc}, - {"DisconnectEx", (PyCFunction) Overlapped_DisconnectEx, - METH_VARARGS, Overlapped_DisconnectEx_doc}, - {"TransmitFile", (PyCFunction) Overlapped_TransmitFile, - METH_VARARGS, Overlapped_TransmitFile_doc}, - {"ConnectNamedPipe", (PyCFunction) Overlapped_ConnectNamedPipe, - METH_VARARGS, Overlapped_ConnectNamedPipe_doc}, - {"WSARecvFrom", (PyCFunction) Overlapped_WSARecvFrom, - METH_VARARGS, Overlapped_WSARecvFrom_doc }, - {"WSASendTo", (PyCFunction) Overlapped_WSASendTo, - METH_VARARGS, Overlapped_WSASendTo_doc }, + _OVERLAPPED_OVERLAPPED_GETRESULT_METHODDEF + _OVERLAPPED_OVERLAPPED_CANCEL_METHODDEF + _OVERLAPPED_OVERLAPPED_READFILE_METHODDEF + _OVERLAPPED_OVERLAPPED_READFILEINTO_METHODDEF + _OVERLAPPED_OVERLAPPED_WSARECV_METHODDEF + _OVERLAPPED_OVERLAPPED_WSARECVINTO_METHODDEF + _OVERLAPPED_OVERLAPPED_WRITEFILE_METHODDEF + _OVERLAPPED_OVERLAPPED_WSASEND_METHODDEF + _OVERLAPPED_OVERLAPPED_ACCEPTEX_METHODDEF + _OVERLAPPED_OVERLAPPED_CONNECTEX_METHODDEF + _OVERLAPPED_OVERLAPPED_DISCONNECTEX_METHODDEF + _OVERLAPPED_OVERLAPPED_TRANSMITFILE_METHODDEF + _OVERLAPPED_OVERLAPPED_CONNECTNAMEDPIPE_METHODDEF + _OVERLAPPED_OVERLAPPED_WSARECVFROM_METHODDEF + _OVERLAPPED_OVERLAPPED_WSASENDTO_METHODDEF {NULL} }; @@ -1756,112 +1862,100 @@ static PyGetSetDef Overlapped_getsets[] = { {NULL}, }; -PyTypeObject OverlappedType = { - PyVarObject_HEAD_INIT(NULL, 0) - /* tp_name */ "_overlapped.Overlapped", - /* tp_basicsize */ sizeof(OverlappedObject), - /* tp_itemsize */ 0, - /* tp_dealloc */ (destructor) Overlapped_dealloc, - /* tp_vectorcall_offset */ 0, - /* tp_getattr */ 0, - /* tp_setattr */ 0, - /* tp_as_async */ 0, - /* tp_repr */ 0, - /* tp_as_number */ 0, - /* tp_as_sequence */ 0, - /* tp_as_mapping */ 0, - /* tp_hash */ 0, - /* tp_call */ 0, - /* tp_str */ 0, - /* tp_getattro */ 0, - /* tp_setattro */ 0, - /* tp_as_buffer */ 0, - /* tp_flags */ Py_TPFLAGS_DEFAULT, - /* tp_doc */ "OVERLAPPED structure wrapper", - /* tp_traverse */ (traverseproc)Overlapped_traverse, - /* tp_clear */ 0, - /* tp_richcompare */ 0, - /* tp_weaklistoffset */ 0, - /* tp_iter */ 0, - /* tp_iternext */ 0, - /* tp_methods */ Overlapped_methods, - /* tp_members */ Overlapped_members, - /* tp_getset */ Overlapped_getsets, - /* tp_base */ 0, - /* tp_dict */ 0, - /* tp_descr_get */ 0, - /* tp_descr_set */ 0, - /* tp_dictoffset */ 0, - /* tp_init */ 0, - /* tp_alloc */ 0, - /* tp_new */ Overlapped_new, +static PyType_Slot overlapped_type_slots[] = { + {Py_tp_dealloc, Overlapped_dealloc}, + {Py_tp_doc, (char *)_overlapped_Overlapped__doc__}, + {Py_tp_traverse, Overlapped_traverse}, + {Py_tp_methods, Overlapped_methods}, + {Py_tp_members, Overlapped_members}, + {Py_tp_getset, Overlapped_getsets}, + {Py_tp_new, _overlapped_Overlapped}, + {0,0} +}; + +static PyType_Spec overlapped_type_spec = { + .name = "_overlapped.Overlapped", + .basicsize = sizeof(OverlappedObject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE), + .slots = overlapped_type_slots }; static PyMethodDef overlapped_functions[] = { - {"CreateIoCompletionPort", overlapped_CreateIoCompletionPort, - METH_VARARGS, CreateIoCompletionPort_doc}, - {"GetQueuedCompletionStatus", overlapped_GetQueuedCompletionStatus, - METH_VARARGS, GetQueuedCompletionStatus_doc}, - {"PostQueuedCompletionStatus", overlapped_PostQueuedCompletionStatus, - METH_VARARGS, PostQueuedCompletionStatus_doc}, - {"FormatMessage", overlapped_FormatMessage, - METH_VARARGS, FormatMessage_doc}, - {"BindLocal", overlapped_BindLocal, - METH_VARARGS, BindLocal_doc}, - {"RegisterWaitWithQueue", overlapped_RegisterWaitWithQueue, - METH_VARARGS, RegisterWaitWithQueue_doc}, - {"UnregisterWait", overlapped_UnregisterWait, - METH_VARARGS, UnregisterWait_doc}, - {"UnregisterWaitEx", overlapped_UnregisterWaitEx, - METH_VARARGS, UnregisterWaitEx_doc}, - {"CreateEvent", overlapped_CreateEvent, - METH_VARARGS, CreateEvent_doc}, - {"SetEvent", overlapped_SetEvent, - METH_VARARGS, SetEvent_doc}, - {"ResetEvent", overlapped_ResetEvent, - METH_VARARGS, ResetEvent_doc}, - {"ConnectPipe", overlapped_ConnectPipe, - METH_VARARGS, ConnectPipe_doc}, - {"WSAConnect", overlapped_WSAConnect, - METH_VARARGS, WSAConnect_doc}, + _OVERLAPPED_CREATEIOCOMPLETIONPORT_METHODDEF + _OVERLAPPED_GETQUEUEDCOMPLETIONSTATUS_METHODDEF + _OVERLAPPED_POSTQUEUEDCOMPLETIONSTATUS_METHODDEF + _OVERLAPPED_FORMATMESSAGE_METHODDEF + _OVERLAPPED_BINDLOCAL_METHODDEF + _OVERLAPPED_REGISTERWAITWITHQUEUE_METHODDEF + _OVERLAPPED_UNREGISTERWAIT_METHODDEF + _OVERLAPPED_UNREGISTERWAITEX_METHODDEF + _OVERLAPPED_CREATEEVENT_METHODDEF + _OVERLAPPED_SETEVENT_METHODDEF + _OVERLAPPED_RESETEVENT_METHODDEF + _OVERLAPPED_OVERLAPPED_CONNECTPIPE_METHODDEF + _OVERLAPPED_WSACONNECT_METHODDEF {NULL} }; -static struct PyModuleDef overlapped_module = { - PyModuleDef_HEAD_INIT, - "_overlapped", - NULL, - -1, - overlapped_functions, - NULL, - NULL, - NULL, - NULL -}; +static int +overlapped_traverse(PyObject *module, visitproc visit, void *arg) +{ + OverlappedState *state = overlapped_get_state(module); + Py_VISIT(state->overlapped_type); + return 0; +} -#define WINAPI_CONSTANT(fmt, con) \ - PyDict_SetItemString(d, #con, Py_BuildValue(fmt, con)) +static int +overlapped_clear(PyObject *module) +{ + OverlappedState *state = overlapped_get_state(module); + Py_CLEAR(state->overlapped_type); + return 0; +} -PyMODINIT_FUNC -PyInit__overlapped(void) +static void +overlapped_free(void *module) { - PyObject *m, *d; + overlapped_clear((PyObject *)module); +} +#define WINAPI_CONSTANT(fmt, con) \ + do { \ + PyObject *value = Py_BuildValue(fmt, con); \ + if (value == NULL) { \ + return -1; \ + } \ + if (PyModule_AddObject(module, #con, value) < 0 ) { \ + Py_DECREF(value); \ + return -1; \ + } \ + } while (0) + +static int +overlapped_exec(PyObject *module) +{ /* Ensure WSAStartup() called before initializing function pointers */ - m = PyImport_ImportModule("_socket"); - if (!m) - return NULL; - Py_DECREF(m); + PyObject *socket_module = PyImport_ImportModule("_socket"); + if (!socket_module) { + return -1; + } - if (initialize_function_pointers() < 0) - return NULL; + Py_DECREF(socket_module); - m = PyModule_Create(&overlapped_module); - if (PyModule_AddType(m, &OverlappedType) < 0) { - return NULL; + if (initialize_function_pointers() < 0) { + return -1; } - d = PyModule_GetDict(m); + OverlappedState *st = overlapped_get_state(module); + st->overlapped_type = (PyTypeObject *)PyType_FromModuleAndSpec( + module, &overlapped_type_spec, NULL); + if (st->overlapped_type == NULL) { + return -1; + } + + if (PyModule_AddType(module, st->overlapped_type) < 0) { + return -1; + } WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING); WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED); @@ -1875,5 +1969,27 @@ PyInit__overlapped(void) WINAPI_CONSTANT(F_DWORD, SO_UPDATE_CONNECT_CONTEXT); WINAPI_CONSTANT(F_DWORD, TF_REUSE_SOCKET); - return m; + return 0; +} + +static PyModuleDef_Slot overlapped_slots[] = { + {Py_mod_exec, overlapped_exec}, + {0, NULL} +}; + +static struct PyModuleDef overlapped_module = { + PyModuleDef_HEAD_INIT, + .m_name = "_overlapped", + .m_size = sizeof(OverlappedState), + .m_methods = overlapped_functions, + .m_slots = overlapped_slots, + .m_traverse = overlapped_traverse, + .m_clear = overlapped_clear, + .m_free = overlapped_free +}; + +PyMODINIT_FUNC +PyInit__overlapped(void) +{ + return PyModuleDef_Init(&overlapped_module); } diff --git a/contrib/tools/python3/src/Modules/parsermodule.c b/contrib/tools/python3/src/Modules/parsermodule.c deleted file mode 100644 index 24b0ffbe36..0000000000 --- a/contrib/tools/python3/src/Modules/parsermodule.c +++ /dev/null @@ -1,1222 +0,0 @@ -/* parsermodule.c - * - * Copyright 1995-1996 by Fred L. Drake, Jr. and Virginia Polytechnic - * Institute and State University, Blacksburg, Virginia, USA. - * Portions copyright 1991-1995 by Stichting Mathematisch Centrum, - * Amsterdam, The Netherlands. Copying is permitted under the terms - * associated with the main Python distribution, with the additional - * restriction that this additional notice be included and maintained - * on all distributed copies. - * - * This module serves to replace the original parser module written - * by Guido. The functionality is not matched precisely, but the - * original may be implemented on top of this. This is desirable - * since the source of the text to be parsed is now divorced from - * this interface. - * - * Unlike the prior interface, the ability to give a parse tree - * produced by Python code as a tuple to the compiler is enabled by - * this module. See the documentation for more details. - * - * I've added some annotations that help with the lint code-checking - * program, but they're not complete by a long shot. The real errors - * that lint detects are gone, but there are still warnings with - * Py_[X]DECREF() and Py_[X]INCREF() macros. The lint annotations - * look like "NOTE(...)". - * - */ - -#include "Python.h" /* general Python API */ -#include "Python-ast.h" /* mod_ty */ -#undef Yield /* undefine macro conflicting with <winbase.h> */ -#include "ast.h" -#include "graminit.h" /* symbols defined in the grammar */ -#include "node.h" /* internal parser structure */ -#include "errcode.h" /* error codes for PyNode_*() */ -#include "token.h" /* token definitions */ - /* ISTERMINAL() / ISNONTERMINAL() */ -#include "grammar.h" -#include "parsetok.h" - -extern grammar _PyParser_Grammar; /* From graminit.c */ - -#ifdef lint -#include <note.h> -#else -#define NOTE(x) -#endif - -/* String constants used to initialize module attributes. - * - */ -static const char parser_copyright_string[] = -"Copyright 1995-1996 by Virginia Polytechnic Institute & State\n\ -University, Blacksburg, Virginia, USA, and Fred L. Drake, Jr., Reston,\n\ -Virginia, USA. Portions copyright 1991-1995 by Stichting Mathematisch\n\ -Centrum, Amsterdam, The Netherlands."; - - -PyDoc_STRVAR(parser_doc_string, -"This is an interface to Python's internal parser."); - -static const char parser_version_string[] = "0.5"; - - -typedef PyObject* (*SeqMaker) (Py_ssize_t length); -typedef int (*SeqInserter) (PyObject* sequence, - Py_ssize_t index, - PyObject* element); - -/* The function below is copyrighted by Stichting Mathematisch Centrum. The - * original copyright statement is included below, and continues to apply - * in full to the function immediately following. All other material is - * original, copyrighted by Fred L. Drake, Jr. and Virginia Polytechnic - * Institute and State University. Changes were made to comply with the - * new naming conventions. Added arguments to provide support for creating - * lists as well as tuples, and optionally including the line numbers. - */ - - -static PyObject* -node2tuple(node *n, /* node to convert */ - SeqMaker mkseq, /* create sequence */ - SeqInserter addelem, /* func. to add elem. in seq. */ - int lineno, /* include line numbers? */ - int col_offset) /* include column offsets? */ -{ - PyObject *result = NULL, *w; - - if (n == NULL) { - Py_RETURN_NONE; - } - - if (ISNONTERMINAL(TYPE(n))) { - int i; - - result = mkseq(1 + NCH(n) + (TYPE(n) == encoding_decl)); - if (result == NULL) - goto error; - - w = PyLong_FromLong(TYPE(n)); - if (w == NULL) - goto error; - (void) addelem(result, 0, w); - - for (i = 0; i < NCH(n); i++) { - w = node2tuple(CHILD(n, i), mkseq, addelem, lineno, col_offset); - if (w == NULL) - goto error; - (void) addelem(result, i+1, w); - } - - if (TYPE(n) == encoding_decl) { - w = PyUnicode_FromString(STR(n)); - if (w == NULL) - goto error; - (void) addelem(result, i+1, w); - } - } - else if (ISTERMINAL(TYPE(n))) { - result = mkseq(2 + lineno + col_offset); - if (result == NULL) - goto error; - - w = PyLong_FromLong(TYPE(n)); - if (w == NULL) - goto error; - (void) addelem(result, 0, w); - - w = PyUnicode_FromString(STR(n)); - if (w == NULL) - goto error; - (void) addelem(result, 1, w); - - if (lineno) { - w = PyLong_FromLong(n->n_lineno); - if (w == NULL) - goto error; - (void) addelem(result, 2, w); - } - - if (col_offset) { - w = PyLong_FromLong(n->n_col_offset); - if (w == NULL) - goto error; - (void) addelem(result, 2 + lineno, w); - } - } - else { - PyErr_SetString(PyExc_SystemError, - "unrecognized parse tree node type"); - return ((PyObject*) NULL); - } - return result; - -error: - Py_XDECREF(result); - return NULL; -} -/* - * End of material copyrighted by Stichting Mathematisch Centrum. - */ - - - -/* There are two types of intermediate objects we're interested in: - * 'eval' and 'exec' types. These constants can be used in the st_type - * field of the object type to identify which any given object represents. - * These should probably go in an external header to allow other extensions - * to use them, but then, we really should be using C++ too. ;-) - */ - -#define PyST_EXPR 1 -#define PyST_SUITE 2 - - -/* These are the internal objects and definitions required to implement the - * ST type. Most of the internal names are more reminiscent of the 'old' - * naming style, but the code uses the new naming convention. - */ - -static PyObject* -parser_error = 0; - - -typedef struct { - PyObject_HEAD /* standard object header */ - node* st_node; /* the node* returned by the parser */ - int st_type; /* EXPR or SUITE ? */ - PyCompilerFlags st_flags; /* Parser and compiler flags */ -} PyST_Object; - - -static void parser_free(PyST_Object *st); -static PyObject* parser_sizeof(PyST_Object *, void *); -static PyObject* parser_richcompare(PyObject *left, PyObject *right, int op); -static PyObject* parser_compilest(PyST_Object *, PyObject *, PyObject *); -static PyObject* parser_isexpr(PyST_Object *, PyObject *, PyObject *); -static PyObject* parser_issuite(PyST_Object *, PyObject *, PyObject *); -static PyObject* parser_st2list(PyST_Object *, PyObject *, PyObject *); -static PyObject* parser_st2tuple(PyST_Object *, PyObject *, PyObject *); - -#define PUBLIC_METHOD_TYPE (METH_VARARGS|METH_KEYWORDS) - -static PyMethodDef parser_methods[] = { - {"compile", (PyCFunction)(void(*)(void))parser_compilest, PUBLIC_METHOD_TYPE, - PyDoc_STR("Compile this ST object into a code object.")}, - {"isexpr", (PyCFunction)(void(*)(void))parser_isexpr, PUBLIC_METHOD_TYPE, - PyDoc_STR("Determines if this ST object was created from an expression.")}, - {"issuite", (PyCFunction)(void(*)(void))parser_issuite, PUBLIC_METHOD_TYPE, - PyDoc_STR("Determines if this ST object was created from a suite.")}, - {"tolist", (PyCFunction)(void(*)(void))parser_st2list, PUBLIC_METHOD_TYPE, - PyDoc_STR("Creates a list-tree representation of this ST.")}, - {"totuple", (PyCFunction)(void(*)(void))parser_st2tuple, PUBLIC_METHOD_TYPE, - PyDoc_STR("Creates a tuple-tree representation of this ST.")}, - {"__sizeof__", (PyCFunction)parser_sizeof, METH_NOARGS, - PyDoc_STR("Returns size in memory, in bytes.")}, - {NULL, NULL, 0, NULL} -}; - -static -PyTypeObject PyST_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "parser.st", /* tp_name */ - (int) sizeof(PyST_Object), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)parser_free, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - - /* Functions to access object as input/output buffer */ - 0, /* tp_as_buffer */ - - Py_TPFLAGS_DEFAULT, /* tp_flags */ - - /* __doc__ */ - "Intermediate representation of a Python parse tree.", - 0, /* tp_traverse */ - 0, /* tp_clear */ - parser_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - parser_methods, /* tp_methods */ -}; /* PyST_Type */ - - -/* PyST_Type isn't subclassable, so just check ob_type */ -#define PyST_Object_Check(v) Py_IS_TYPE(v, &PyST_Type) - -static int -parser_compare_nodes(node *left, node *right) -{ - int j; - - if (TYPE(left) < TYPE(right)) - return (-1); - - if (TYPE(right) < TYPE(left)) - return (1); - - if (ISTERMINAL(TYPE(left))) - return (strcmp(STR(left), STR(right))); - - if (NCH(left) < NCH(right)) - return (-1); - - if (NCH(right) < NCH(left)) - return (1); - - for (j = 0; j < NCH(left); ++j) { - int v = parser_compare_nodes(CHILD(left, j), CHILD(right, j)); - - if (v != 0) - return (v); - } - return (0); -} - -/* parser_richcompare(PyObject* left, PyObject* right, int op) - * - * Comparison function used by the Python operators ==, !=, <, >, <=, >= - * This really just wraps a call to parser_compare_nodes() with some easy - * checks and protection code. - * - */ - -static PyObject * -parser_richcompare(PyObject *left, PyObject *right, int op) -{ - int result; - - /* neither argument should be NULL, unless something's gone wrong */ - if (left == NULL || right == NULL) { - PyErr_BadInternalCall(); - return NULL; - } - - /* both arguments should be instances of PyST_Object */ - if (!PyST_Object_Check(left) || !PyST_Object_Check(right)) { - Py_RETURN_NOTIMPLEMENTED; - } - - if (left == right) - /* if arguments are identical, they're equal */ - result = 0; - else - result = parser_compare_nodes(((PyST_Object *)left)->st_node, - ((PyST_Object *)right)->st_node); - - Py_RETURN_RICHCOMPARE(result, 0, op); -} - -/* parser_newstobject(node* st) - * - * Allocates a new Python object representing an ST. This is simply the - * 'wrapper' object that holds a node* and allows it to be passed around in - * Python code. - * - */ -static PyObject* -parser_newstobject(node *st, int type) -{ - PyST_Object* o = PyObject_New(PyST_Object, &PyST_Type); - - if (o != 0) { - o->st_node = st; - o->st_type = type; - o->st_flags = _PyCompilerFlags_INIT; - } - else { - PyNode_Free(st); - } - return ((PyObject*)o); -} - - -/* void parser_free(PyST_Object* st) - * - * This is called by a del statement that reduces the reference count to 0. - * - */ -static void -parser_free(PyST_Object *st) -{ - PyNode_Free(st->st_node); - PyObject_Del(st); -} - -static PyObject * -parser_sizeof(PyST_Object *st, void *unused) -{ - Py_ssize_t res; - - res = _PyObject_SIZE(Py_TYPE(st)) + _PyNode_SizeOf(st->st_node); - return PyLong_FromSsize_t(res); -} - - -/* parser_st2tuple(PyObject* self, PyObject* args, PyObject* kw) - * - * This provides conversion from a node* to a tuple object that can be - * returned to the Python-level caller. The ST object is not modified. - * - */ -static PyObject* -parser_st2tuple(PyST_Object *self, PyObject *args, PyObject *kw) -{ - int line_info = 0; - int col_info = 0; - PyObject *res = 0; - int ok; - - static char *keywords[] = {"st", "line_info", "col_info", NULL}; - - if (self == NULL || PyModule_Check(self)) { - ok = PyArg_ParseTupleAndKeywords(args, kw, "O!|pp:st2tuple", keywords, - &PyST_Type, &self, &line_info, - &col_info); - } - else - ok = PyArg_ParseTupleAndKeywords(args, kw, "|pp:totuple", &keywords[1], - &line_info, &col_info); - if (ok != 0) { - /* - * Convert ST into a tuple representation. Use Guido's function, - * since it's known to work already. - */ - res = node2tuple(((PyST_Object*)self)->st_node, - PyTuple_New, PyTuple_SetItem, line_info, col_info); - } - return (res); -} - - -/* parser_st2list(PyObject* self, PyObject* args, PyObject* kw) - * - * This provides conversion from a node* to a list object that can be - * returned to the Python-level caller. The ST object is not modified. - * - */ -static PyObject* -parser_st2list(PyST_Object *self, PyObject *args, PyObject *kw) -{ - int line_info = 0; - int col_info = 0; - PyObject *res = 0; - int ok; - - static char *keywords[] = {"st", "line_info", "col_info", NULL}; - - if (self == NULL || PyModule_Check(self)) - ok = PyArg_ParseTupleAndKeywords(args, kw, "O!|pp:st2list", keywords, - &PyST_Type, &self, &line_info, - &col_info); - else - ok = PyArg_ParseTupleAndKeywords(args, kw, "|pp:tolist", &keywords[1], - &line_info, &col_info); - if (ok) { - /* - * Convert ST into a tuple representation. Use Guido's function, - * since it's known to work already. - */ - res = node2tuple(self->st_node, - PyList_New, PyList_SetItem, line_info, col_info); - } - return (res); -} - - -/* parser_compilest(PyObject* self, PyObject* args) - * - * This function creates code objects from the parse tree represented by - * the passed-in data object. An optional file name is passed in as well. - * - */ -static PyObject* -parser_compilest(PyST_Object *self, PyObject *args, PyObject *kw) -{ - PyObject* res = NULL; - PyArena* arena = NULL; - mod_ty mod; - PyObject* filename = NULL; - int ok; - - static char *keywords[] = {"st", "filename", NULL}; - - if (self == NULL || PyModule_Check(self)) - ok = PyArg_ParseTupleAndKeywords(args, kw, "O!|O&:compilest", keywords, - &PyST_Type, &self, - PyUnicode_FSDecoder, &filename); - else - ok = PyArg_ParseTupleAndKeywords(args, kw, "|O&:compile", &keywords[1], - PyUnicode_FSDecoder, &filename); - if (!ok) - goto error; - - if (filename == NULL) { - filename = PyUnicode_FromString("<syntax-tree>"); - if (filename == NULL) - goto error; - } - - arena = PyArena_New(); - if (!arena) - goto error; - - mod = PyAST_FromNodeObject(self->st_node, &self->st_flags, - filename, arena); - if (!mod) - goto error; - - res = (PyObject *)PyAST_CompileObject(mod, filename, - &self->st_flags, -1, arena); -error: - Py_XDECREF(filename); - if (arena != NULL) - PyArena_Free(arena); - return res; -} - - -/* PyObject* parser_isexpr(PyObject* self, PyObject* args) - * PyObject* parser_issuite(PyObject* self, PyObject* args) - * - * Checks the passed-in ST object to determine if it is an expression or - * a statement suite, respectively. The return is a Python truth value. - * - */ -static PyObject* -parser_isexpr(PyST_Object *self, PyObject *args, PyObject *kw) -{ - PyObject* res = 0; - int ok; - - static char *keywords[] = {"st", NULL}; - - if (self == NULL || PyModule_Check(self)) - ok = PyArg_ParseTupleAndKeywords(args, kw, "O!:isexpr", keywords, - &PyST_Type, &self); - else - ok = PyArg_ParseTupleAndKeywords(args, kw, ":isexpr", &keywords[1]); - - if (ok) { - /* Check to see if the ST represents an expression or not. */ - res = (self->st_type == PyST_EXPR) ? Py_True : Py_False; - Py_INCREF(res); - } - return (res); -} - - -static PyObject* -parser_issuite(PyST_Object *self, PyObject *args, PyObject *kw) -{ - PyObject* res = 0; - int ok; - - static char *keywords[] = {"st", NULL}; - - if (self == NULL || PyModule_Check(self)) - ok = PyArg_ParseTupleAndKeywords(args, kw, "O!:issuite", keywords, - &PyST_Type, &self); - else - ok = PyArg_ParseTupleAndKeywords(args, kw, ":issuite", &keywords[1]); - - if (ok) { - /* Check to see if the ST represents an expression or not. */ - res = (self->st_type == PyST_EXPR) ? Py_False : Py_True; - Py_INCREF(res); - } - return (res); -} - - -/* err_string(const char* message) - * - * Sets the error string for an exception of type ParserError. - * - */ -static void -err_string(const char *message) -{ - PyErr_SetString(parser_error, message); -} - - -/* PyObject* parser_do_parse(PyObject* args, int type) - * - * Internal function to actually execute the parse and return the result if - * successful or set an exception if not. - * - */ -static PyObject* -parser_do_parse(PyObject *args, PyObject *kw, const char *argspec, int type) -{ - char* string = 0; - PyObject* res = 0; - int flags = 0; - perrdetail err; - - static char *keywords[] = {"source", NULL}; - - if (PyArg_ParseTupleAndKeywords(args, kw, argspec, keywords, &string)) { - node* n = PyParser_ParseStringFlagsFilenameEx(string, NULL, - &_PyParser_Grammar, - (type == PyST_EXPR) - ? eval_input : file_input, - &err, &flags); - - if (n) { - res = parser_newstobject(n, type); - if (res) { - ((PyST_Object *)res)->st_flags.cf_flags = flags & PyCF_MASK; - ((PyST_Object *)res)->st_flags.cf_feature_version = PY_MINOR_VERSION; - } - } - else { - PyParser_SetError(&err); - } - PyParser_ClearError(&err); - } - return (res); -} - - -/* PyObject* parser_expr(PyObject* self, PyObject* args) - * PyObject* parser_suite(PyObject* self, PyObject* args) - * - * External interfaces to the parser itself. Which is called determines if - * the parser attempts to recognize an expression ('eval' form) or statement - * suite ('exec' form). The real work is done by parser_do_parse() above. - * - */ -static PyObject* -parser_expr(PyST_Object *self, PyObject *args, PyObject *kw) -{ - NOTE(ARGUNUSED(self)) - return (parser_do_parse(args, kw, "s:expr", PyST_EXPR)); -} - - -static PyObject* -parser_suite(PyST_Object *self, PyObject *args, PyObject *kw) -{ - NOTE(ARGUNUSED(self)) - return (parser_do_parse(args, kw, "s:suite", PyST_SUITE)); -} - - - -/* This is the messy part of the code. Conversion from a tuple to an ST - * object requires that the input tuple be valid without having to rely on - * catching an exception from the compiler. This is done to allow the - * compiler itself to remain fast, since most of its input will come from - * the parser directly, and therefore be known to be syntactically correct. - * This validation is done to ensure that we don't core dump the compile - * phase, returning an exception instead. - * - * Two aspects can be broken out in this code: creating a node tree from - * the tuple passed in, and verifying that it is indeed valid. It may be - * advantageous to expand the number of ST types to include funcdefs and - * lambdadefs to take advantage of the optimizer, recognizing those STs - * here. They are not necessary, and not quite as useful in a raw form. - * For now, let's get expressions and suites working reliably. - */ - - -static node* build_node_tree(PyObject *tuple); - -static int -validate_node(node *tree) -{ - int type = TYPE(tree); - int nch = NCH(tree); - state *dfa_state; - int pos, arc; - - assert(ISNONTERMINAL(type)); - type -= NT_OFFSET; - if (type >= _PyParser_Grammar.g_ndfas) { - PyErr_Format(parser_error, "Unrecognized node type %d.", TYPE(tree)); - return 0; - } - const dfa *nt_dfa = &_PyParser_Grammar.g_dfa[type]; - REQ(tree, nt_dfa->d_type); - - /* Run the DFA for this nonterminal. */ - dfa_state = nt_dfa->d_state; - for (pos = 0; pos < nch; ++pos) { - node *ch = CHILD(tree, pos); - int ch_type = TYPE(ch); - if ((ch_type >= NT_OFFSET + _PyParser_Grammar.g_ndfas) - || (ISTERMINAL(ch_type) && (ch_type >= N_TOKENS)) - || (ch_type < 0) - ) { - PyErr_Format(parser_error, "Unrecognized node type %d.", ch_type); - return 0; - } - if (ch_type == suite && TYPE(tree) == funcdef) { - /* This is the opposite hack of what we do in parser.c - (search for func_body_suite), except we don't ever - support type comments here. */ - ch_type = func_body_suite; - } - for (arc = 0; arc < dfa_state->s_narcs; ++arc) { - short a_label = dfa_state->s_arc[arc].a_lbl; - assert(a_label < _PyParser_Grammar.g_ll.ll_nlabels); - - const char *label_str = _PyParser_Grammar.g_ll.ll_label[a_label].lb_str; - if ((_PyParser_Grammar.g_ll.ll_label[a_label].lb_type == ch_type) - && ((ch->n_str == NULL) || (label_str == NULL) - || (strcmp(ch->n_str, label_str) == 0)) - ) { - /* The child is acceptable; if non-terminal, validate it recursively. */ - if (ISNONTERMINAL(ch_type) && !validate_node(ch)) - return 0; - - /* Update the state, and move on to the next child. */ - dfa_state = &nt_dfa->d_state[dfa_state->s_arc[arc].a_arrow]; - goto arc_found; - } - } - /* What would this state have accepted? */ - { - short a_label = dfa_state->s_arc->a_lbl; - if (!a_label) /* Wouldn't accept any more children */ - goto illegal_num_children; - - int next_type = _PyParser_Grammar.g_ll.ll_label[a_label].lb_type; - const char *expected_str = _PyParser_Grammar.g_ll.ll_label[a_label].lb_str; - - if (ISNONTERMINAL(next_type)) { - PyErr_Format(parser_error, "Expected %s, got %s.", - _PyParser_Grammar.g_dfa[next_type - NT_OFFSET].d_name, - ISTERMINAL(ch_type) ? _PyParser_TokenNames[ch_type] : - _PyParser_Grammar.g_dfa[ch_type - NT_OFFSET].d_name); - } - else if (expected_str != NULL) { - PyErr_Format(parser_error, "Illegal terminal: expected '%s'.", - expected_str); - } - else { - PyErr_Format(parser_error, "Illegal terminal: expected %s.", - _PyParser_TokenNames[next_type]); - } - return 0; - } - -arc_found: - continue; - } - /* Are we in a final state? If so, return 1 for successful validation. */ - for (arc = 0; arc < dfa_state->s_narcs; ++arc) { - if (!dfa_state->s_arc[arc].a_lbl) { - return 1; - } - } - -illegal_num_children: - PyErr_Format(parser_error, - "Illegal number of children for %s node.", nt_dfa->d_name); - return 0; -} - -/* PyObject* parser_tuple2st(PyObject* self, PyObject* args) - * - * This is the public function, called from the Python code. It receives a - * single tuple object from the caller, and creates an ST object if the - * tuple can be validated. It does this by checking the first code of the - * tuple, and, if acceptable, builds the internal representation. If this - * step succeeds, the internal representation is validated as fully as - * possible with the recursive validate_node() routine defined above. - * - * This function must be changed if support is to be added for PyST_FRAGMENT - * ST objects. - * - */ -static PyObject* -parser_tuple2st(PyST_Object *self, PyObject *args, PyObject *kw) -{ - NOTE(ARGUNUSED(self)) - PyObject *st = 0; - PyObject *tuple; - node *tree; - - static char *keywords[] = {"sequence", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kw, "O:sequence2st", keywords, - &tuple)) - return (0); - if (!PySequence_Check(tuple)) { - PyErr_SetString(PyExc_ValueError, - "sequence2st() requires a single sequence argument"); - return (0); - } - /* - * Convert the tree to the internal form before checking it. - */ - tree = build_node_tree(tuple); - if (tree != 0) { - node *validation_root = NULL; - int tree_type = 0; - switch (TYPE(tree)) { - case eval_input: - /* Might be an eval form. */ - tree_type = PyST_EXPR; - validation_root = tree; - break; - case encoding_decl: - /* This looks like an encoding_decl so far. */ - if (NCH(tree) == 1) { - tree_type = PyST_SUITE; - validation_root = CHILD(tree, 0); - } - else { - err_string("Error Parsing encoding_decl"); - } - break; - case file_input: - /* This looks like an exec form so far. */ - tree_type = PyST_SUITE; - validation_root = tree; - break; - default: - /* This is a fragment, at best. */ - err_string("parse tree does not use a valid start symbol"); - } - - if (validation_root != NULL && validate_node(validation_root)) - st = parser_newstobject(tree, tree_type); - else - PyNode_Free(tree); - } - /* Make sure we raise an exception on all errors. We should never - * get this, but we'd do well to be sure something is done. - */ - if (st == NULL && !PyErr_Occurred()) - err_string("unspecified ST error occurred"); - - return st; -} - - -/* node* build_node_children() - * - * Iterate across the children of the current non-terminal node and build - * their structures. If successful, return the root of this portion of - * the tree, otherwise, 0. Any required exception will be specified already, - * and no memory will have been deallocated. - * - */ -static node* -build_node_children(PyObject *tuple, node *root, int *line_num) -{ - Py_ssize_t len = PyObject_Size(tuple); - Py_ssize_t i; - int err; - - if (len < 0) { - return NULL; - } - for (i = 1; i < len; ++i) { - /* elem must always be a sequence, however simple */ - PyObject* elem = PySequence_GetItem(tuple, i); - int ok = elem != NULL; - int type = 0; - char *strn = 0; - - if (ok) - ok = PySequence_Check(elem); - if (ok) { - PyObject *temp = PySequence_GetItem(elem, 0); - if (temp == NULL) - ok = 0; - else { - ok = PyLong_Check(temp); - if (ok) { - type = _PyLong_AsInt(temp); - if (type == -1 && PyErr_Occurred()) { - Py_DECREF(temp); - Py_DECREF(elem); - return NULL; - } - } - Py_DECREF(temp); - } - } - if (!ok) { - PyObject *err = Py_BuildValue("Os", elem, - "Illegal node construct."); - PyErr_SetObject(parser_error, err); - Py_XDECREF(err); - Py_XDECREF(elem); - return NULL; - } - if (ISTERMINAL(type)) { - Py_ssize_t len = PyObject_Size(elem); - PyObject *temp; - const char *temp_str; - - if ((len != 2) && (len != 3)) { - err_string("terminal nodes must have 2 or 3 entries"); - Py_DECREF(elem); - return NULL; - } - temp = PySequence_GetItem(elem, 1); - if (temp == NULL) { - Py_DECREF(elem); - return NULL; - } - if (!PyUnicode_Check(temp)) { - PyErr_Format(parser_error, - "second item in terminal node must be a string," - " found %s", - Py_TYPE(temp)->tp_name); - Py_DECREF(temp); - Py_DECREF(elem); - return NULL; - } - if (len == 3) { - PyObject *o = PySequence_GetItem(elem, 2); - if (o == NULL) { - Py_DECREF(temp); - Py_DECREF(elem); - return NULL; - } - if (PyLong_Check(o)) { - int num = _PyLong_AsInt(o); - if (num == -1 && PyErr_Occurred()) { - Py_DECREF(o); - Py_DECREF(temp); - Py_DECREF(elem); - return NULL; - } - *line_num = num; - } - else { - PyErr_Format(parser_error, - "third item in terminal node must be an" - " integer, found %s", - Py_TYPE(temp)->tp_name); - Py_DECREF(o); - Py_DECREF(temp); - Py_DECREF(elem); - return NULL; - } - Py_DECREF(o); - } - temp_str = PyUnicode_AsUTF8AndSize(temp, &len); - if (temp_str == NULL) { - Py_DECREF(temp); - Py_DECREF(elem); - return NULL; - } - strn = (char *)PyObject_MALLOC(len + 1); - if (strn == NULL) { - Py_DECREF(temp); - Py_DECREF(elem); - PyErr_NoMemory(); - return NULL; - } - (void) memcpy(strn, temp_str, len + 1); - Py_DECREF(temp); - } - else if (!ISNONTERMINAL(type)) { - /* - * It has to be one or the other; this is an error. - * Raise an exception. - */ - PyObject *err = Py_BuildValue("Os", elem, "unknown node type."); - PyErr_SetObject(parser_error, err); - Py_XDECREF(err); - Py_DECREF(elem); - return NULL; - } - err = PyNode_AddChild(root, type, strn, *line_num, 0, *line_num, 0); - if (err == E_NOMEM) { - Py_DECREF(elem); - PyObject_FREE(strn); - PyErr_NoMemory(); - return NULL; - } - if (err == E_OVERFLOW) { - Py_DECREF(elem); - PyObject_FREE(strn); - PyErr_SetString(PyExc_ValueError, - "unsupported number of child nodes"); - return NULL; - } - - if (ISNONTERMINAL(type)) { - node* new_child = CHILD(root, i - 1); - - if (new_child != build_node_children(elem, new_child, line_num)) { - Py_DECREF(elem); - return NULL; - } - } - else if (type == NEWLINE) { /* It's true: we increment the */ - ++(*line_num); /* line number *after* the newline! */ - } - Py_DECREF(elem); - } - return root; -} - - -static node* -build_node_tree(PyObject *tuple) -{ - node* res = 0; - PyObject *temp = PySequence_GetItem(tuple, 0); - long num = -1; - - if (temp != NULL) - num = PyLong_AsLong(temp); - Py_XDECREF(temp); - if (ISTERMINAL(num)) { - /* - * The tuple is simple, but it doesn't start with a start symbol. - * Raise an exception now and be done with it. - */ - tuple = Py_BuildValue("Os", tuple, - "Illegal syntax-tree; cannot start with terminal symbol."); - PyErr_SetObject(parser_error, tuple); - Py_XDECREF(tuple); - } - else if (ISNONTERMINAL(num)) { - /* - * Not efficient, but that can be handled later. - */ - int line_num = 0; - PyObject *encoding = NULL; - - if (num == encoding_decl) { - encoding = PySequence_GetItem(tuple, 2); - if (encoding == NULL) { - PyErr_SetString(parser_error, "missed encoding"); - return NULL; - } - if (!PyUnicode_Check(encoding)) { - PyErr_Format(parser_error, - "encoding must be a string, found %.200s", - Py_TYPE(encoding)->tp_name); - Py_DECREF(encoding); - return NULL; - } - /* tuple isn't borrowed anymore here, need to DECREF */ - tuple = PySequence_GetSlice(tuple, 0, 2); - if (tuple == NULL) { - Py_DECREF(encoding); - return NULL; - } - } - res = PyNode_New(num); - if (res != NULL) { - if (res != build_node_children(tuple, res, &line_num)) { - PyNode_Free(res); - res = NULL; - } - if (res && encoding) { - Py_ssize_t len; - const char *temp; - temp = PyUnicode_AsUTF8AndSize(encoding, &len); - if (temp == NULL) { - PyNode_Free(res); - Py_DECREF(encoding); - Py_DECREF(tuple); - return NULL; - } - res->n_str = (char *)PyObject_MALLOC(len + 1); - if (res->n_str == NULL) { - PyNode_Free(res); - Py_DECREF(encoding); - Py_DECREF(tuple); - PyErr_NoMemory(); - return NULL; - } - (void) memcpy(res->n_str, temp, len + 1); - } - } - if (encoding != NULL) { - Py_DECREF(encoding); - Py_DECREF(tuple); - } - } - else { - /* The tuple is illegal -- if the number is neither TERMINAL nor - * NONTERMINAL, we can't use it. Not sure the implementation - * allows this condition, but the API doesn't preclude it. - */ - PyObject *err = Py_BuildValue("Os", tuple, - "Illegal component tuple."); - PyErr_SetObject(parser_error, err); - Py_XDECREF(err); - } - - return (res); -} - - -static PyObject* -pickle_constructor = NULL; - - -static PyObject* -parser__pickler(PyObject *self, PyObject *args) -{ - NOTE(ARGUNUSED(self)) - PyObject *result = NULL; - PyObject *st = NULL; - - if (PyArg_ParseTuple(args, "O!:_pickler", &PyST_Type, &st)) { - PyObject *newargs; - PyObject *tuple; - - if ((newargs = PyTuple_Pack(2, st, Py_True)) == NULL) - return NULL; - tuple = parser_st2tuple((PyST_Object*)NULL, newargs, NULL); - if (tuple != NULL) { - result = Py_BuildValue("O(O)", pickle_constructor, tuple); - Py_DECREF(tuple); - } - Py_DECREF(newargs); - } - - return (result); -} - - -/* Functions exported by this module. Most of this should probably - * be converted into an ST object with methods, but that is better - * done directly in Python, allowing subclasses to be created directly. - * We'd really have to write a wrapper around it all anyway to allow - * inheritance. - */ -static PyMethodDef parser_functions[] = { - {"compilest", (PyCFunction)(void(*)(void))parser_compilest, PUBLIC_METHOD_TYPE, - PyDoc_STR("Compiles an ST object into a code object.")}, - {"expr", (PyCFunction)(void(*)(void))parser_expr, PUBLIC_METHOD_TYPE, - PyDoc_STR("Creates an ST object from an expression.")}, - {"isexpr", (PyCFunction)(void(*)(void))parser_isexpr, PUBLIC_METHOD_TYPE, - PyDoc_STR("Determines if an ST object was created from an expression.")}, - {"issuite", (PyCFunction)(void(*)(void))parser_issuite, PUBLIC_METHOD_TYPE, - PyDoc_STR("Determines if an ST object was created from a suite.")}, - {"suite", (PyCFunction)(void(*)(void))parser_suite, PUBLIC_METHOD_TYPE, - PyDoc_STR("Creates an ST object from a suite.")}, - {"sequence2st", (PyCFunction)(void(*)(void))parser_tuple2st, PUBLIC_METHOD_TYPE, - PyDoc_STR("Creates an ST object from a tree representation.")}, - {"st2tuple", (PyCFunction)(void(*)(void))parser_st2tuple, PUBLIC_METHOD_TYPE, - PyDoc_STR("Creates a tuple-tree representation of an ST.")}, - {"st2list", (PyCFunction)(void(*)(void))parser_st2list, PUBLIC_METHOD_TYPE, - PyDoc_STR("Creates a list-tree representation of an ST.")}, - {"tuple2st", (PyCFunction)(void(*)(void))parser_tuple2st, PUBLIC_METHOD_TYPE, - PyDoc_STR("Creates an ST object from a tree representation.")}, - - /* private stuff: support pickle module */ - {"_pickler", (PyCFunction)parser__pickler, METH_VARARGS, - PyDoc_STR("Returns the pickle magic to allow ST objects to be pickled.")}, - - {NULL, NULL, 0, NULL} - }; - - - -static struct PyModuleDef parsermodule = { - PyModuleDef_HEAD_INIT, - "parser", - NULL, - -1, - parser_functions, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC PyInit_parser(void); /* supply a prototype */ - -PyMODINIT_FUNC -PyInit_parser(void) -{ - PyObject *module, *copyreg; - - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "The parser module is deprecated and will be removed " - "in future versions of Python", 7) != 0) { - return NULL; - } - - if (PyType_Ready(&PyST_Type) < 0) - return NULL; - module = PyModule_Create(&parsermodule); - if (module == NULL) - return NULL; - - if (parser_error == 0) - parser_error = PyErr_NewException("parser.ParserError", NULL, NULL); - - if (parser_error == 0) - return NULL; - /* CAUTION: The code next used to skip bumping the refcount on - * parser_error. That's a disaster if PyInit_parser() gets called more - * than once. By incref'ing, we ensure that each module dict that - * gets created owns its reference to the shared parser_error object, - * and the file static parser_error vrbl owns a reference too. - */ - Py_INCREF(parser_error); - if (PyModule_AddObject(module, "ParserError", parser_error) != 0) - return NULL; - - Py_INCREF(&PyST_Type); - PyModule_AddObject(module, "STType", (PyObject*)&PyST_Type); - - PyModule_AddStringConstant(module, "__copyright__", - parser_copyright_string); - PyModule_AddStringConstant(module, "__doc__", - parser_doc_string); - PyModule_AddStringConstant(module, "__version__", - parser_version_string); - - /* Register to support pickling. - * If this fails, the import of this module will fail because an - * exception will be raised here; should we clear the exception? - */ - copyreg = PyImport_ImportModuleNoBlock("copyreg"); - if (copyreg != NULL) { - PyObject *func, *pickler; - _Py_IDENTIFIER(pickle); - _Py_IDENTIFIER(sequence2st); - _Py_IDENTIFIER(_pickler); - - func = _PyObject_GetAttrId(copyreg, &PyId_pickle); - pickle_constructor = _PyObject_GetAttrId(module, &PyId_sequence2st); - pickler = _PyObject_GetAttrId(module, &PyId__pickler); - Py_XINCREF(pickle_constructor); - if ((func != NULL) && (pickle_constructor != NULL) - && (pickler != NULL)) { - PyObject *res; - - res = PyObject_CallFunctionObjArgs(func, &PyST_Type, pickler, - pickle_constructor, NULL); - Py_XDECREF(res); - } - Py_XDECREF(func); - Py_XDECREF(pickle_constructor); - Py_XDECREF(pickler); - Py_DECREF(copyreg); - } - return module; -} diff --git a/contrib/tools/python3/src/Modules/posixmodule.c b/contrib/tools/python3/src/Modules/posixmodule.c index 0918266843..7b1b2cd252 100644 --- a/contrib/tools/python3/src/Modules/posixmodule.c +++ b/contrib/tools/python3/src/Modules/posixmodule.c @@ -10,6 +10,8 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" +#include "pycore_fileutils.h" +#include "pycore_moduleobject.h" // _PyModule_GetState() #ifdef MS_WINDOWS /* include <windows.h> early to avoid conflict with pycore_condvar.h: @@ -21,8 +23,12 @@ # include <pathcch.h> #endif +#ifdef __VXWORKS__ +# include "pycore_bitutils.h" // _Py_popcount32() +#endif #include "pycore_ceval.h" // _PyEval_ReInitThreads() #include "pycore_import.h" // _PyImport_ReInitLock() +#include "pycore_initconfig.h" // _PyStatus_EXCEPTION() #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "structmember.h" // PyMemberDef #ifndef MS_WINDOWS @@ -276,6 +282,7 @@ corresponding Unix manual entries for more information on calls."); #endif #ifdef HAVE_GETRANDOM_SYSCALL # include <sys/syscall.h> +# include <sys/random.h> #endif #if defined(MS_WINDOWS) @@ -521,6 +528,11 @@ extern char *ctermid_r(char *); # include <linux/memfd.h> #endif +/* eventfd() */ +#ifdef HAVE_SYS_EVENTFD_H +# include <sys/eventfd.h> +#endif + #ifdef _Py_MEMORY_SANITIZER # include <sanitizer/msan_interface.h> #endif @@ -578,15 +590,45 @@ PyOS_AfterFork_Parent(void) void PyOS_AfterFork_Child(void) { + PyStatus status; _PyRuntimeState *runtime = &_PyRuntime; - _PyGILState_Reinit(runtime); - _PyEval_ReInitThreads(runtime); - _PyImport_ReInitLock(); + + status = _PyGILState_Reinit(runtime); + if (_PyStatus_EXCEPTION(status)) { + goto fatal_error; + } + + PyThreadState *tstate = _PyThreadState_GET(); + _Py_EnsureTstateNotNULL(tstate); + + status = _PyEval_ReInitThreads(tstate); + if (_PyStatus_EXCEPTION(status)) { + goto fatal_error; + } + + status = _PyImport_ReInitLock(); + if (_PyStatus_EXCEPTION(status)) { + goto fatal_error; + } + _PySignal_AfterFork(); - _PyRuntimeState_ReInitThreads(runtime); - _PyInterpreterState_DeleteExceptMain(runtime); - run_at_forkers(_PyInterpreterState_GET()->after_forkers_child, 0); + status = _PyRuntimeState_ReInitThreads(runtime); + if (_PyStatus_EXCEPTION(status)) { + goto fatal_error; + } + + status = _PyInterpreterState_DeleteExceptMain(runtime); + if (_PyStatus_EXCEPTION(status)) { + goto fatal_error; + } + assert(_PyThreadState_GET() == tstate); + + run_at_forkers(tstate->interp->after_forkers_child, 0); + return; + +fatal_error: + Py_ExitStatusException(status); } static int @@ -648,7 +690,7 @@ _Py_Uid_Converter(PyObject *obj, uid_t *p) long result; unsigned long uresult; - index = PyNumber_Index(obj); + index = _PyNumber_Index(obj); if (index == NULL) { PyErr_Format(PyExc_TypeError, "uid should be integer, not %.200s", @@ -754,7 +796,7 @@ _Py_Gid_Converter(PyObject *obj, gid_t *p) long result; unsigned long uresult; - index = PyNumber_Index(obj); + index = _PyNumber_Index(obj); if (index == NULL) { PyErr_Format(PyExc_TypeError, "gid should be integer, not %.200s", @@ -888,7 +930,7 @@ _fd_converter(PyObject *o, int *p) int overflow; long long_value; - PyObject *index = PyNumber_Index(o); + PyObject *index = _PyNumber_Index(o); if (index == NULL) { return 0; } @@ -955,7 +997,7 @@ typedef struct { static inline _posixstate* get_posix_state(PyObject *module) { - void *state = PyModule_GetState(module); + void *state = _PyModule_GetState(module); assert(state != NULL); return (_posixstate *)state; } @@ -1074,6 +1116,11 @@ typedef struct { static void path_cleanup(path_t *path) { +#if !USE_UNICODE_WCHAR_CACHE + wchar_t *wide = (wchar_t *)path->wide; + path->wide = NULL; + PyMem_Free(wide); +#endif /* USE_UNICODE_WCHAR_CACHE */ Py_CLEAR(path->object); Py_CLEAR(path->cleanup); } @@ -1088,7 +1135,7 @@ path_converter(PyObject *o, void *p) const char *narrow; #ifdef MS_WINDOWS PyObject *wo = NULL; - const wchar_t *wide; + wchar_t *wide = NULL; #endif #define FORMAT_EXCEPTION(exc, fmt) \ @@ -1161,10 +1208,14 @@ path_converter(PyObject *o, void *p) if (is_unicode) { #ifdef MS_WINDOWS +#if USE_UNICODE_WCHAR_CACHE _Py_COMP_DIAG_PUSH _Py_COMP_DIAG_IGNORE_DEPR_DECLS wide = PyUnicode_AsUnicodeAndSize(o, &length); _Py_COMP_DIAG_POP +#else /* USE_UNICODE_WCHAR_CACHE */ + wide = PyUnicode_AsWideCharString(o, &length); +#endif /* USE_UNICODE_WCHAR_CACHE */ if (!wide) { goto error_exit; } @@ -1180,6 +1231,9 @@ _Py_COMP_DIAG_POP path->wide = wide; path->narrow = FALSE; path->fd = -1; +#if !USE_UNICODE_WCHAR_CACHE + wide = NULL; +#endif /* USE_UNICODE_WCHAR_CACHE */ goto success_exit; #else if (!PyUnicode_FSConverter(o, &bytes)) { @@ -1255,10 +1309,15 @@ _Py_COMP_DIAG_POP goto error_exit; } +#if USE_UNICODE_WCHAR_CACHE _Py_COMP_DIAG_PUSH _Py_COMP_DIAG_IGNORE_DEPR_DECLS wide = PyUnicode_AsUnicodeAndSize(wo, &length); _Py_COMP_DIAG_POP +#else /* USE_UNICODE_WCHAR_CACHE */ + wide = PyUnicode_AsWideCharString(wo, &length); + Py_DECREF(wo); +#endif /* USE_UNICODE_WCHAR_CACHE */ if (!wide) { goto error_exit; } @@ -1272,8 +1331,12 @@ _Py_COMP_DIAG_POP } path->wide = wide; path->narrow = TRUE; - path->cleanup = wo; Py_DECREF(bytes); +#if USE_UNICODE_WCHAR_CACHE + path->cleanup = wo; +#else /* USE_UNICODE_WCHAR_CACHE */ + wide = NULL; +#endif /* USE_UNICODE_WCHAR_CACHE */ #else path->wide = NULL; path->narrow = narrow; @@ -1297,7 +1360,11 @@ _Py_COMP_DIAG_POP Py_XDECREF(o); Py_XDECREF(bytes); #ifdef MS_WINDOWS +#if USE_UNICODE_WCHAR_CACHE Py_XDECREF(wo); +#else /* USE_UNICODE_WCHAR_CACHE */ + PyMem_Free(wide); +#endif /* USE_UNICODE_WCHAR_CACHE */ #endif return 0; } @@ -1583,13 +1650,11 @@ convertenviron(void) Py_DECREF(d); return NULL; } - if (PyDict_GetItemWithError(d, k) == NULL) { - if (PyErr_Occurred() || PyDict_SetItem(d, k, v) != 0) { - Py_DECREF(v); - Py_DECREF(k); - Py_DECREF(d); - return NULL; - } + if (PyDict_SetDefault(d, k, v) == NULL) { + Py_DECREF(v); + Py_DECREF(k); + Py_DECREF(d); + return NULL; } Py_DECREF(k); Py_DECREF(v); @@ -1692,18 +1757,6 @@ path_error2(path_t *path, path_t *path2) /* POSIX generic methods */ -static int -fildes_converter(PyObject *o, void *p) -{ - int fd; - int *pointer = (int *)p; - fd = PyObject_AsFileDescriptor(o); - if (fd < 0) - return 0; - *pointer = fd; - return 1; -} - static PyObject * posix_fildes_fd(int fd, int (*func)(int)) { @@ -2735,10 +2788,6 @@ class dir_fd_converter(CConverter): else: self.converter = 'dir_fd_converter' -class fildes_converter(CConverter): - type = 'int' - converter = 'fildes_converter' - class uid_t_converter(CConverter): type = "uid_t" converter = '_Py_Uid_Converter' @@ -2801,7 +2850,7 @@ class sysconf_confname_converter(path_confname_converter): converter="conv_sysconf_confname" [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=f1c8ae8d744f6c8b]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=3338733161aa7879]*/ /*[clinic input] @@ -5507,7 +5556,7 @@ free_string_array(EXECV_CHAR **array, Py_ssize_t count) Py_ssize_t i; for (i = 0; i < count; i++) PyMem_Free(array[i]); - PyMem_DEL(array); + PyMem_Free(array); } static int @@ -6545,9 +6594,10 @@ os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv, res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval); fail_2: - while (--envc >= 0) - PyMem_DEL(envlist[envc]); - PyMem_DEL(envlist); + while (--envc >= 0) { + PyMem_Free(envlist[envc]); + } + PyMem_Free(envlist); fail_1: free_string_array(argvlist, lastarg); fail_0: @@ -6556,7 +6606,6 @@ os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv, #endif /* HAVE_SPAWNV */ - #ifdef HAVE_FORK /* Helper function to validate arguments. @@ -7146,12 +7195,11 @@ error: /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */ -/* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */ #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX) -#define DEV_PTY_FILE "/dev/ptc" -#define HAVE_DEV_PTMX +# define DEV_PTY_FILE "/dev/ptc" +# define HAVE_DEV_PTMX #else -#define DEV_PTY_FILE "/dev/ptmx" +# define DEV_PTY_FILE "/dev/ptmx" #endif #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX) @@ -7484,7 +7532,7 @@ os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid) list = PyList_New(ngroups); if (list == NULL) { - PyMem_Del(groups); + PyMem_Free(groups); return NULL; } @@ -7496,13 +7544,13 @@ os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid) #endif if (o == NULL) { Py_DECREF(list); - PyMem_Del(groups); + PyMem_Free(groups); return NULL; } PyList_SET_ITEM(list, i, o); } - PyMem_Del(groups); + PyMem_Free(groups); return list; } @@ -9169,25 +9217,6 @@ os_close_impl(PyObject *module, int fd) Py_RETURN_NONE; } - -#ifdef HAVE_FDWALK -static int -_fdwalk_close_func(void *lohi, int fd) -{ - int lo = ((int *)lohi)[0]; - int hi = ((int *)lohi)[1]; - - if (fd >= hi) { - return 1; - } - else if (fd >= lo) { - /* Ignore errors */ - (void)close(fd); - } - return 0; -} -#endif /* HAVE_FDWALK */ - /*[clinic input] os.closerange @@ -9202,32 +9231,8 @@ static PyObject * os_closerange_impl(PyObject *module, int fd_low, int fd_high) /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/ { -#ifdef HAVE_FDWALK - int lohi[2]; -#endif Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH -#ifdef HAVE_FDWALK - lohi[0] = Py_MAX(fd_low, 0); - lohi[1] = fd_high; - fdwalk(_fdwalk_close_func, lohi); -#else - fd_low = Py_MAX(fd_low, 0); -#ifdef __FreeBSD__ - if (fd_high >= sysconf(_SC_OPEN_MAX)) { - /* Any errors encountered while closing file descriptors are ignored */ - closefrom(fd_low); - } - else -#endif - { - for (int i = fd_low; i < fd_high; i++) { - /* Ignore errors */ - (void)close(i); - } - } -#endif - _Py_END_SUPPRESS_IPH + _Py_closerange(fd_low, fd_high - 1); Py_END_ALLOW_THREADS Py_RETURN_NONE; } @@ -9490,7 +9495,7 @@ iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, in *buf = PyMem_New(Py_buffer, cnt); if (*buf == NULL) { - PyMem_Del(*iov); + PyMem_Free(*iov); PyErr_NoMemory(); return -1; } @@ -9510,11 +9515,11 @@ iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, in return 0; fail: - PyMem_Del(*iov); + PyMem_Free(*iov); for (j = 0; j < i; j++) { PyBuffer_Release(&(*buf)[j]); } - PyMem_Del(*buf); + PyMem_Free(*buf); return -1; } @@ -9522,11 +9527,11 @@ static void iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt) { int i; - PyMem_Del(iov); + PyMem_Free(iov); for (i = 0; i < cnt; i++) { PyBuffer_Release(&buf[i]); } - PyMem_Del(buf); + PyMem_Free(buf); } #endif @@ -10108,18 +10113,16 @@ os_pipe_impl(PyObject *module) attr.bInheritHandle = FALSE; Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH ok = CreatePipe(&read, &write, &attr, 0); if (ok) { - fds[0] = _open_osfhandle((intptr_t)read, _O_RDONLY); - fds[1] = _open_osfhandle((intptr_t)write, _O_WRONLY); + fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY); + fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY); if (fds[0] == -1 || fds[1] == -1) { CloseHandle(read); CloseHandle(write); ok = 0; } } - _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS if (!ok) @@ -10304,6 +10307,7 @@ The flags argument contains a bitwise OR of zero or more of the following flags: - RWF_DSYNC - RWF_SYNC +- RWF_APPEND Using non-zero flags requires Linux 4.7 or newer. [clinic start generated code]*/ @@ -10311,7 +10315,7 @@ Using non-zero flags requires Linux 4.7 or newer. static Py_ssize_t os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, int flags) -/*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=803dc5ddbf0cfd3b]*/ +/*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/ { Py_ssize_t cnt; Py_ssize_t result; @@ -10453,6 +10457,75 @@ os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count, } #endif /* HAVE_COPY_FILE_RANGE*/ +#if (defined(HAVE_SPLICE) && !defined(_AIX)) +/*[clinic input] + +os.splice + src: int + Source file descriptor. + dst: int + Destination file descriptor. + count: Py_ssize_t + Number of bytes to copy. + offset_src: object = None + Starting offset in src. + offset_dst: object = None + Starting offset in dst. + flags: unsigned_int = 0 + Flags to modify the semantics of the call. + +Transfer count bytes from one pipe to a descriptor or vice versa. + +If offset_src is None, then src is read from the current position; +respectively for offset_dst. The offset associated to the file +descriptor that refers to a pipe must be None. +[clinic start generated code]*/ + +static PyObject * +os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count, + PyObject *offset_src, PyObject *offset_dst, + unsigned int flags) +/*[clinic end generated code: output=d0386f25a8519dc5 input=047527c66c6d2e0a]*/ +{ + off_t offset_src_val, offset_dst_val; + off_t *p_offset_src = NULL; + off_t *p_offset_dst = NULL; + Py_ssize_t ret; + int async_err = 0; + + if (count < 0) { + PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed"); + return NULL; + } + + if (offset_src != Py_None) { + if (!Py_off_t_converter(offset_src, &offset_src_val)) { + return NULL; + } + p_offset_src = &offset_src_val; + } + + if (offset_dst != Py_None) { + if (!Py_off_t_converter(offset_dst, &offset_dst_val)) { + return NULL; + } + p_offset_dst = &offset_dst_val; + } + + do { + Py_BEGIN_ALLOW_THREADS + ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags); + Py_END_ALLOW_THREADS + } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + + if (ret < 0) { + return (!async_err) ? posix_error() : NULL; + } + + return PyLong_FromSsize_t(ret); +} +#endif /* HAVE_SPLICE*/ + #ifdef HAVE_MKFIFO /*[clinic input] os.mkfifo @@ -11489,7 +11562,7 @@ conv_path_confname(PyObject *arg, int *valuep) /*[clinic input] os.fpathconf -> long - fd: int + fd: fildes name: path_confname / @@ -11500,7 +11573,7 @@ If there is no limit, return -1. static long os_fpathconf_impl(PyObject *module, int fd, int name) -/*[clinic end generated code: output=d5b7042425fc3e21 input=5942a024d3777810]*/ +/*[clinic end generated code: output=d5b7042425fc3e21 input=5b8d2471cfaae186]*/ { long limit; @@ -12425,6 +12498,9 @@ check_ShellExecute() os.startfile filepath: path_t operation: Py_UNICODE = NULL + arguments: Py_UNICODE = NULL + cwd: path_t(nullable=True) = None + show_cmd: int = 1 Start a file with its associated application. @@ -12435,6 +12511,16 @@ application (if any) its extension is associated. When another "operation" is given, it specifies what should be done with the file. A typical operation is "print". +"arguments" is passed to the application, but should be omitted if the +file is a document. + +"cwd" is the working directory for the operation. If "filepath" is +relative, it will be resolved against this directory. This argument +should usually be an absolute path. + +"show_cmd" can be used to override the recommended visibility option. +See the Windows ShellExecute documentation for values. + startfile returns as soon as the associated application is launched. There is no option to wait for the application to close, and no way to retrieve the application's exit status. @@ -12446,8 +12532,9 @@ the underlying Win32 ShellExecute function doesn't work if it is. static PyObject * os_startfile_impl(PyObject *module, path_t *filepath, - const Py_UNICODE *operation) -/*[clinic end generated code: output=66dc311c94d50797 input=c940888a5390f039]*/ + const Py_UNICODE *operation, const Py_UNICODE *arguments, + path_t *cwd, int show_cmd) +/*[clinic end generated code: output=3baa4f9795841880 input=8248997b80669622]*/ { HINSTANCE rc; @@ -12461,10 +12548,15 @@ os_startfile_impl(PyObject *module, path_t *filepath, if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) { return NULL; } + if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation, + arguments, cwd->object ? cwd->object : Py_None, + show_cmd) < 0) { + return NULL; + } Py_BEGIN_ALLOW_THREADS rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide, - NULL, NULL, SW_SHOWNORMAL); + arguments, cwd->wide, show_cmd); Py_END_ALLOW_THREADS if (rc <= (HINSTANCE)32) { @@ -12830,7 +12922,7 @@ os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks) path_error(path); break; } - buffer = PyMem_MALLOC(buffer_size); + buffer = PyMem_Malloc(buffer_size); if (!buffer) { PyErr_NoMemory(); break; @@ -12847,7 +12939,7 @@ os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks) if (length < 0) { if (errno == ERANGE) { - PyMem_FREE(buffer); + PyMem_Free(buffer); buffer = NULL; continue; } @@ -12885,7 +12977,7 @@ os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks) } exit: if (buffer) - PyMem_FREE(buffer); + PyMem_Free(buffer); return result; } #endif /* USE_XATTRS */ @@ -12947,6 +13039,79 @@ os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags) } #endif +#ifdef HAVE_EVENTFD +/*[clinic input] +os.eventfd + + initval: unsigned_int + flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC + +Creates and returns an event notification file descriptor. +[clinic start generated code]*/ + +static PyObject * +os_eventfd_impl(PyObject *module, unsigned int initval, int flags) +/*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/ + +{ + /* initval is limited to uint32_t, internal counter is uint64_t */ + int fd; + Py_BEGIN_ALLOW_THREADS + fd = eventfd(initval, flags); + Py_END_ALLOW_THREADS + if (fd == -1) { + return PyErr_SetFromErrno(PyExc_OSError); + } + return PyLong_FromLong(fd); +} + +/*[clinic input] +os.eventfd_read + + fd: fildes + +Read eventfd value +[clinic start generated code]*/ + +static PyObject * +os_eventfd_read_impl(PyObject *module, int fd) +/*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/ +{ + eventfd_t value; + int result; + Py_BEGIN_ALLOW_THREADS + result = eventfd_read(fd, &value); + Py_END_ALLOW_THREADS + if (result == -1) { + return PyErr_SetFromErrno(PyExc_OSError); + } + return PyLong_FromUnsignedLongLong(value); +} + +/*[clinic input] +os.eventfd_write + + fd: fildes + value: unsigned_long_long + +Write eventfd value. +[clinic start generated code]*/ + +static PyObject * +os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value) +/*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/ +{ + int result; + Py_BEGIN_ALLOW_THREADS + result = eventfd_write(fd, value); + Py_END_ALLOW_THREADS + if (result == -1) { + return PyErr_SetFromErrno(PyExc_OSError); + } + Py_RETURN_NONE; +} +#endif /* HAVE_EVENTFD */ + /* Terminal size querying */ PyDoc_STRVAR(TerminalSize_docstring, @@ -13077,6 +13242,8 @@ os_cpu_count_impl(PyObject *module) ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL); #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) ncpu = sysconf(_SC_NPROCESSORS_ONLN); +#elif defined(__VXWORKS__) + ncpu = _Py_popcount32(vxCpuEnabledGet()); #elif defined(__DragonFly__) || \ defined(__OpenBSD__) || \ defined(__FreeBSD__) || \ @@ -13263,14 +13430,6 @@ typedef struct { #endif } DirEntry; -static PyObject * -_disabled_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) -{ - PyErr_Format(PyExc_TypeError, - "cannot create '%.100s' instances", _PyType_Name(type)); - return NULL; -} - static void DirEntry_dealloc(DirEntry *entry) { @@ -13325,10 +13484,15 @@ DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks) #ifdef MS_WINDOWS if (!PyUnicode_FSDecoder(self->path, &ub)) return NULL; +#if USE_UNICODE_WCHAR_CACHE _Py_COMP_DIAG_PUSH _Py_COMP_DIAG_IGNORE_DEPR_DECLS const wchar_t *path = PyUnicode_AsUnicode(ub); _Py_COMP_DIAG_POP +#else /* USE_UNICODE_WCHAR_CACHE */ + wchar_t *path = PyUnicode_AsWideCharString(ub, NULL); + Py_DECREF(ub); +#endif /* USE_UNICODE_WCHAR_CACHE */ #else /* POSIX */ if (!PyUnicode_FSConverter(self->path, &ub)) return NULL; @@ -13355,7 +13519,11 @@ _Py_COMP_DIAG_POP else result = LSTAT(path, &st); } +#if defined(MS_WINDOWS) && !USE_UNICODE_WCHAR_CACHE + PyMem_Free(path); +#else /* USE_UNICODE_WCHAR_CACHE */ Py_DECREF(ub); +#endif /* USE_UNICODE_WCHAR_CACHE */ if (result != 0) return path_object_error(self->path); @@ -13544,18 +13712,24 @@ os_DirEntry_inode_impl(DirEntry *self) #ifdef MS_WINDOWS if (!self->got_file_index) { PyObject *unicode; - const wchar_t *path; STRUCT_STAT stat; int result; if (!PyUnicode_FSDecoder(self->path, &unicode)) return NULL; +#if USE_UNICODE_WCHAR_CACHE _Py_COMP_DIAG_PUSH _Py_COMP_DIAG_IGNORE_DEPR_DECLS - path = PyUnicode_AsUnicode(unicode); -_Py_COMP_DIAG_POP + const wchar_t *path = PyUnicode_AsUnicode(unicode); result = LSTAT(path, &stat); Py_DECREF(unicode); +_Py_COMP_DIAG_POP +#else /* USE_UNICODE_WCHAR_CACHE */ + wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL); + Py_DECREF(unicode); + result = LSTAT(path, &stat); + PyMem_Free(path); +#endif /* USE_UNICODE_WCHAR_CACHE */ if (result != 0) return path_object_error(self->path); @@ -13614,7 +13788,6 @@ static PyMethodDef DirEntry_methods[] = { }; static PyType_Slot DirEntryType_slots[] = { - {Py_tp_new, _disabled_new}, {Py_tp_dealloc, DirEntry_dealloc}, {Py_tp_repr, DirEntry_repr}, {Py_tp_methods, DirEntry_methods}, @@ -13626,7 +13799,7 @@ static PyType_Spec DirEntryType_spec = { MODNAME ".DirEntry", sizeof(DirEntry), 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, DirEntryType_slots }; @@ -14046,7 +14219,6 @@ static PyMethodDef ScandirIterator_methods[] = { }; static PyType_Slot ScandirIteratorType_slots[] = { - {Py_tp_new, _disabled_new}, {Py_tp_dealloc, ScandirIterator_dealloc}, {Py_tp_finalize, ScandirIterator_finalize}, {Py_tp_iter, PyObject_SelfIter}, @@ -14061,7 +14233,8 @@ static PyType_Spec ScandirIteratorType_spec = { 0, // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance. - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE, + (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE + | Py_TPFLAGS_DISALLOW_INSTANTIATION), ScandirIteratorType_slots }; @@ -14109,10 +14282,9 @@ os_scandir_impl(PyObject *module, path_t *path) iterator->dirp = NULL; #endif - memcpy(&iterator->path, path, sizeof(path_t)); /* Move the ownership to iterator->path */ - path->object = NULL; - path->cleanup = NULL; + memcpy(&iterator->path, path, sizeof(path_t)); + memset(path, 0, sizeof(path_t)); #ifdef MS_WINDOWS iterator->first_time = 1; @@ -14137,7 +14309,7 @@ os_scandir_impl(PyObject *module, path_t *path) if (iterator->path.fd != -1) { if (HAVE_FDOPENDIR_RUNTIME) { /* closedir() closes the FD, so we duplicate it */ - fd = _Py_dup(path->fd); + fd = _Py_dup(iterator->path.fd); if (fd == -1) goto error; @@ -14427,7 +14599,7 @@ os__remove_dll_directory_impl(PyObject *module, PyObject *cookie) os.waitstatus_to_exitcode() is implemented in C and not in Python, so subprocess can safely call it during late Python finalization without - risking that used os attributes were set to None by _PyImport_Cleanup(). */ + risking that used os attributes were set to None by finalize_modules(). */ #if defined(WIFEXITED) || defined(MS_WINDOWS) /*[clinic input] os.waitstatus_to_exitcode @@ -14453,11 +14625,6 @@ static PyObject * os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj) /*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/ { - if (PyFloat_Check(status_obj)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - return NULL; - } #ifndef MS_WINDOWS int status = _PyLong_AsInt(status_obj); if (status == -1 && PyErr_Occurred()) { @@ -14549,6 +14716,7 @@ static PyMethodDef posix_methods[] = { OS_POSIX_SPAWNP_METHODDEF OS_READLINK_METHODDEF OS_COPY_FILE_RANGE_METHODDEF + OS_SPLICE_METHODDEF OS_RENAME_METHODDEF OS_REPLACE_METHODDEF OS_RMDIR_METHODDEF @@ -14697,6 +14865,9 @@ static PyMethodDef posix_methods[] = { OS_FSPATH_METHODDEF OS_GETRANDOM_METHODDEF OS_MEMFD_CREATE_METHODDEF + OS_EVENTFD_METHODDEF + OS_EVENTFD_READ_METHODDEF + OS_EVENTFD_WRITE_METHODDEF OS__ADD_DLL_DIRECTORY_METHODDEF OS__REMOVE_DLL_DIRECTORY_METHODDEF OS_WAITSTATUS_TO_EXITCODE_METHODDEF @@ -14822,7 +14993,15 @@ all_ins(PyObject *m) #ifdef O_ACCMODE if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1; #endif - +#ifdef O_EVTONLY + if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1; +#endif +#ifdef O_FSYNC + if (PyModule_AddIntMacro(m, O_FSYNC)) return -1; +#endif +#ifdef O_SYMLINK + if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1; +#endif #ifdef SEEK_HOLE if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1; @@ -14872,6 +15051,9 @@ all_ins(PyObject *m) /* Do not follow links. */ if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1; #endif +#ifdef O_NOFOLLOW_ANY + if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1; +#endif #ifdef O_NOLINKS /* Fails if link count of the named file is greater than 1 */ if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1; @@ -15065,6 +15247,16 @@ all_ins(PyObject *m) #ifdef RWF_NOWAIT if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1; #endif +#ifdef RWF_APPEND + if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1; +#endif + +/* constants for splice */ +#if defined(HAVE_SPLICE) && defined(__linux__) + if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1; + if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1; + if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1; +#endif /* constants for posix_spawn */ #ifdef HAVE_POSIX_SPAWN @@ -15202,6 +15394,12 @@ all_ins(PyObject *m) #ifdef MFD_HUGE_16GB if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1; #endif +#endif /* HAVE_MEMFD_CREATE */ + +#ifdef HAVE_EVENTFD + if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1; + if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1; + if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1; #endif #if defined(__APPLE__) @@ -15295,6 +15493,10 @@ static const struct have_function { int (*probe)(void); } have_functions[] = { +#ifdef HAVE_EVENTFD + {"HAVE_EVENTFD", NULL}, +#endif + #ifdef HAVE_FACCESSAT { "HAVE_FACCESSAT", probe_faccessat }, #endif diff --git a/contrib/tools/python3/src/Modules/pwdmodule.c b/contrib/tools/python3/src/Modules/pwdmodule.c index 901a3ed9a2..14d3f9dcb1 100644 --- a/contrib/tools/python3/src/Modules/pwdmodule.c +++ b/contrib/tools/python3/src/Modules/pwdmodule.c @@ -59,8 +59,6 @@ get_pwd_state(PyObject *module) return (pwdmodulestate *)state; } -#define modulestate_global get_pwd_state(PyState_FindModule(&pwdmodule)) - static struct PyModuleDef pwdmodule; #define DEFAULT_BUFFER_SIZE 1024 @@ -79,10 +77,10 @@ sets(PyObject *v, int i, const char* val) } static PyObject * -mkpwent(struct passwd *p) +mkpwent(PyObject *module, struct passwd *p) { int setIndex = 0; - PyObject *v = PyStructSequence_New(modulestate_global->StructPwdType); + PyObject *v = PyStructSequence_New(get_pwd_state(module)->StructPwdType); if (v == NULL) return NULL; @@ -194,7 +192,7 @@ pwd_getpwuid(PyObject *module, PyObject *uidobj) Py_DECREF(uid_obj); return NULL; } - retval = mkpwent(p); + retval = mkpwent(module, p); #ifdef HAVE_GETPWUID_R PyMem_RawFree(buf); #endif @@ -274,7 +272,7 @@ pwd_getpwnam_impl(PyObject *module, PyObject *name) } goto out; } - retval = mkpwent(p); + retval = mkpwent(module, p); out: PyMem_RawFree(buf); Py_DECREF(bytes); @@ -300,7 +298,7 @@ pwd_getpwall_impl(PyObject *module) return NULL; setpwent(); while ((p = getpwent()) != NULL) { - PyObject *v = mkpwent(p); + PyObject *v = mkpwent(module, p); if (v == NULL || PyList_Append(d, v) != 0) { Py_XDECREF(v); Py_DECREF(d); @@ -323,6 +321,26 @@ static PyMethodDef pwd_methods[] = { {NULL, NULL} /* sentinel */ }; +static int +pwdmodule_exec(PyObject *module) +{ + pwdmodulestate *state = get_pwd_state(module); + + state->StructPwdType = PyStructSequence_NewType(&struct_pwd_type_desc); + if (state->StructPwdType == NULL) { + return -1; + } + if (PyModule_AddType(module, state->StructPwdType) < 0) { + return -1; + } + return 0; +} + +static PyModuleDef_Slot pwdmodule_slots[] = { + {Py_mod_exec, pwdmodule_exec}, + {0, NULL} +}; + static int pwdmodule_traverse(PyObject *m, visitproc visit, void *arg) { Py_VISIT(get_pwd_state(m)->StructPwdType); return 0; @@ -337,34 +355,19 @@ static void pwdmodule_free(void *m) { static struct PyModuleDef pwdmodule = { PyModuleDef_HEAD_INIT, - "pwd", - pwd__doc__, - sizeof(pwdmodulestate), - pwd_methods, - NULL, - pwdmodule_traverse, - pwdmodule_clear, - pwdmodule_free, + .m_name = "pwd", + .m_doc = pwd__doc__, + .m_size = sizeof(pwdmodulestate), + .m_methods = pwd_methods, + .m_slots = pwdmodule_slots, + .m_traverse = pwdmodule_traverse, + .m_clear = pwdmodule_clear, + .m_free = pwdmodule_free, }; PyMODINIT_FUNC PyInit_pwd(void) { - PyObject *m; - if ((m = PyState_FindModule(&pwdmodule)) != NULL) { - Py_INCREF(m); - return m; - } - if ((m = PyModule_Create(&pwdmodule)) == NULL) - return NULL; - - pwdmodulestate *state = PyModule_GetState(m); - state->StructPwdType = PyStructSequence_NewType(&struct_pwd_type_desc); - if (state->StructPwdType == NULL) { - return NULL; - } - Py_INCREF(state->StructPwdType); - PyModule_AddObject(m, "struct_passwd", (PyObject *) state->StructPwdType); - return m; + return PyModuleDef_Init(&pwdmodule); } diff --git a/contrib/tools/python3/src/Modules/pyexpat.c b/contrib/tools/python3/src/Modules/pyexpat.c index 12ae66d945..b3d9bdda7e 100644 --- a/contrib/tools/python3/src/Modules/pyexpat.c +++ b/contrib/tools/python3/src/Modules/pyexpat.c @@ -47,7 +47,18 @@ enum HandlerTypes { _DummyDecl }; -static PyObject *ErrorObject; +typedef struct { + PyTypeObject *xml_parse_type; + PyObject *error; +} pyexpat_state; + +static inline pyexpat_state* +pyexpat_get_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (pyexpat_state *)state; +} /* ----------------------------------------------------- */ @@ -73,8 +84,6 @@ typedef struct { #define CHARACTER_DATA_BUFFER_SIZE 8192 -static PyTypeObject Xmlparsetype; - typedef void (*xmlhandlersetter)(XML_Parser self, void *meth); typedef void* xmlhandler; @@ -107,7 +116,7 @@ set_error_attr(PyObject *err, const char *name, int value) * information. Always returns NULL. */ static PyObject * -set_error(xmlparseobject *self, enum XML_Error code) +set_error(pyexpat_state *state, xmlparseobject *self, enum XML_Error code) { PyObject *err; PyObject *buffer; @@ -119,13 +128,13 @@ set_error(xmlparseobject *self, enum XML_Error code) XML_ErrorString(code), lineno, column); if (buffer == NULL) return NULL; - err = PyObject_CallOneArg(ErrorObject, buffer); + err = PyObject_CallOneArg(state->error, buffer); Py_DECREF(buffer); if ( err != NULL && set_error_attr(err, "code", code) && set_error_attr(err, "offset", column) && set_error_attr(err, "lineno", lineno)) { - PyErr_SetObject(ErrorObject, err); + PyErr_SetObject(state->error, err); } Py_XDECREF(err); return NULL; @@ -680,13 +689,13 @@ class pyexpat.xmlparser "xmlparseobject *" "&Xmlparsetype" static PyObject * -get_parse_result(xmlparseobject *self, int rv) +get_parse_result(pyexpat_state *state, xmlparseobject *self, int rv) { if (PyErr_Occurred()) { return NULL; } if (rv == 0) { - return set_error(self, XML_GetErrorCode(self->itself)); + return set_error(state, self, XML_GetErrorCode(self->itself)); } if (flush_character_buffer(self) < 0) { return NULL; @@ -699,6 +708,7 @@ get_parse_result(xmlparseobject *self, int rv) /*[clinic input] pyexpat.xmlparser.Parse + cls: defining_class data: object isfinal: bool(accept={int}) = False / @@ -709,14 +719,15 @@ Parse XML data. [clinic start generated code]*/ static PyObject * -pyexpat_xmlparser_Parse_impl(xmlparseobject *self, PyObject *data, - int isfinal) -/*[clinic end generated code: output=f4db843dd1f4ed4b input=eb616027bfa9847f]*/ +pyexpat_xmlparser_Parse_impl(xmlparseobject *self, PyTypeObject *cls, + PyObject *data, int isfinal) +/*[clinic end generated code: output=8faffe07fe1f862a input=fc97f833558ca715]*/ { const char *s; Py_ssize_t slen; Py_buffer view; int rc; + pyexpat_state *state = PyType_GetModuleState(cls); if (PyUnicode_Check(data)) { view.buf = NULL; @@ -745,9 +756,10 @@ pyexpat_xmlparser_Parse_impl(xmlparseobject *self, PyObject *data, rc = XML_Parse(self->itself, s, (int)slen, isfinal); done: - if (view.buf != NULL) + if (view.buf != NULL) { PyBuffer_Release(&view); - return get_parse_result(self, rc); + } + return get_parse_result(state, self, rc); } /* File reading copied from cPickle */ @@ -796,6 +808,7 @@ error: /*[clinic input] pyexpat.xmlparser.ParseFile + cls: defining_class file: object / @@ -803,13 +816,16 @@ Parse XML data from file-like object. [clinic start generated code]*/ static PyObject * -pyexpat_xmlparser_ParseFile(xmlparseobject *self, PyObject *file) -/*[clinic end generated code: output=2adc6a13100cc42b input=fbb5a12b6038d735]*/ +pyexpat_xmlparser_ParseFile_impl(xmlparseobject *self, PyTypeObject *cls, + PyObject *file) +/*[clinic end generated code: output=34780a094c8ca3ae input=ba4bc9c541684793]*/ { int rv = 1; PyObject *readmethod = NULL; _Py_IDENTIFIER(read); + pyexpat_state *state = PyType_GetModuleState(cls); + if (_PyObject_LookupAttrId(file, &PyId_read, &readmethod) < 0) { return NULL; } @@ -823,7 +839,7 @@ pyexpat_xmlparser_ParseFile(xmlparseobject *self, PyObject *file) void *buf = XML_GetBuffer(self->itself, BUF_SIZE); if (buf == NULL) { Py_XDECREF(readmethod); - return get_parse_result(self, 0); + return get_parse_result(state, self, 0); } bytes_read = readinst(buf, BUF_SIZE, readmethod); @@ -841,7 +857,7 @@ pyexpat_xmlparser_ParseFile(xmlparseobject *self, PyObject *file) break; } Py_XDECREF(readmethod); - return get_parse_result(self, rv); + return get_parse_result(state, self, rv); } /*[clinic input] @@ -907,6 +923,7 @@ pyexpat_xmlparser_GetInputContext_impl(xmlparseobject *self) /*[clinic input] pyexpat.xmlparser.ExternalEntityParserCreate + cls: defining_class context: str(accept={str, NoneType}) encoding: str = NULL / @@ -916,16 +933,21 @@ Create a parser for parsing an external entity based on the information passed t static PyObject * pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self, + PyTypeObject *cls, const char *context, const char *encoding) -/*[clinic end generated code: output=535cda9d7a0fbcd6 input=b906714cc122c322]*/ +/*[clinic end generated code: output=01d4472b49cb3f92 input=ec70c6b9e6e9619a]*/ { xmlparseobject *new_parser; int i; - new_parser = PyObject_GC_New(xmlparseobject, &Xmlparsetype); - if (new_parser == NULL) + pyexpat_state *state = PyType_GetModuleState(cls); + + new_parser = PyObject_GC_New(xmlparseobject, state->xml_parse_type); + if (new_parser == NULL) { return NULL; + } + new_parser->buffer_size = self->buffer_size; new_parser->buffer_used = 0; new_parser->buffer = NULL; @@ -1006,6 +1028,7 @@ pyexpat_xmlparser_SetParamEntityParsing_impl(xmlparseobject *self, int flag) /*[clinic input] pyexpat.xmlparser.UseForeignDTD + cls: defining_class flag: bool = True / @@ -1017,14 +1040,16 @@ information to the parser. 'flag' defaults to True if not provided. [clinic start generated code]*/ static PyObject * -pyexpat_xmlparser_UseForeignDTD_impl(xmlparseobject *self, int flag) -/*[clinic end generated code: output=cfaa9aa50bb0f65c input=78144c519d116a6e]*/ +pyexpat_xmlparser_UseForeignDTD_impl(xmlparseobject *self, PyTypeObject *cls, + int flag) +/*[clinic end generated code: output=d7d98252bd25a20f input=23440ecb0573fb29]*/ { + pyexpat_state *state = PyType_GetModuleState(cls); enum XML_Error rc; rc = XML_UseForeignDTD(self->itself, flag ? XML_TRUE : XML_FALSE); if (rc != XML_ERROR_NONE) { - return set_error(self, rc); + return set_error(state, self, rc); } Py_RETURN_NONE; } @@ -1104,12 +1129,13 @@ PyUnknownEncodingHandler(void *encodingHandlerData, static PyObject * -newxmlparseobject(const char *encoding, const char *namespace_separator, PyObject *intern) +newxmlparseobject(pyexpat_state *state, const char *encoding, + const char *namespace_separator, PyObject *intern) { int i; xmlparseobject *self; - self = PyObject_GC_New(xmlparseobject, &Xmlparsetype); + self = PyObject_GC_New(xmlparseobject, state->xml_parse_type); if (self == NULL) return NULL; @@ -1156,19 +1182,34 @@ newxmlparseobject(const char *encoding, const char *namespace_separator, PyObjec return (PyObject*)self; } +static int +xmlparse_traverse(xmlparseobject *op, visitproc visit, void *arg) +{ + for (int i = 0; handler_info[i].name != NULL; i++) { + Py_VISIT(op->handlers[i]); + } + Py_VISIT(Py_TYPE(op)); + return 0; +} + +static int +xmlparse_clear(xmlparseobject *op) +{ + clear_handlers(op, 0); + Py_CLEAR(op->intern); + return 0; +} static void xmlparse_dealloc(xmlparseobject *self) { - int i; PyObject_GC_UnTrack(self); + (void)xmlparse_clear(self); if (self->itself != NULL) XML_ParserFree(self->itself); self->itself = NULL; if (self->handlers != NULL) { - for (i = 0; handler_info[i].name != NULL; i++) - Py_CLEAR(self->handlers[i]); PyMem_Free(self->handlers); self->handlers = NULL; } @@ -1176,8 +1217,9 @@ xmlparse_dealloc(xmlparseobject *self) PyMem_Free(self->buffer); self->buffer = NULL; } - Py_XDECREF(self->intern); + PyTypeObject *tp = Py_TYPE(self); PyObject_GC_Del(self); + Py_DECREF(tp); } @@ -1445,57 +1487,25 @@ static PyGetSetDef xmlparse_getsetlist[] = { #undef XMLPARSE_GETTER_DEF #undef XMLPARSE_GETTER_SETTER_DEF -static int -xmlparse_traverse(xmlparseobject *op, visitproc visit, void *arg) -{ - int i; - for (i = 0; handler_info[i].name != NULL; i++) - Py_VISIT(op->handlers[i]); - return 0; -} - -static int -xmlparse_clear(xmlparseobject *op) -{ - clear_handlers(op, 0); - Py_CLEAR(op->intern); - return 0; -} - PyDoc_STRVAR(Xmlparsetype__doc__, "XML parser"); -static PyTypeObject Xmlparsetype = { - PyVarObject_HEAD_INIT(NULL, 0) - "pyexpat.xmlparser", /*tp_name*/ - sizeof(xmlparseobject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)xmlparse_dealloc, /*tp_dealloc*/ - 0, /*tp_vectorcall_offset*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_as_async*/ - (reprfunc)0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - (hashfunc)0, /*tp_hash*/ - (ternaryfunc)0, /*tp_call*/ - (reprfunc)0, /*tp_str*/ - (getattrofunc)0, /* tp_getattro */ - (setattrofunc)0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ - Xmlparsetype__doc__, /* tp_doc - Documentation string */ - (traverseproc)xmlparse_traverse, /* tp_traverse */ - (inquiry)xmlparse_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - xmlparse_methods, /* tp_methods */ - xmlparse_members, /* tp_members */ - xmlparse_getsetlist, /* tp_getset */ +static PyType_Slot _xml_parse_type_spec_slots[] = { + {Py_tp_dealloc, xmlparse_dealloc}, + {Py_tp_doc, (void *)Xmlparsetype__doc__}, + {Py_tp_traverse, xmlparse_traverse}, + {Py_tp_clear, xmlparse_clear}, + {Py_tp_methods, xmlparse_methods}, + {Py_tp_members, xmlparse_members}, + {Py_tp_getset, xmlparse_getsetlist}, + {0, 0} +}; + +static PyType_Spec _xml_parse_type_spec = { + .name = "pyexpat.xmlparser", + .basicsize = sizeof(xmlparseobject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE), + .slots = _xml_parse_type_spec_slots, }; /* End of code for xmlparser objects */ @@ -1541,7 +1551,8 @@ pyexpat_ParserCreate_impl(PyObject *module, const char *encoding, return NULL; } - result = newxmlparseobject(encoding, namespace_separator, intern); + pyexpat_state *state = pyexpat_get_state(module); + result = newxmlparseobject(state, encoding, namespace_separator, intern); if (intern_decref) { Py_DECREF(intern); } @@ -1583,26 +1594,10 @@ PyDoc_STRVAR(pyexpat_module_documentation, #define MODULE_NAME "pyexpat" #endif -#ifndef MODULE_INITFUNC -#define MODULE_INITFUNC PyInit_pyexpat -#endif - -static struct PyModuleDef pyexpatmodule = { - PyModuleDef_HEAD_INIT, - MODULE_NAME, - pyexpat_module_documentation, - -1, - pyexpat_methods, - NULL, - NULL, - NULL, - NULL -}; - -static int init_handler_descrs(void) +static int init_handler_descrs(pyexpat_state *state) { int i; - assert(!PyType_HasFeature(&Xmlparsetype, Py_TPFLAGS_VALID_VERSION_TAG)); + assert(!PyType_HasFeature(state->xml_parse_type, Py_TPFLAGS_VALID_VERSION_TAG)); for (i = 0; handler_info[i].name != NULL; i++) { struct HandlerInfo *hi = &handler_info[i]; hi->getset.name = hi->name; @@ -1610,19 +1605,11 @@ static int init_handler_descrs(void) hi->getset.set = (setter)xmlparse_handler_setter; hi->getset.closure = &handler_info[i]; - PyObject *descr = PyDescr_NewGetSet(&Xmlparsetype, &hi->getset); + PyObject *descr = PyDescr_NewGetSet(state->xml_parse_type, &hi->getset); if (descr == NULL) return -1; - if (PyDict_GetItemWithError(Xmlparsetype.tp_dict, PyDescr_NAME(descr))) { - Py_DECREF(descr); - continue; - } - else if (PyErr_Occurred()) { - Py_DECREF(descr); - return -1; - } - if (PyDict_SetItem(Xmlparsetype.tp_dict, PyDescr_NAME(descr), descr) < 0) { + if (PyDict_SetDefault(state->xml_parse_type->tp_dict, PyDescr_NAME(descr), descr) == NULL) { Py_DECREF(descr); return -1; } @@ -1631,210 +1618,182 @@ static int init_handler_descrs(void) return 0; } -PyMODINIT_FUNC -MODULE_INITFUNC(void) +static PyObject * +add_submodule(PyObject *mod, const char *fullname) { - PyObject *m, *d; - PyObject *errmod_name = PyUnicode_FromString(MODULE_NAME ".errors"); - PyObject *errors_module; - PyObject *modelmod_name; - PyObject *model_module; - PyObject *tmpnum, *tmpstr; - PyObject *codes_dict; - PyObject *rev_codes_dict; - int res; - static struct PyExpat_CAPI capi; - PyObject *capi_object; - - if (errmod_name == NULL) - return NULL; - modelmod_name = PyUnicode_FromString(MODULE_NAME ".model"); - if (modelmod_name == NULL) + const char *name = strrchr(fullname, '.') + 1; + + PyObject *submodule = PyModule_New(fullname); + if (submodule == NULL) { return NULL; + } - if (PyType_Ready(&Xmlparsetype) < 0 || init_handler_descrs() < 0) + PyObject *mod_name = PyUnicode_FromString(fullname); + if (mod_name == NULL) { + Py_DECREF(submodule); return NULL; + } - /* Create the module and add the functions */ - m = PyModule_Create(&pyexpatmodule); - if (m == NULL) + if (_PyImport_SetModule(mod_name, submodule) < 0) { + Py_DECREF(submodule); + Py_DECREF(mod_name); return NULL; + } + Py_DECREF(mod_name); - /* Add some symbolic constants to the module */ - if (ErrorObject == NULL) { - ErrorObject = PyErr_NewException("xml.parsers.expat.ExpatError", - NULL, NULL); - if (ErrorObject == NULL) - return NULL; + /* gives away the reference to the submodule */ + if (PyModule_AddObject(mod, name, submodule) < 0) { + Py_DECREF(submodule); + return NULL; } - Py_INCREF(ErrorObject); - PyModule_AddObject(m, "error", ErrorObject); - Py_INCREF(ErrorObject); - PyModule_AddObject(m, "ExpatError", ErrorObject); - Py_INCREF(&Xmlparsetype); - PyModule_AddObject(m, "XMLParserType", (PyObject *) &Xmlparsetype); - PyModule_AddStringConstant(m, "EXPAT_VERSION", - XML_ExpatVersion()); - { - XML_Expat_Version info = XML_ExpatVersionInfo(); - PyModule_AddObject(m, "version_info", - Py_BuildValue("(iii)", info.major, - info.minor, info.micro)); + return submodule; +} + +static int +add_error(PyObject *errors_module, PyObject *codes_dict, + PyObject *rev_codes_dict, const char *name, int value) +{ + const char *error_string = XML_ErrorString(value); + if (PyModule_AddStringConstant(errors_module, name, error_string) < 0) { + return -1; } - /* XXX When Expat supports some way of figuring out how it was - compiled, this should check and set native_encoding - appropriately. - */ - PyModule_AddStringConstant(m, "native_encoding", "UTF-8"); - d = PyModule_GetDict(m); - if (d == NULL) { - Py_DECREF(m); - return NULL; + PyObject *num = PyLong_FromLong(value); + if (num == NULL) { + return -1; } - errors_module = PyDict_GetItemWithError(d, errmod_name); - if (errors_module == NULL && !PyErr_Occurred()) { - errors_module = PyModule_New(MODULE_NAME ".errors"); - if (errors_module != NULL) { - _PyImport_SetModule(errmod_name, errors_module); - /* gives away the reference to errors_module */ - PyModule_AddObject(m, "errors", errors_module); - } + + if (PyDict_SetItemString(codes_dict, error_string, num) < 0) { + Py_DECREF(num); + return -1; } - Py_DECREF(errmod_name); - model_module = PyDict_GetItemWithError(d, modelmod_name); - if (model_module == NULL && !PyErr_Occurred()) { - model_module = PyModule_New(MODULE_NAME ".model"); - if (model_module != NULL) { - _PyImport_SetModule(modelmod_name, model_module); - /* gives away the reference to model_module */ - PyModule_AddObject(m, "model", model_module); - } + + PyObject *str = PyUnicode_FromString(error_string); + if (str == NULL) { + Py_DECREF(num); + return -1; } - Py_DECREF(modelmod_name); - if (errors_module == NULL || model_module == NULL) { - /* Don't core dump later! */ - Py_DECREF(m); - return NULL; + + int res = PyDict_SetItem(rev_codes_dict, num, str); + Py_DECREF(str); + Py_DECREF(num); + if (res < 0) { + return -1; } -#if XML_COMBINED_VERSION > 19505 - { - const XML_Feature *features = XML_GetFeatureList(); - PyObject *list = PyList_New(0); - if (list == NULL) - /* just ignore it */ - PyErr_Clear(); - else { - int i = 0; - for (; features[i].feature != XML_FEATURE_END; ++i) { - int ok; - PyObject *item = Py_BuildValue("si", features[i].name, - features[i].value); - if (item == NULL) { - Py_DECREF(list); - list = NULL; - break; - } - ok = PyList_Append(list, item); - Py_DECREF(item); - if (ok < 0) { - PyErr_Clear(); - break; - } - } - if (list != NULL) - PyModule_AddObject(m, "features", list); - } + return 0; +} + +static int +add_errors_module(PyObject *mod) +{ + PyObject *errors_module = add_submodule(mod, MODULE_NAME ".errors"); + if (errors_module == NULL) { + return -1; } -#endif - codes_dict = PyDict_New(); - rev_codes_dict = PyDict_New(); + PyObject *codes_dict = PyDict_New(); + PyObject *rev_codes_dict = PyDict_New(); if (codes_dict == NULL || rev_codes_dict == NULL) { - Py_XDECREF(codes_dict); - Py_XDECREF(rev_codes_dict); - return NULL; + goto error; } -#define MYCONST(name) \ - if (PyModule_AddStringConstant(errors_module, #name, \ - XML_ErrorString(name)) < 0) \ - return NULL; \ - tmpnum = PyLong_FromLong(name); \ - if (tmpnum == NULL) return NULL; \ - res = PyDict_SetItemString(codes_dict, \ - XML_ErrorString(name), tmpnum); \ - if (res < 0) return NULL; \ - tmpstr = PyUnicode_FromString(XML_ErrorString(name)); \ - if (tmpstr == NULL) return NULL; \ - res = PyDict_SetItem(rev_codes_dict, tmpnum, tmpstr); \ - Py_DECREF(tmpstr); \ - Py_DECREF(tmpnum); \ - if (res < 0) return NULL; \ - - MYCONST(XML_ERROR_NO_MEMORY); - MYCONST(XML_ERROR_SYNTAX); - MYCONST(XML_ERROR_NO_ELEMENTS); - MYCONST(XML_ERROR_INVALID_TOKEN); - MYCONST(XML_ERROR_UNCLOSED_TOKEN); - MYCONST(XML_ERROR_PARTIAL_CHAR); - MYCONST(XML_ERROR_TAG_MISMATCH); - MYCONST(XML_ERROR_DUPLICATE_ATTRIBUTE); - MYCONST(XML_ERROR_JUNK_AFTER_DOC_ELEMENT); - MYCONST(XML_ERROR_PARAM_ENTITY_REF); - MYCONST(XML_ERROR_UNDEFINED_ENTITY); - MYCONST(XML_ERROR_RECURSIVE_ENTITY_REF); - MYCONST(XML_ERROR_ASYNC_ENTITY); - MYCONST(XML_ERROR_BAD_CHAR_REF); - MYCONST(XML_ERROR_BINARY_ENTITY_REF); - MYCONST(XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF); - MYCONST(XML_ERROR_MISPLACED_XML_PI); - MYCONST(XML_ERROR_UNKNOWN_ENCODING); - MYCONST(XML_ERROR_INCORRECT_ENCODING); - MYCONST(XML_ERROR_UNCLOSED_CDATA_SECTION); - MYCONST(XML_ERROR_EXTERNAL_ENTITY_HANDLING); - MYCONST(XML_ERROR_NOT_STANDALONE); - MYCONST(XML_ERROR_UNEXPECTED_STATE); - MYCONST(XML_ERROR_ENTITY_DECLARED_IN_PE); - MYCONST(XML_ERROR_FEATURE_REQUIRES_XML_DTD); - MYCONST(XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING); +#define ADD_CONST(name) do { \ + if (add_error(errors_module, codes_dict, rev_codes_dict, \ + #name, name) < 0) { \ + goto error; \ + } \ + } while(0) + + ADD_CONST(XML_ERROR_NO_MEMORY); + ADD_CONST(XML_ERROR_SYNTAX); + ADD_CONST(XML_ERROR_NO_ELEMENTS); + ADD_CONST(XML_ERROR_INVALID_TOKEN); + ADD_CONST(XML_ERROR_UNCLOSED_TOKEN); + ADD_CONST(XML_ERROR_PARTIAL_CHAR); + ADD_CONST(XML_ERROR_TAG_MISMATCH); + ADD_CONST(XML_ERROR_DUPLICATE_ATTRIBUTE); + ADD_CONST(XML_ERROR_JUNK_AFTER_DOC_ELEMENT); + ADD_CONST(XML_ERROR_PARAM_ENTITY_REF); + ADD_CONST(XML_ERROR_UNDEFINED_ENTITY); + ADD_CONST(XML_ERROR_RECURSIVE_ENTITY_REF); + ADD_CONST(XML_ERROR_ASYNC_ENTITY); + ADD_CONST(XML_ERROR_BAD_CHAR_REF); + ADD_CONST(XML_ERROR_BINARY_ENTITY_REF); + ADD_CONST(XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF); + ADD_CONST(XML_ERROR_MISPLACED_XML_PI); + ADD_CONST(XML_ERROR_UNKNOWN_ENCODING); + ADD_CONST(XML_ERROR_INCORRECT_ENCODING); + ADD_CONST(XML_ERROR_UNCLOSED_CDATA_SECTION); + ADD_CONST(XML_ERROR_EXTERNAL_ENTITY_HANDLING); + ADD_CONST(XML_ERROR_NOT_STANDALONE); + ADD_CONST(XML_ERROR_UNEXPECTED_STATE); + ADD_CONST(XML_ERROR_ENTITY_DECLARED_IN_PE); + ADD_CONST(XML_ERROR_FEATURE_REQUIRES_XML_DTD); + ADD_CONST(XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING); /* Added in Expat 1.95.7. */ - MYCONST(XML_ERROR_UNBOUND_PREFIX); + ADD_CONST(XML_ERROR_UNBOUND_PREFIX); /* Added in Expat 1.95.8. */ - MYCONST(XML_ERROR_UNDECLARING_PREFIX); - MYCONST(XML_ERROR_INCOMPLETE_PE); - MYCONST(XML_ERROR_XML_DECL); - MYCONST(XML_ERROR_TEXT_DECL); - MYCONST(XML_ERROR_PUBLICID); - MYCONST(XML_ERROR_SUSPENDED); - MYCONST(XML_ERROR_NOT_SUSPENDED); - MYCONST(XML_ERROR_ABORTED); - MYCONST(XML_ERROR_FINISHED); - MYCONST(XML_ERROR_SUSPEND_PE); + ADD_CONST(XML_ERROR_UNDECLARING_PREFIX); + ADD_CONST(XML_ERROR_INCOMPLETE_PE); + ADD_CONST(XML_ERROR_XML_DECL); + ADD_CONST(XML_ERROR_TEXT_DECL); + ADD_CONST(XML_ERROR_PUBLICID); + ADD_CONST(XML_ERROR_SUSPENDED); + ADD_CONST(XML_ERROR_NOT_SUSPENDED); + ADD_CONST(XML_ERROR_ABORTED); + ADD_CONST(XML_ERROR_FINISHED); + ADD_CONST(XML_ERROR_SUSPEND_PE); +#undef ADD_CONST if (PyModule_AddStringConstant(errors_module, "__doc__", "Constants used to describe " - "error conditions.") < 0) - return NULL; + "error conditions.") < 0) { + goto error; + } - if (PyModule_AddObject(errors_module, "codes", codes_dict) < 0) - return NULL; - if (PyModule_AddObject(errors_module, "messages", rev_codes_dict) < 0) - return NULL; + Py_INCREF(codes_dict); + if (PyModule_AddObject(errors_module, "codes", codes_dict) < 0) { + Py_DECREF(codes_dict); + goto error; + } + Py_CLEAR(codes_dict); -#undef MYCONST + Py_INCREF(rev_codes_dict); + if (PyModule_AddObject(errors_module, "messages", rev_codes_dict) < 0) { + Py_DECREF(rev_codes_dict); + goto error; + } + Py_CLEAR(rev_codes_dict); -#define MYCONST(c) PyModule_AddIntConstant(m, #c, c) - MYCONST(XML_PARAM_ENTITY_PARSING_NEVER); - MYCONST(XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE); - MYCONST(XML_PARAM_ENTITY_PARSING_ALWAYS); -#undef MYCONST + return 0; -#define MYCONST(c) PyModule_AddIntConstant(model_module, #c, c) - PyModule_AddStringConstant(model_module, "__doc__", - "Constants used to interpret content model information."); +error: + Py_XDECREF(codes_dict); + Py_XDECREF(rev_codes_dict); + return -1; +} + +static int +add_model_module(PyObject *mod) +{ + PyObject *model_module = add_submodule(mod, MODULE_NAME ".model"); + if (model_module == NULL) { + return -1; + } + +#define MYCONST(c) do { \ + if (PyModule_AddIntConstant(model_module, #c, c) < 0) { \ + return -1; \ + } \ + } while(0) + + if (PyModule_AddStringConstant( + model_module, "__doc__", + "Constants used to interpret content model information.") < 0) { + return -1; + } MYCONST(XML_CTYPE_EMPTY); MYCONST(XML_CTYPE_ANY); @@ -1848,42 +1807,228 @@ MODULE_INITFUNC(void) MYCONST(XML_CQUANT_REP); MYCONST(XML_CQUANT_PLUS); #undef MYCONST + return 0; +} + +#if XML_COMBINED_VERSION > 19505 +static int +add_features(PyObject *mod) +{ + PyObject *list = PyList_New(0); + if (list == NULL) { + return -1; + } + + const XML_Feature *features = XML_GetFeatureList(); + for (size_t i = 0; features[i].feature != XML_FEATURE_END; ++i) { + PyObject *item = Py_BuildValue("si", features[i].name, + features[i].value); + if (item == NULL) { + goto error; + } + int ok = PyList_Append(list, item); + Py_DECREF(item); + if (ok < 0) { + goto error; + } + } + if (PyModule_AddObject(mod, "features", list) < 0) { + goto error; + } + return 0; + +error: + Py_DECREF(list); + return -1; +} +#endif + +static void +pyexpat_destructor(PyObject *op) +{ + void *p = PyCapsule_GetPointer(op, PyExpat_CAPSULE_NAME); + PyMem_Free(p); +} + +static int +pyexpat_exec(PyObject *mod) +{ + pyexpat_state *state = pyexpat_get_state(mod); + state->xml_parse_type = (PyTypeObject *)PyType_FromModuleAndSpec( + mod, &_xml_parse_type_spec, NULL); + + if (state->xml_parse_type == NULL) { + return -1; + } + + if (init_handler_descrs(state) < 0) { + return -1; + } + state->error = PyErr_NewException("xml.parsers.expat.ExpatError", + NULL, NULL); + if (state->error == NULL) { + return -1; + } + + /* Add some symbolic constants to the module */ + + if (PyModule_AddObjectRef(mod, "error", state->error) < 0) { + return -1; + } + + if (PyModule_AddObjectRef(mod, "ExpatError", state->error) < 0) { + return -1; + } + + if (PyModule_AddObjectRef(mod, "XMLParserType", + (PyObject *) state->xml_parse_type) < 0) { + return -1; + } + + if (PyModule_AddStringConstant(mod, "EXPAT_VERSION", + XML_ExpatVersion()) < 0) { + return -1; + } + { + XML_Expat_Version info = XML_ExpatVersionInfo(); + PyObject *versionInfo = Py_BuildValue("(iii)", + info.major, + info.minor, + info.micro); + if (PyModule_AddObject(mod, "version_info", versionInfo) < 0) { + Py_DECREF(versionInfo); + return -1; + } + } + /* XXX When Expat supports some way of figuring out how it was + compiled, this should check and set native_encoding + appropriately. + */ + if (PyModule_AddStringConstant(mod, "native_encoding", "UTF-8") < 0) { + return -1; + } + + if (add_errors_module(mod) < 0) { + return -1; + } + + if (add_model_module(mod) < 0) { + return -1; + } + +#if XML_COMBINED_VERSION > 19505 + if (add_features(mod) < 0) { + return -1; + } +#endif + +#define MYCONST(c) do { \ + if (PyModule_AddIntConstant(mod, #c, c) < 0) { \ + return -1; \ + } \ + } while(0) + + MYCONST(XML_PARAM_ENTITY_PARSING_NEVER); + MYCONST(XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE); + MYCONST(XML_PARAM_ENTITY_PARSING_ALWAYS); +#undef MYCONST + struct PyExpat_CAPI *capi = PyMem_Calloc(1, sizeof(struct PyExpat_CAPI)); + if (capi == NULL) { + PyErr_NoMemory(); + return -1; + } /* initialize pyexpat dispatch table */ - capi.size = sizeof(capi); - capi.magic = PyExpat_CAPI_MAGIC; - capi.MAJOR_VERSION = XML_MAJOR_VERSION; - capi.MINOR_VERSION = XML_MINOR_VERSION; - capi.MICRO_VERSION = XML_MICRO_VERSION; - capi.ErrorString = XML_ErrorString; - capi.GetErrorCode = XML_GetErrorCode; - capi.GetErrorColumnNumber = XML_GetErrorColumnNumber; - capi.GetErrorLineNumber = XML_GetErrorLineNumber; - capi.Parse = XML_Parse; - capi.ParserCreate_MM = XML_ParserCreate_MM; - capi.ParserFree = XML_ParserFree; - capi.SetCharacterDataHandler = XML_SetCharacterDataHandler; - capi.SetCommentHandler = XML_SetCommentHandler; - capi.SetDefaultHandlerExpand = XML_SetDefaultHandlerExpand; - capi.SetElementHandler = XML_SetElementHandler; - capi.SetNamespaceDeclHandler = XML_SetNamespaceDeclHandler; - capi.SetProcessingInstructionHandler = XML_SetProcessingInstructionHandler; - capi.SetUnknownEncodingHandler = XML_SetUnknownEncodingHandler; - capi.SetUserData = XML_SetUserData; - capi.SetStartDoctypeDeclHandler = XML_SetStartDoctypeDeclHandler; - capi.SetEncoding = XML_SetEncoding; - capi.DefaultUnknownEncodingHandler = PyUnknownEncodingHandler; + capi->size = sizeof(*capi); + capi->magic = PyExpat_CAPI_MAGIC; + capi->MAJOR_VERSION = XML_MAJOR_VERSION; + capi->MINOR_VERSION = XML_MINOR_VERSION; + capi->MICRO_VERSION = XML_MICRO_VERSION; + capi->ErrorString = XML_ErrorString; + capi->GetErrorCode = XML_GetErrorCode; + capi->GetErrorColumnNumber = XML_GetErrorColumnNumber; + capi->GetErrorLineNumber = XML_GetErrorLineNumber; + capi->Parse = XML_Parse; + capi->ParserCreate_MM = XML_ParserCreate_MM; + capi->ParserFree = XML_ParserFree; + capi->SetCharacterDataHandler = XML_SetCharacterDataHandler; + capi->SetCommentHandler = XML_SetCommentHandler; + capi->SetDefaultHandlerExpand = XML_SetDefaultHandlerExpand; + capi->SetElementHandler = XML_SetElementHandler; + capi->SetNamespaceDeclHandler = XML_SetNamespaceDeclHandler; + capi->SetProcessingInstructionHandler = XML_SetProcessingInstructionHandler; + capi->SetUnknownEncodingHandler = XML_SetUnknownEncodingHandler; + capi->SetUserData = XML_SetUserData; + capi->SetStartDoctypeDeclHandler = XML_SetStartDoctypeDeclHandler; + capi->SetEncoding = XML_SetEncoding; + capi->DefaultUnknownEncodingHandler = PyUnknownEncodingHandler; #if XML_COMBINED_VERSION >= 20100 - capi.SetHashSalt = XML_SetHashSalt; + capi->SetHashSalt = XML_SetHashSalt; #else - capi.SetHashSalt = NULL; + capi->SetHashSalt = NULL; #endif /* export using capsule */ - capi_object = PyCapsule_New(&capi, PyExpat_CAPSULE_NAME, NULL); - if (capi_object) - PyModule_AddObject(m, "expat_CAPI", capi_object); - return m; + PyObject *capi_object = PyCapsule_New(capi, PyExpat_CAPSULE_NAME, + pyexpat_destructor); + if (capi_object == NULL) { + PyMem_Free(capi); + return -1; + } + + if (PyModule_AddObject(mod, "expat_CAPI", capi_object) < 0) { + Py_DECREF(capi_object); + return -1; + } + + return 0; +} + +static int +pyexpat_traverse(PyObject *module, visitproc visit, void *arg) +{ + pyexpat_state *state = pyexpat_get_state(module); + Py_VISIT(state->xml_parse_type); + Py_VISIT(state->error); + return 0; +} + +static int +pyexpat_clear(PyObject *module) +{ + pyexpat_state *state = pyexpat_get_state(module); + Py_CLEAR(state->xml_parse_type); + Py_CLEAR(state->error); + return 0; +} + +static void +pyexpat_free(void *module) +{ + pyexpat_clear((PyObject *)module); +} + +static PyModuleDef_Slot pyexpat_slots[] = { + {Py_mod_exec, pyexpat_exec}, + {0, NULL} +}; + +static struct PyModuleDef pyexpatmodule = { + PyModuleDef_HEAD_INIT, + .m_name = MODULE_NAME, + .m_doc = pyexpat_module_documentation, + .m_size = sizeof(pyexpat_state), + .m_methods = pyexpat_methods, + .m_slots = pyexpat_slots, + .m_traverse = pyexpat_traverse, + .m_clear = pyexpat_clear, + .m_free = pyexpat_free +}; + +PyMODINIT_FUNC +PyInit_pyexpat(void) +{ + return PyModuleDef_Init(&pyexpatmodule); } static void diff --git a/contrib/tools/python3/src/Modules/resource.c b/contrib/tools/python3/src/Modules/resource.c index ddbf80be9c..0d69c2983b 100644 --- a/contrib/tools/python3/src/Modules/resource.c +++ b/contrib/tools/python3/src/Modules/resource.c @@ -63,8 +63,20 @@ static PyStructSequence_Desc struct_rusage_desc = { 16 /* n_in_sequence */ }; -static int initialized; -static PyTypeObject StructRUsageType; +typedef struct { + PyTypeObject *StructRUsageType; +} resourcemodulestate; + + +static inline resourcemodulestate* +get_resource_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (resourcemodulestate *)state; +} + +static struct PyModuleDef resourcemodule; /*[clinic input] resource.getrusage @@ -91,7 +103,8 @@ resource_getrusage_impl(PyObject *module, int who) return NULL; } - result = PyStructSequence_New(&StructRUsageType); + result = PyStructSequence_New( + get_resource_state(module)->StructRUsageType); if (!result) return NULL; @@ -313,13 +326,10 @@ resource_getpagesize_impl(PyObject *module) long pagesize = 0; #if defined(HAVE_GETPAGESIZE) pagesize = getpagesize(); -#elif defined(HAVE_SYSCONF) -#if defined(_SC_PAGE_SIZE) +#elif defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE) pagesize = sysconf(_SC_PAGE_SIZE); #else - /* Irix 5.3 has _SC_PAGESIZE, but not _SC_PAGE_SIZE */ - pagesize = sysconf(_SC_PAGESIZE); -#endif +# error "unsupported platform: resource.getpagesize()" #endif return pagesize; } @@ -339,10 +349,10 @@ resource_methods[] = { /* Module initialization */ - static int resource_exec(PyObject *module) { + resourcemodulestate *state = get_resource_state(module); #define ADD_INT(module, value) \ do { \ if (PyModule_AddIntConstant(module, #value, value) < 0) { \ @@ -356,13 +366,12 @@ resource_exec(PyObject *module) Py_DECREF(PyExc_OSError); return -1; } - if (!initialized) { - if (PyStructSequence_InitType2(&StructRUsageType, - &struct_rusage_desc) < 0) - return -1; - } - if(PyModule_AddType(module, &StructRUsageType) < 0) { + state->StructRUsageType = PyStructSequence_NewType(&struct_rusage_desc); + if (state->StructRUsageType == NULL) { + return -1; + } + if (PyModule_AddType(module, state->StructRUsageType) < 0) { return -1; } @@ -471,6 +480,10 @@ resource_exec(PyObject *module) ADD_INT(module, RLIMIT_NPTS); #endif +#ifdef RLIMIT_KQUEUES + ADD_INT(module, RLIMIT_KQUEUES); +#endif + PyObject *v; if (sizeof(RLIM_INFINITY) > sizeof(long)) { v = PyLong_FromLongLong((long long) RLIM_INFINITY); @@ -486,8 +499,6 @@ resource_exec(PyObject *module) Py_DECREF(v); return -1; } - - initialized = 1; return 0; #undef ADD_INT @@ -498,12 +509,32 @@ static struct PyModuleDef_Slot resource_slots[] = { {0, NULL} }; +static int +resourcemodule_traverse(PyObject *m, visitproc visit, void *arg) { + Py_VISIT(get_resource_state(m)->StructRUsageType); + return 0; +} + +static int +resourcemodule_clear(PyObject *m) { + Py_CLEAR(get_resource_state(m)->StructRUsageType); + return 0; +} + +static void +resourcemodule_free(void *m) { + resourcemodule_clear((PyObject *)m); +} + static struct PyModuleDef resourcemodule = { PyModuleDef_HEAD_INIT, .m_name = "resource", - .m_size = 0, + .m_size = sizeof(resourcemodulestate), .m_methods = resource_methods, .m_slots = resource_slots, + .m_traverse = resourcemodule_traverse, + .m_clear = resourcemodule_clear, + .m_free = resourcemodule_free, }; PyMODINIT_FUNC diff --git a/contrib/tools/python3/src/Modules/selectmodule.c b/contrib/tools/python3/src/Modules/selectmodule.c index d4af4f7b52..3afcb0e2a0 100644 --- a/contrib/tools/python3/src/Modules/selectmodule.c +++ b/contrib/tools/python3/src/Modules/selectmodule.c @@ -77,35 +77,16 @@ get_select_state(PyObject *module) return (_selectstate *)state; } -#define _selectstate_global get_select_state(PyState_FindModule(&selectmodule)) +#define _selectstate_by_type(type) get_select_state(PyType_GetModule(type)) /*[clinic input] module select -class select.poll "pollObject *" "&poll_Type" -class select.devpoll "devpollObject *" "&devpoll_Type" -class select.epoll "pyEpoll_Object *" "&pyEpoll_Type" -class select.kqueue "kqueue_queue_Object *" "_selectstate_global->kqueue_queue_Type" +class select.poll "pollObject *" "_selectstate_by_type(type)->poll_Type" +class select.devpoll "devpollObject *" "_selectstate_by_type(type)->devpoll_Type" +class select.epoll "pyEpoll_Object *" "_selectstate_by_type(type)->pyEpoll_Type" +class select.kqueue "kqueue_queue_Object *" "_selectstate_by_type(type)->kqueue_queue_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=41071028e0ede093]*/ - -static int -fildes_converter(PyObject *o, void *p) -{ - int fd; - int *pointer = (int *)p; - fd = PyObject_AsFileDescriptor(o); - if (fd == -1) - return 0; - *pointer = fd; - return 1; -} - -/*[python input] -class fildes_converter(CConverter): - type = 'int' - converter = 'fildes_converter' -[python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=ca54eb5aa476e20a]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8072de35824aa327]*/ /* list of Python objects and their file descriptor */ typedef struct { @@ -313,9 +294,9 @@ select_select_impl(PyObject *module, PyObject *rlist, PyObject *wlist, wfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1); efd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1); if (rfd2obj == NULL || wfd2obj == NULL || efd2obj == NULL) { - if (rfd2obj) PyMem_DEL(rfd2obj); - if (wfd2obj) PyMem_DEL(wfd2obj); - if (efd2obj) PyMem_DEL(efd2obj); + if (rfd2obj) PyMem_Free(rfd2obj); + if (wfd2obj) PyMem_Free(wfd2obj); + if (efd2obj) PyMem_Free(efd2obj); return PyErr_NoMemory(); } #endif /* SELECT_USES_HEAP */ @@ -400,9 +381,9 @@ select_select_impl(PyObject *module, PyObject *rlist, PyObject *wlist, reap_obj(wfd2obj); reap_obj(efd2obj); #ifdef SELECT_USES_HEAP - PyMem_DEL(rfd2obj); - PyMem_DEL(wfd2obj); - PyMem_DEL(efd2obj); + PyMem_Free(rfd2obj); + PyMem_Free(wfd2obj); + PyMem_Free(efd2obj); #endif /* SELECT_USES_HEAP */ return ret; } @@ -518,11 +499,14 @@ select_poll_modify_impl(pollObject *self, int fd, unsigned short eventmask) key = PyLong_FromLong(fd); if (key == NULL) return NULL; - if (PyDict_GetItemWithError(self->dict, key) == NULL) { - if (!PyErr_Occurred()) { - errno = ENOENT; - PyErr_SetFromErrno(PyExc_OSError); - } + err = PyDict_Contains(self->dict, key); + if (err < 0) { + Py_DECREF(key); + return NULL; + } + if (err == 0) { + errno = ENOENT; + PyErr_SetFromErrno(PyExc_OSError); Py_DECREF(key); return NULL; } @@ -727,10 +711,10 @@ select_poll_poll_impl(pollObject *self, PyObject *timeout_obj) } static pollObject * -newPollObject(void) +newPollObject(PyObject *module) { pollObject *self; - self = PyObject_New(pollObject, _selectstate_global->poll_Type); + self = PyObject_New(pollObject, get_select_state(module)->poll_Type); if (self == NULL) return NULL; /* ufd_uptodate is a Boolean, denoting whether the @@ -746,21 +730,14 @@ newPollObject(void) return self; } -static PyObject * -poll_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) -{ - PyErr_Format(PyExc_TypeError, "Cannot create '%.200s' instances", _PyType_Name(type)); - return NULL; -} - static void poll_dealloc(pollObject *self) { PyObject* type = (PyObject *)Py_TYPE(self); if (self->ufds != NULL) - PyMem_DEL(self->ufds); + PyMem_Free(self->ufds); Py_XDECREF(self->dict); - PyObject_Del(self); + PyObject_Free(self); Py_DECREF(type); } @@ -1093,7 +1070,7 @@ static PyGetSetDef devpoll_getsetlist[] = { }; static devpollObject * -newDevPollObject(void) +newDevPollObject(PyObject *module) { devpollObject *self; int fd_devpoll, limit_result; @@ -1123,10 +1100,10 @@ newDevPollObject(void) return NULL; } - self = PyObject_New(devpollObject, _selectstate_global->devpoll_Type); + self = PyObject_New(devpollObject, get_select_state(module)->devpoll_Type); if (self == NULL) { close(fd_devpoll); - PyMem_DEL(fds); + PyMem_Free(fds); return NULL; } self->fd_devpoll = fd_devpoll; @@ -1137,20 +1114,13 @@ newDevPollObject(void) return self; } -static PyObject * -devpoll_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) -{ - PyErr_Format(PyExc_TypeError, "Cannot create '%.200s' instances", _PyType_Name(type)); - return NULL; -} - static void devpoll_dealloc(devpollObject *self) { PyObject *type = (PyObject *)Py_TYPE(self); (void)devpoll_internal_close(self); - PyMem_DEL(self->fds); - PyObject_Del(self); + PyMem_Free(self->fds); + PyObject_Free(self); Py_DECREF(type); } @@ -1158,7 +1128,6 @@ static PyType_Slot devpoll_Type_slots[] = { {Py_tp_dealloc, devpoll_dealloc}, {Py_tp_getset, devpoll_getsetlist}, {Py_tp_methods, devpoll_methods}, - {Py_tp_new, devpoll_new}, {0, 0}, }; @@ -1166,7 +1135,7 @@ static PyType_Spec devpoll_Type_spec = { "select.devpoll", sizeof(devpollObject), 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, devpoll_Type_slots }; @@ -1186,7 +1155,7 @@ static PyObject * select_poll_impl(PyObject *module) /*[clinic end generated code: output=16a665a4e1d228c5 input=3f877909d5696bbf]*/ { - return (PyObject *)newPollObject(); + return (PyObject *)newPollObject(module); } #ifdef HAVE_SYS_DEVPOLL_H @@ -1204,7 +1173,7 @@ static PyObject * select_devpoll_impl(PyObject *module) /*[clinic end generated code: output=ea9213cc87fd9581 input=53a1af94564f00a3]*/ { - return (PyObject *)newDevPollObject(); + return (PyObject *)newDevPollObject(module); } #endif @@ -1258,8 +1227,6 @@ typedef struct { SOCKET epfd; /* epoll control file descriptor */ } pyEpoll_Object; -#define pyepoll_CHECK(op) (PyObject_TypeCheck((op), _selectstate_global->pyEpoll_Type)) - static PyObject * pyepoll_err_closed(void) { @@ -1687,7 +1654,8 @@ select_epoll___exit___impl(pyEpoll_Object *self, PyObject *exc_type, PyObject *exc_value, PyObject *exc_tb) /*[clinic end generated code: output=c480f38ce361748e input=7ae81a5a4c1a98d8]*/ { - return PyObject_CallMethodObjArgs((PyObject *)self, _selectstate_global->close, NULL); + _selectstate *state = _selectstate_by_type(Py_TYPE(self)); + return PyObject_CallMethodObjArgs((PyObject *)self, state->close, NULL); } static PyGetSetDef pyepoll_getsetlist[] = { @@ -1761,15 +1729,13 @@ typedef struct { struct kevent e; } kqueue_event_Object; -#define kqueue_event_Check(op) (PyObject_TypeCheck((op), _selectstate_global->kqueue_event_Type)) +#define kqueue_event_Check(op, state) (PyObject_TypeCheck((op), state->kqueue_event_Type)) typedef struct { PyObject_HEAD SOCKET kqfd; /* kqueue control fd */ } kqueue_queue_Object; -#define kqueue_queue_Check(op) (PyObject_TypeCheck((op), _selectstate_global->kqueue_queue_Type)) - #if (SIZEOF_UINTPTR_T != SIZEOF_VOID_P) # error uintptr_t does not match void *! #elif (SIZEOF_UINTPTR_T == SIZEOF_LONG_LONG) @@ -1910,8 +1876,9 @@ kqueue_event_richcompare(kqueue_event_Object *s, kqueue_event_Object *o, int op) { int result; + _selectstate *state = _selectstate_by_type(Py_TYPE(s)); - if (!kqueue_event_Check(o)) { + if (!kqueue_event_Check(o, state)) { Py_RETURN_NOTIMPLEMENTED; } @@ -2133,6 +2100,7 @@ select_kqueue_control_impl(kqueue_queue_Object *self, PyObject *changelist, struct timespec timeoutspec; struct timespec *ptimeoutspec; _PyTime_t timeout, deadline = 0; + _selectstate *state = _selectstate_by_type(Py_TYPE(self)); if (self->kqfd < 0) return kqueue_queue_err_closed(); @@ -2185,9 +2153,10 @@ select_kqueue_control_impl(kqueue_queue_Object *self, PyObject *changelist, PyErr_NoMemory(); goto error; } + _selectstate *state = _selectstate_by_type(Py_TYPE(self)); for (i = 0; i < nchanges; ++i) { ei = PySequence_Fast_GET_ITEM(seq, i); - if (!kqueue_event_Check(ei)) { + if (!kqueue_event_Check(ei, state)) { PyErr_SetString(PyExc_TypeError, "changelist must be an iterable of " "select.kevent objects"); @@ -2249,7 +2218,7 @@ select_kqueue_control_impl(kqueue_queue_Object *self, PyObject *changelist, for (i = 0; i < gotevents; i++) { kqueue_event_Object *ch; - ch = PyObject_New(kqueue_event_Object, _selectstate_global->kqueue_event_Type); + ch = PyObject_New(kqueue_event_Object, state->kqueue_event_Type); if (ch == NULL) { goto error; } @@ -2295,16 +2264,14 @@ static PyMethodDef poll_methods[] = { static PyType_Slot poll_Type_slots[] = { {Py_tp_dealloc, poll_dealloc}, {Py_tp_methods, poll_methods}, - {Py_tp_new, poll_new}, {0, 0}, }; static PyType_Spec poll_Type_spec = { - "select.poll", - sizeof(pollObject), - 0, - Py_TPFLAGS_DEFAULT, - poll_Type_slots + .name = "select.poll", + .basicsize = sizeof(pollObject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, + .slots = poll_Type_slots, }; #ifdef HAVE_SYS_DEVPOLL_H @@ -2412,24 +2379,28 @@ On Windows, only sockets are supported; on Unix, all file descriptors."); static int _select_traverse(PyObject *module, visitproc visit, void *arg) { - Py_VISIT(get_select_state(module)->close); - Py_VISIT(get_select_state(module)->poll_Type); - Py_VISIT(get_select_state(module)->devpoll_Type); - Py_VISIT(get_select_state(module)->pyEpoll_Type); - Py_VISIT(get_select_state(module)->kqueue_event_Type); - Py_VISIT(get_select_state(module)->kqueue_queue_Type); + _selectstate *state = get_select_state(module); + + Py_VISIT(state->close); + Py_VISIT(state->poll_Type); + Py_VISIT(state->devpoll_Type); + Py_VISIT(state->pyEpoll_Type); + Py_VISIT(state->kqueue_event_Type); + Py_VISIT(state->kqueue_queue_Type); return 0; } static int _select_clear(PyObject *module) { - Py_CLEAR(get_select_state(module)->close); - Py_CLEAR(get_select_state(module)->poll_Type); - Py_CLEAR(get_select_state(module)->devpoll_Type); - Py_CLEAR(get_select_state(module)->pyEpoll_Type); - Py_CLEAR(get_select_state(module)->kqueue_event_Type); - Py_CLEAR(get_select_state(module)->kqueue_queue_Type); + _selectstate *state = get_select_state(module); + + Py_CLEAR(state->close); + Py_CLEAR(state->poll_Type); + Py_CLEAR(state->devpoll_Type); + Py_CLEAR(state->pyEpoll_Type); + Py_CLEAR(state->kqueue_event_Type); + Py_CLEAR(state->kqueue_queue_Type); return 0; } @@ -2439,30 +2410,18 @@ _select_free(void *module) _select_clear((PyObject *)module); } -static struct PyModuleDef selectmodule = { - PyModuleDef_HEAD_INIT, - "select", - module_doc, - sizeof(_selectstate), - select_methods, - NULL, - _select_traverse, - _select_clear, - _select_free, -}; - -PyMODINIT_FUNC -PyInit_select(void) +int +_select_exec(PyObject *m) { - PyObject *m; - m = PyModule_Create(&selectmodule); - if (m == NULL) - return NULL; + _selectstate *state = get_select_state(m); - get_select_state(m)->close = PyUnicode_InternFromString("close"); - - Py_INCREF(PyExc_OSError); - PyModule_AddObject(m, "error", PyExc_OSError); + state->close = PyUnicode_InternFromString("close"); + if (state->close == NULL) { + return -1; + } + if (PyModule_AddObjectRef(m, "error", PyExc_OSError) < 0) { + return -1; + } #ifdef PIPE_BUF #ifdef HAVE_BROKEN_PIPE_BUF @@ -2482,11 +2441,11 @@ PyInit_select(void) #else { #endif - PyObject *poll_Type = PyType_FromSpec(&poll_Type_spec); - if (poll_Type == NULL) - return NULL; - get_select_state(m)->poll_Type = (PyTypeObject *)poll_Type; - Py_INCREF(poll_Type); + state->poll_Type = (PyTypeObject *)PyType_FromModuleAndSpec( + m, &poll_Type_spec, NULL); + if (state->poll_Type == NULL) { + return -1; + } PyModule_AddIntMacro(m, POLLIN); PyModule_AddIntMacro(m, POLLPRI); @@ -2518,20 +2477,22 @@ PyInit_select(void) #endif /* HAVE_POLL */ #ifdef HAVE_SYS_DEVPOLL_H - PyObject *devpoll_Type = PyType_FromSpec(&devpoll_Type_spec); - if (devpoll_Type == NULL) - return NULL; - get_select_state(m)->devpoll_Type = (PyTypeObject *)devpoll_Type; - Py_INCREF(devpoll_Type); + state->devpoll_Type = (PyTypeObject *)PyType_FromModuleAndSpec( + m, &devpoll_Type_spec, NULL); + if (state->devpoll_Type == NULL) { + return -1; + } #endif #ifdef HAVE_EPOLL - PyObject *pyEpoll_Type = PyType_FromSpec(&pyEpoll_Type_spec); - if (pyEpoll_Type == NULL) - return NULL; - get_select_state(m)->pyEpoll_Type = (PyTypeObject *)pyEpoll_Type; - Py_INCREF(pyEpoll_Type); - PyModule_AddObject(m, "epoll", (PyObject *)get_select_state(m)->pyEpoll_Type); + state->pyEpoll_Type = (PyTypeObject *)PyType_FromModuleAndSpec( + m, &pyEpoll_Type_spec, NULL); + if (state->pyEpoll_Type == NULL) { + return -1; + } + if (PyModule_AddType(m, state->pyEpoll_Type) < 0) { + return -1; + } PyModule_AddIntMacro(m, EPOLLIN); PyModule_AddIntMacro(m, EPOLLOUT); @@ -2573,19 +2534,23 @@ PyInit_select(void) #endif /* HAVE_EPOLL */ #ifdef HAVE_KQUEUE - PyObject *kqueue_event_Type = PyType_FromSpec(&kqueue_event_Type_spec); - if (kqueue_event_Type == NULL) - return NULL; - get_select_state(m)->kqueue_event_Type = (PyTypeObject *)kqueue_event_Type; - Py_INCREF(get_select_state(m)->kqueue_event_Type); - PyModule_AddObject(m, "kevent", kqueue_event_Type); + state->kqueue_event_Type = (PyTypeObject *)PyType_FromModuleAndSpec( + m, &kqueue_event_Type_spec, NULL); + if (state->kqueue_event_Type == NULL) { + return -1; + } + if (PyModule_AddType(m, state->kqueue_event_Type) < 0) { + return -1; + } - PyObject *kqueue_queue_Type = PyType_FromSpec(&kqueue_queue_Type_spec); - if (kqueue_queue_Type == NULL) - return NULL; - get_select_state(m)->kqueue_queue_Type = (PyTypeObject *)kqueue_queue_Type; - Py_INCREF(get_select_state(m)->kqueue_queue_Type); - PyModule_AddObject(m, "kqueue", kqueue_queue_Type); + state->kqueue_queue_Type = (PyTypeObject *)PyType_FromModuleAndSpec( + m, &kqueue_queue_Type_spec, NULL); + if (state->kqueue_queue_Type == NULL) { + return -1; + } + if (PyModule_AddType(m, state->kqueue_queue_Type) < 0) { + return -1; + } /* event filters */ PyModule_AddIntConstant(m, "KQ_FILTER_READ", EVFILT_READ); @@ -2662,5 +2627,28 @@ PyInit_select(void) #endif #endif /* HAVE_KQUEUE */ - return m; + return 0; +} + +static PyModuleDef_Slot _select_slots[] = { + {Py_mod_exec, _select_exec}, + {0, NULL} +}; + +static struct PyModuleDef selectmodule = { + PyModuleDef_HEAD_INIT, + .m_name = "select", + .m_doc = module_doc, + .m_size = sizeof(_selectstate), + .m_methods = select_methods, + .m_slots = _select_slots, + .m_traverse = _select_traverse, + .m_clear = _select_clear, + .m_free = _select_free, +}; + +PyMODINIT_FUNC +PyInit_select(void) +{ + return PyModuleDef_Init(&selectmodule); } diff --git a/contrib/tools/python3/src/Modules/sha1module.c b/contrib/tools/python3/src/Modules/sha1module.c index 44fe8ef7b3..d186aa460a 100644 --- a/contrib/tools/python3/src/Modules/sha1module.c +++ b/contrib/tools/python3/src/Modules/sha1module.c @@ -295,22 +295,42 @@ sha1_done(struct sha1_state *sha1, unsigned char *out) * ------------------------------------------------------------------------ */ -static PyTypeObject SHA1type; +typedef struct { + PyTypeObject* sha1_type; +} SHA1State; +static inline SHA1State* +sha1_get_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (SHA1State *)state; +} static SHA1object * -newSHA1object(void) +newSHA1object(SHA1State *st) { - return (SHA1object *)PyObject_New(SHA1object, &SHA1type); + SHA1object *sha = (SHA1object *)PyObject_GC_New(SHA1object, st->sha1_type); + PyObject_GC_Track(sha); + return sha; } /* Internal methods for a hash object */ +static int +SHA1_traverse(PyObject *ptr, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(ptr)); + return 0; +} static void SHA1_dealloc(PyObject *ptr) { - PyObject_Del(ptr); + PyTypeObject *tp = Py_TYPE(ptr); + PyObject_GC_UnTrack(ptr); + PyObject_GC_Del(ptr); + Py_DECREF(tp); } @@ -319,16 +339,19 @@ SHA1_dealloc(PyObject *ptr) /*[clinic input] SHA1Type.copy + cls: defining_class + Return a copy of the hash object. [clinic start generated code]*/ static PyObject * -SHA1Type_copy_impl(SHA1object *self) -/*[clinic end generated code: output=b4e001264620f02a input=b7eae10df6f89b36]*/ +SHA1Type_copy_impl(SHA1object *self, PyTypeObject *cls) +/*[clinic end generated code: output=b32d4461ce8bc7a7 input=6c22e66fcc34c58e]*/ { - SHA1object *newobj; + SHA1State *st = PyType_GetModuleState(cls); - if ((newobj = newSHA1object()) == NULL) + SHA1object *newobj; + if ((newobj = newSHA1object(st)) == NULL) return NULL; newobj->hash_state = self->hash_state; @@ -422,7 +445,6 @@ sha1_get_digest_size(PyObject *self, void *closure) return PyLong_FromLong(SHA1_DIGESTSIZE); } - static PyGetSetDef SHA1_getseters[] = { {"block_size", (getter)SHA1_get_block_size, NULL, @@ -439,40 +461,21 @@ static PyGetSetDef SHA1_getseters[] = { {NULL} /* Sentinel */ }; -static PyTypeObject SHA1type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_sha1.sha1", /*tp_name*/ - sizeof(SHA1object), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - SHA1_dealloc, /*tp_dealloc*/ - 0, /*tp_vectorcall_offset*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_as_async*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - SHA1_methods, /* tp_methods */ - NULL, /* tp_members */ - SHA1_getseters, /* tp_getset */ +static PyType_Slot sha1_type_slots[] = { + {Py_tp_dealloc, SHA1_dealloc}, + {Py_tp_methods, SHA1_methods}, + {Py_tp_getset, SHA1_getseters}, + {Py_tp_traverse, SHA1_traverse}, + {0,0} }; +static PyType_Spec sha1_type_spec = { + .name = "_sha1.sha1", + .basicsize = sizeof(SHA1object), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC), + .slots = sha1_type_slots +}; /* The single module-level function: new() */ @@ -496,7 +499,8 @@ _sha1_sha1_impl(PyObject *module, PyObject *string, int usedforsecurity) if (string) GET_BUFFER_VIEW_OR_ERROUT(string, &buf); - if ((new = newSHA1object()) == NULL) { + SHA1State *st = sha1_get_state(module); + if ((new = newSHA1object(st)) == NULL) { if (string) PyBuffer_Release(&buf); return NULL; @@ -526,37 +530,72 @@ static struct PyMethodDef SHA1_functions[] = { {NULL, NULL} /* Sentinel */ }; +static int +_sha1_traverse(PyObject *module, visitproc visit, void *arg) +{ + SHA1State *state = sha1_get_state(module); + Py_VISIT(state->sha1_type); + return 0; +} + +static int +_sha1_clear(PyObject *module) +{ + SHA1State *state = sha1_get_state(module); + Py_CLEAR(state->sha1_type); + return 0; +} + +static void +_sha1_free(void *module) +{ + _sha1_clear((PyObject *)module); +} + +static int +_sha1_exec(PyObject *module) +{ + SHA1State* st = sha1_get_state(module); + + st->sha1_type = (PyTypeObject *)PyType_FromModuleAndSpec( + module, &sha1_type_spec, NULL); + + if (st->sha1_type == NULL) { + return -1; + } + + Py_INCREF(st->sha1_type); + if (PyModule_AddObject(module, + "SHA1Type", + (PyObject *)st->sha1_type) < 0) { + Py_DECREF(st->sha1_type); + return -1; + } + + return 0; +} + /* Initialize this module. */ +static PyModuleDef_Slot _sha1_slots[] = { + {Py_mod_exec, _sha1_exec}, + {0, NULL} +}; + static struct PyModuleDef _sha1module = { PyModuleDef_HEAD_INIT, - "_sha1", - NULL, - -1, - SHA1_functions, - NULL, - NULL, - NULL, - NULL + .m_name = "_sha1", + .m_size = sizeof(SHA1State), + .m_methods = SHA1_functions, + .m_slots = _sha1_slots, + .m_traverse = _sha1_traverse, + .m_clear = _sha1_clear, + .m_free = _sha1_free }; PyMODINIT_FUNC PyInit__sha1(void) { - PyObject *m; - - Py_SET_TYPE(&SHA1type, &PyType_Type); - if (PyType_Ready(&SHA1type) < 0) { - return NULL; - } - - m = PyModule_Create(&_sha1module); - if (m == NULL) { - return NULL; - } - - Py_INCREF((PyObject *)&SHA1type); - PyModule_AddObject(m, "SHA1Type", (PyObject *)&SHA1type); - return m; + return PyModuleDef_Init(&_sha1module); } diff --git a/contrib/tools/python3/src/Modules/sha256module.c b/contrib/tools/python3/src/Modules/sha256module.c index 9b885c7255..fac7073d95 100644 --- a/contrib/tools/python3/src/Modules/sha256module.c +++ b/contrib/tools/python3/src/Modules/sha256module.c @@ -17,7 +17,7 @@ /* SHA objects */ #include "Python.h" -#include "pycore_byteswap.h" // _Py_bswap32() +#include "pycore_bitutils.h" // _Py_bswap32() #include "structmember.h" // PyMemberDef #include "hashlib.h" #include "pystrhex.h" @@ -51,6 +51,19 @@ typedef struct { #include "clinic/sha256module.c.h" +typedef struct { + PyTypeObject* sha224_type; + PyTypeObject* sha256_type; +} _sha256_state; + +static inline _sha256_state* +_sha256_get_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (_sha256_state *)state; +} + /* When run on a little-endian CPU we need to perform byte reversal on an array of longwords. */ @@ -365,28 +378,40 @@ sha_final(unsigned char digest[SHA_DIGESTSIZE], SHAobject *sha_info) * ------------------------------------------------------------------------ */ -static PyTypeObject SHA224type; -static PyTypeObject SHA256type; - static SHAobject * -newSHA224object(void) +newSHA224object(_sha256_state *state) { - return (SHAobject *)PyObject_New(SHAobject, &SHA224type); + SHAobject *sha = (SHAobject *)PyObject_GC_New(SHAobject, + state->sha224_type); + PyObject_GC_Track(sha); + return sha; } static SHAobject * -newSHA256object(void) +newSHA256object(_sha256_state *state) { - return (SHAobject *)PyObject_New(SHAobject, &SHA256type); + SHAobject *sha = (SHAobject *)PyObject_GC_New(SHAobject, + state->sha256_type); + PyObject_GC_Track(sha); + return sha; } /* Internal methods for a hash object */ +static int +SHA_traverse(PyObject *ptr, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(ptr)); + return 0; +} static void SHA_dealloc(PyObject *ptr) { - PyObject_Del(ptr); + PyTypeObject *tp = Py_TYPE(ptr); + PyObject_GC_UnTrack(ptr); + PyObject_GC_Del(ptr); + Py_DECREF(tp); } @@ -395,21 +420,25 @@ SHA_dealloc(PyObject *ptr) /*[clinic input] SHA256Type.copy + cls:defining_class + Return a copy of the hash object. [clinic start generated code]*/ static PyObject * -SHA256Type_copy_impl(SHAobject *self) -/*[clinic end generated code: output=1a8bbd66a0c9c168 input=f58840a618d4f2a7]*/ +SHA256Type_copy_impl(SHAobject *self, PyTypeObject *cls) +/*[clinic end generated code: output=9273f92c382be12f input=3137146fcb88e212]*/ { SHAobject *newobj; - - if (Py_IS_TYPE(self, &SHA256type)) { - if ( (newobj = newSHA256object())==NULL) + _sha256_state *state = PyType_GetModuleState(cls); + if (Py_IS_TYPE(self, state->sha256_type)) { + if ( (newobj = newSHA256object(state)) == NULL) { return NULL; + } } else { - if ( (newobj = newSHA224object())==NULL) + if ( (newobj = newSHA224object(state))==NULL) { return NULL; + } } SHAcopy(self, newobj); @@ -517,74 +546,30 @@ static PyMemberDef SHA_members[] = { {NULL} /* Sentinel */ }; -static PyTypeObject SHA224type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_sha256.sha224", /*tp_name*/ - sizeof(SHAobject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - SHA_dealloc, /*tp_dealloc*/ - 0, /*tp_vectorcall_offset*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_as_async*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - SHA_methods, /* tp_methods */ - SHA_members, /* tp_members */ - SHA_getseters, /* tp_getset */ +static PyType_Slot sha256_types_slots[] = { + {Py_tp_dealloc, SHA_dealloc}, + {Py_tp_methods, SHA_methods}, + {Py_tp_members, SHA_members}, + {Py_tp_getset, SHA_getseters}, + {Py_tp_traverse, SHA_traverse}, + {0,0} }; -static PyTypeObject SHA256type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_sha256.sha256", /*tp_name*/ - sizeof(SHAobject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - SHA_dealloc, /*tp_dealloc*/ - 0, /*tp_vectorcall_offset*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_as_async*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - SHA_methods, /* tp_methods */ - SHA_members, /* tp_members */ - SHA_getseters, /* tp_getset */ +static PyType_Spec sha224_type_spec = { + .name = "_sha256.sha224", + .basicsize = sizeof(SHAobject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC), + .slots = sha256_types_slots }; +static PyType_Spec sha256_type_spec = { + .name = "_sha256.sha256", + .basicsize = sizeof(SHAobject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC), + .slots = sha256_types_slots +}; /* The single module-level function: new() */ @@ -602,15 +587,19 @@ static PyObject * _sha256_sha256_impl(PyObject *module, PyObject *string, int usedforsecurity) /*[clinic end generated code: output=a1de327e8e1185cf input=9be86301aeb14ea5]*/ { - SHAobject *new; Py_buffer buf; - if (string) + if (string) { GET_BUFFER_VIEW_OR_ERROUT(string, &buf); + } - if ((new = newSHA256object()) == NULL) { - if (string) + _sha256_state *state = PyModule_GetState(module); + + SHAobject *new; + if ((new = newSHA256object(state)) == NULL) { + if (string) { PyBuffer_Release(&buf); + } return NULL; } @@ -618,8 +607,9 @@ _sha256_sha256_impl(PyObject *module, PyObject *string, int usedforsecurity) if (PyErr_Occurred()) { Py_DECREF(new); - if (string) + if (string) { PyBuffer_Release(&buf); + } return NULL; } if (string) { @@ -644,15 +634,17 @@ static PyObject * _sha256_sha224_impl(PyObject *module, PyObject *string, int usedforsecurity) /*[clinic end generated code: output=08be6b36569bc69c input=9fcfb46e460860ac]*/ { - SHAobject *new; Py_buffer buf; - - if (string) + if (string) { GET_BUFFER_VIEW_OR_ERROUT(string, &buf); + } - if ((new = newSHA224object()) == NULL) { - if (string) + _sha256_state *state = PyModule_GetState(module); + SHAobject *new; + if ((new = newSHA224object(state)) == NULL) { + if (string) { PyBuffer_Release(&buf); + } return NULL; } @@ -660,8 +652,9 @@ _sha256_sha224_impl(PyObject *module, PyObject *string, int usedforsecurity) if (PyErr_Occurred()) { Py_DECREF(new); - if (string) + if (string) { PyBuffer_Release(&buf); + } return NULL; } if (string) { @@ -681,43 +674,80 @@ static struct PyMethodDef SHA_functions[] = { {NULL, NULL} /* Sentinel */ }; +static int +_sha256_traverse(PyObject *module, visitproc visit, void *arg) +{ + _sha256_state *state = _sha256_get_state(module); + Py_VISIT(state->sha224_type); + Py_VISIT(state->sha256_type); + return 0; +} -/* Initialize this module. */ +static int +_sha256_clear(PyObject *module) +{ + _sha256_state *state = _sha256_get_state(module); + Py_CLEAR(state->sha224_type); + Py_CLEAR(state->sha256_type); + return 0; +} -static struct PyModuleDef _sha256module = { - PyModuleDef_HEAD_INIT, - "_sha256", - NULL, - -1, - SHA_functions, - NULL, - NULL, - NULL, - NULL -}; +static void +_sha256_free(void *module) +{ + _sha256_clear((PyObject *)module); +} -PyMODINIT_FUNC -PyInit__sha256(void) +static int sha256_exec(PyObject *module) { - PyObject *m; + _sha256_state *state = _sha256_get_state(module); - Py_SET_TYPE(&SHA224type, &PyType_Type); - if (PyType_Ready(&SHA224type) < 0) { - return NULL; + state->sha224_type = (PyTypeObject *)PyType_FromModuleAndSpec( + module, &sha224_type_spec, NULL); + + if (state->sha224_type == NULL) { + return -1; } - Py_SET_TYPE(&SHA256type, &PyType_Type); - if (PyType_Ready(&SHA256type) < 0) { - return NULL; + + state->sha256_type = (PyTypeObject *)PyType_FromModuleAndSpec( + module, &sha256_type_spec, NULL); + + if (state->sha256_type == NULL) { + return -1; } - m = PyModule_Create(&_sha256module); - if (m == NULL) - return NULL; + Py_INCREF((PyObject *)state->sha224_type); + if (PyModule_AddObject(module, "SHA224Type", (PyObject *)state->sha224_type) < 0) { + Py_DECREF((PyObject *)state->sha224_type); + return -1; + } + Py_INCREF((PyObject *)state->sha256_type); + if (PyModule_AddObject(module, "SHA256Type", (PyObject *)state->sha256_type) < 0) { + Py_DECREF((PyObject *)state->sha256_type); + return -1; + } + return 0; +} + +static PyModuleDef_Slot _sha256_slots[] = { + {Py_mod_exec, sha256_exec}, + {0, NULL} +}; - Py_INCREF((PyObject *)&SHA224type); - PyModule_AddObject(m, "SHA224Type", (PyObject *)&SHA224type); - Py_INCREF((PyObject *)&SHA256type); - PyModule_AddObject(m, "SHA256Type", (PyObject *)&SHA256type); - return m; +static struct PyModuleDef _sha256module = { + PyModuleDef_HEAD_INIT, + .m_name = "_sha256", + .m_size = sizeof(_sha256_state), + .m_methods = SHA_functions, + .m_slots = _sha256_slots, + .m_traverse = _sha256_traverse, + .m_clear = _sha256_clear, + .m_free = _sha256_free +}; +/* Initialize this module. */ +PyMODINIT_FUNC +PyInit__sha256(void) +{ + return PyModuleDef_Init(&_sha256module); } diff --git a/contrib/tools/python3/src/Modules/sha512module.c b/contrib/tools/python3/src/Modules/sha512module.c index 831160c324..4ea2fc16de 100644 --- a/contrib/tools/python3/src/Modules/sha512module.c +++ b/contrib/tools/python3/src/Modules/sha512module.c @@ -17,7 +17,7 @@ /* SHA objects */ #include "Python.h" -#include "pycore_byteswap.h" // _Py_bswap32() +#include "pycore_bitutils.h" // _Py_bswap64() #include "structmember.h" // PyMemberDef #include "hashlib.h" #include "pystrhex.h" @@ -422,28 +422,50 @@ sha512_final(unsigned char digest[SHA_DIGESTSIZE], SHAobject *sha_info) * ------------------------------------------------------------------------ */ -static PyTypeObject SHA384type; -static PyTypeObject SHA512type; +typedef struct { + PyTypeObject* sha384_type; + PyTypeObject* sha512_type; +} SHA512State; +static inline SHA512State* +sha512_get_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (SHA512State *)state; +} static SHAobject * -newSHA384object(void) +newSHA384object(SHA512State *st) { - return (SHAobject *)PyObject_New(SHAobject, &SHA384type); + SHAobject *sha = (SHAobject *)PyObject_GC_New(SHAobject, st->sha384_type); + PyObject_GC_Track(sha); + return sha; } static SHAobject * -newSHA512object(void) +newSHA512object(SHA512State *st) { - return (SHAobject *)PyObject_New(SHAobject, &SHA512type); + SHAobject *sha = (SHAobject *)PyObject_GC_New(SHAobject, st->sha512_type); + PyObject_GC_Track(sha); + return sha; } /* Internal methods for a hash object */ +static int +SHA_traverse(PyObject *ptr, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(ptr)); + return 0; +} static void SHA512_dealloc(PyObject *ptr) { - PyObject_Del(ptr); + PyTypeObject *tp = Py_TYPE(ptr); + PyObject_GC_UnTrack(ptr); + PyObject_GC_Del(ptr); + Py_DECREF(tp); } @@ -452,21 +474,27 @@ SHA512_dealloc(PyObject *ptr) /*[clinic input] SHA512Type.copy + cls: defining_class + Return a copy of the hash object. [clinic start generated code]*/ static PyObject * -SHA512Type_copy_impl(SHAobject *self) -/*[clinic end generated code: output=adea896ed3164821 input=9f5f31e6c457776a]*/ +SHA512Type_copy_impl(SHAobject *self, PyTypeObject *cls) +/*[clinic end generated code: output=85ea5b47837a08e6 input=f673a18f66527c90]*/ { SHAobject *newobj; + SHA512State *st = PyType_GetModuleState(cls); - if (Py_IS_TYPE((PyObject*)self, &SHA512type)) { - if ( (newobj = newSHA512object())==NULL) + if (Py_IS_TYPE((PyObject*)self, st->sha512_type)) { + if ( (newobj = newSHA512object(st))==NULL) { return NULL; - } else { - if ( (newobj = newSHA384object())==NULL) + } + } + else { + if ( (newobj = newSHA384object(st))==NULL) { return NULL; + } } SHAcopy(self, newobj); @@ -574,74 +602,41 @@ static PyMemberDef SHA_members[] = { {NULL} /* Sentinel */ }; -static PyTypeObject SHA384type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_sha512.sha384", /*tp_name*/ - sizeof(SHAobject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - SHA512_dealloc, /*tp_dealloc*/ - 0, /*tp_vectorcall_offset*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_as_async*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - SHA_methods, /* tp_methods */ - SHA_members, /* tp_members */ - SHA_getseters, /* tp_getset */ +static PyType_Slot sha512_sha384_type_slots[] = { + {Py_tp_dealloc, SHA512_dealloc}, + {Py_tp_methods, SHA_methods}, + {Py_tp_members, SHA_members}, + {Py_tp_getset, SHA_getseters}, + {Py_tp_traverse, SHA_traverse}, + {0,0} +}; + +static PyType_Spec sha512_sha384_type_spec = { + .name = "_sha512.sha384", + .basicsize = sizeof(SHAobject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC), + .slots = sha512_sha384_type_slots }; -static PyTypeObject SHA512type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_sha512.sha512", /*tp_name*/ - sizeof(SHAobject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - SHA512_dealloc, /*tp_dealloc*/ - 0, /*tp_vectorcall_offset*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_as_async*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - SHA_methods, /* tp_methods */ - SHA_members, /* tp_members */ - SHA_getseters, /* tp_getset */ +static PyType_Slot sha512_sha512_type_slots[] = { + {Py_tp_dealloc, SHA512_dealloc}, + {Py_tp_methods, SHA_methods}, + {Py_tp_members, SHA_members}, + {Py_tp_getset, SHA_getseters}, + {Py_tp_traverse, SHA_traverse}, + {0,0} }; +// Using PyType_GetModuleState() on this type is safe since +// it cannot be subclassed: it does not have the Py_TPFLAGS_BASETYPE flag. +static PyType_Spec sha512_sha512_type_spec = { + .name = "_sha512.sha512", + .basicsize = sizeof(SHAobject), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC), + .slots = sha512_sha512_type_slots +}; /* The single module-level function: new() */ @@ -662,10 +657,12 @@ _sha512_sha512_impl(PyObject *module, PyObject *string, int usedforsecurity) SHAobject *new; Py_buffer buf; + SHA512State *st = sha512_get_state(module); + if (string) GET_BUFFER_VIEW_OR_ERROUT(string, &buf); - if ((new = newSHA512object()) == NULL) { + if ((new = newSHA512object(st)) == NULL) { if (string) PyBuffer_Release(&buf); return NULL; @@ -704,10 +701,12 @@ _sha512_sha384_impl(PyObject *module, PyObject *string, int usedforsecurity) SHAobject *new; Py_buffer buf; + SHA512State *st = sha512_get_state(module); + if (string) GET_BUFFER_VIEW_OR_ERROUT(string, &buf); - if ((new = newSHA384object()) == NULL) { + if ((new = newSHA384object(st)) == NULL) { if (string) PyBuffer_Release(&buf); return NULL; @@ -738,43 +737,80 @@ static struct PyMethodDef SHA_functions[] = { {NULL, NULL} /* Sentinel */ }; +static int +_sha512_traverse(PyObject *module, visitproc visit, void *arg) +{ + SHA512State *state = sha512_get_state(module); + Py_VISIT(state->sha384_type); + Py_VISIT(state->sha512_type); + return 0; +} -/* Initialize this module. */ +static int +_sha512_clear(PyObject *module) +{ + SHA512State *state = sha512_get_state(module); + Py_CLEAR(state->sha384_type); + Py_CLEAR(state->sha512_type); + return 0; +} -static struct PyModuleDef _sha512module = { - PyModuleDef_HEAD_INIT, - "_sha512", - NULL, - -1, - SHA_functions, - NULL, - NULL, - NULL, - NULL -}; +static void +_sha512_free(void *module) +{ + _sha512_clear((PyObject *)module); +} -PyMODINIT_FUNC -PyInit__sha512(void) + +/* Initialize this module. */ +static int +_sha512_exec(PyObject *m) { - PyObject *m; + SHA512State* st = sha512_get_state(m); - Py_SET_TYPE(&SHA384type, &PyType_Type); - if (PyType_Ready(&SHA384type) < 0) { - return NULL; + st->sha384_type = (PyTypeObject *)PyType_FromModuleAndSpec( + m, &sha512_sha384_type_spec, NULL); + + st->sha512_type = (PyTypeObject *)PyType_FromModuleAndSpec( + m, &sha512_sha512_type_spec, NULL); + + if (st->sha384_type == NULL || st->sha512_type == NULL) { + return -1; } - Py_SET_TYPE(&SHA512type, &PyType_Type); - if (PyType_Ready(&SHA512type) < 0) { - return NULL; + + Py_INCREF(st->sha384_type); + if (PyModule_AddObject(m, "SHA384Type", (PyObject *)st->sha384_type) < 0) { + Py_DECREF(st->sha384_type); + return -1; } - m = PyModule_Create(&_sha512module); - if (m == NULL) { - return NULL; + Py_INCREF(st->sha512_type); + if (PyModule_AddObject(m, "SHA384Type", (PyObject *)st->sha512_type) < 0) { + Py_DECREF(st->sha512_type); + return -1; } - Py_INCREF((PyObject *)&SHA384type); - PyModule_AddObject(m, "SHA384Type", (PyObject *)&SHA384type); - Py_INCREF((PyObject *)&SHA512type); - PyModule_AddObject(m, "SHA512Type", (PyObject *)&SHA512type); - return m; + return 0; +} + +static PyModuleDef_Slot _sha512_slots[] = { + {Py_mod_exec, _sha512_exec}, + {0, NULL} +}; + +static struct PyModuleDef _sha512module = { + PyModuleDef_HEAD_INIT, + .m_name = "_sha512", + .m_size = sizeof(SHA512State), + .m_methods = SHA_functions, + .m_slots = _sha512_slots, + .m_traverse = _sha512_traverse, + .m_clear = _sha512_clear, + .m_free = _sha512_free +}; + +PyMODINIT_FUNC +PyInit__sha512(void) +{ + return PyModuleDef_Init(&_sha512module); } diff --git a/contrib/tools/python3/src/Modules/signalmodule.c b/contrib/tools/python3/src/Modules/signalmodule.c index e396a4ad8b..c3a5237bce 100644 --- a/contrib/tools/python3/src/Modules/signalmodule.c +++ b/contrib/tools/python3/src/Modules/signalmodule.c @@ -4,37 +4,39 @@ /* XXX Signals should be recorded per thread, now we have thread state. */ #include "Python.h" -#include "pycore_atomic.h" -#include "pycore_call.h" -#include "pycore_ceval.h" -#include "pycore_pyerrors.h" -#include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_atomic.h" // _Py_atomic_int +#include "pycore_call.h" // _PyObject_Call() +#include "pycore_ceval.h" // _PyEval_SignalReceived() +#include "pycore_moduleobject.h" // _PyModule_GetState() +#include "pycore_pyerrors.h" // _PyErr_SetString() +#include "pycore_pylifecycle.h" // NSIG +#include "pycore_pystate.h" // _PyThreadState_GET() #ifndef MS_WINDOWS -#include "posixmodule.h" +# include "posixmodule.h" #endif #ifdef MS_WINDOWS -#include "socketmodule.h" /* needed for SOCKET_T */ +# include "socketmodule.h" /* needed for SOCKET_T */ #endif #ifdef MS_WINDOWS -#include <windows.h> -#ifdef HAVE_PROCESS_H -#include <process.h> -#endif +# include <windows.h> +# ifdef HAVE_PROCESS_H +# include <process.h> +# endif #endif #ifdef HAVE_SIGNAL_H -#include <signal.h> +# include <signal.h> #endif #ifdef HAVE_SYS_SYSCALL_H -#include <sys/syscall.h> +# include <sys/syscall.h> #endif #ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> +# include <sys/stat.h> #endif #ifdef HAVE_SYS_TIME_H -#include <sys/time.h> +# include <sys/time.h> #endif #if defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK) @@ -46,19 +48,7 @@ #endif #ifndef SIG_ERR -#define SIG_ERR ((PyOS_sighandler_t)(-1)) -#endif - -#ifndef NSIG -# if defined(_NSIG) -# define NSIG _NSIG /* For BSD/SysV */ -# elif defined(_SIGMAX) -# define NSIG (_SIGMAX + 1) /* For QNX */ -# elif defined(SIGMAX) -# define NSIG (SIGMAX + 1) /* For djgpp */ -# else -# define NSIG 64 /* Use a reasonable default value */ -# endif +# define SIG_ERR ((PyOS_sighandler_t)(-1)) #endif #include "clinic/signalmodule.c.h" @@ -109,7 +99,10 @@ class sigset_t_converter(CConverter): static volatile struct { _Py_atomic_int tripped; - PyObject *func; + /* func is atomic to ensure that PyErr_SetInterrupt is async-signal-safe + * (even though it would probably be otherwise, anyway). + */ + _Py_atomic_address func; } Handlers[NSIG]; #ifdef MS_WINDOWS @@ -123,7 +116,11 @@ static volatile struct { #else #define INVALID_FD (-1) static volatile struct { +#ifdef __VXWORKS__ + int fd; +#else sig_atomic_t fd; +#endif int warn_on_full_buffer; } wakeup = {.fd = INVALID_FD, .warn_on_full_buffer = 1}; #endif @@ -131,17 +128,64 @@ static volatile struct { /* Speed up sigcheck() when none tripped */ static _Py_atomic_int is_tripped; -static PyObject *DefaultHandler; -static PyObject *IgnoreHandler; -static PyObject *IntHandler; - +typedef struct { + PyObject *default_handler; + PyObject *ignore_handler; #ifdef MS_WINDOWS -static HANDLE sigint_event = NULL; + HANDLE sigint_event; #endif +} signal_state_t; -#ifdef HAVE_GETITIMER -static PyObject *ItimerError; +// State shared by all Python interpreters +static signal_state_t signal_global_state = {0}; + +#if defined(HAVE_GETITIMER) || defined(HAVE_SETITIMER) +# define PYHAVE_ITIMER_ERROR +#endif + +typedef struct { + PyObject *default_handler; // borrowed ref (signal_global_state) + PyObject *ignore_handler; // borrowed ref (signal_global_state) +#ifdef PYHAVE_ITIMER_ERROR + PyObject *itimer_error; +#endif +} _signal_module_state; + + +Py_LOCAL_INLINE(PyObject *) +get_handler(int i) +{ + return (PyObject *)_Py_atomic_load(&Handlers[i].func); +} + +Py_LOCAL_INLINE(void) +set_handler(int i, PyObject* func) +{ + _Py_atomic_store(&Handlers[i].func, (uintptr_t)func); +} + + +static inline _signal_module_state* +get_signal_state(PyObject *module) +{ + void *state = _PyModule_GetState(module); + assert(state != NULL); + return (_signal_module_state *)state; +} + + +static inline int +compare_handler(PyObject *func, PyObject *dfl_ign_handler) +{ + assert(PyLong_CheckExact(dfl_ign_handler)); + if (!PyLong_CheckExact(func)) { + return 0; + } + // Assume that comparison of two PyLong objects will never fail. + return PyObject_RichCompareBool(func, dfl_ign_handler, Py_EQ) == 1; +} +#ifdef HAVE_GETITIMER /* auxiliary functions for setitimer */ static int timeval_from_double(PyObject *obj, struct timeval *tv) @@ -192,19 +236,26 @@ itimer_retval(struct itimerval *iv) } #endif +/*[clinic input] +signal.default_int_handler + signalnum: int + frame: object + / + +The default handler for SIGINT installed by Python. + +It raises KeyboardInterrupt. +[clinic start generated code]*/ + static PyObject * -signal_default_int_handler(PyObject *self, PyObject *args) +signal_default_int_handler_impl(PyObject *module, int signalnum, + PyObject *frame) +/*[clinic end generated code: output=bb11c2eb115ace4e input=efcd4a56a207acfd]*/ { PyErr_SetNone(PyExc_KeyboardInterrupt); return NULL; } -PyDoc_STRVAR(default_int_handler_doc, -"default_int_handler(...)\n\ -\n\ -The default handler for SIGINT installed by Python.\n\ -It raises KeyboardInterrupt."); - static int report_wakeup_write_error(void *data) @@ -243,10 +294,6 @@ report_wakeup_send_error(void* data) static void trip_signal(int sig_num) { - unsigned char byte; - int fd; - Py_ssize_t rc; - _Py_atomic_store_relaxed(&Handlers[sig_num].tripped, 1); /* Set is_tripped after setting .tripped, as it gets @@ -278,6 +325,7 @@ trip_signal(int sig_num) See bpo-30038 for more details. */ + int fd; #ifdef MS_WINDOWS fd = Py_SAFE_DOWNCAST(wakeup.fd, SOCKET_T, int); #else @@ -285,10 +333,10 @@ trip_signal(int sig_num) #endif if (fd != INVALID_FD) { - byte = (unsigned char)sig_num; + unsigned char byte = (unsigned char)sig_num; #ifdef MS_WINDOWS if (wakeup.use_send) { - rc = send(fd, &byte, 1, 0); + Py_ssize_t rc = send(fd, &byte, 1, 0); if (rc < 0) { int last_error = GetLastError(); @@ -308,7 +356,7 @@ trip_signal(int sig_num) { /* _Py_write_noraise() retries write() if write() is interrupted by a signal (fails with EINTR). */ - rc = _Py_write_noraise(fd, &byte, 1); + Py_ssize_t rc = _Py_write_noraise(fd, &byte, 1); if (rc < 0) { if (wakeup.warn_on_full_buffer || @@ -351,8 +399,10 @@ signal_handler(int sig_num) errno = save_errno; #ifdef MS_WINDOWS - if (sig_num == SIGINT) - SetEvent(sigint_event); + if (sig_num == SIGINT) { + signal_state_t *state = &signal_global_state; + SetEvent(state->sigint_event); + } #endif } @@ -451,6 +501,7 @@ static PyObject * signal_signal_impl(PyObject *module, int signalnum, PyObject *handler) /*[clinic end generated code: output=b44cfda43780f3a1 input=deee84af5fa0432c]*/ { + _signal_module_state *modstate = get_signal_state(module); PyObject *old_handler; void (*func)(int); #ifdef MS_WINDOWS @@ -485,21 +536,18 @@ signal_signal_impl(PyObject *module, int signalnum, PyObject *handler) "signal number out of range"); return NULL; } - if (handler == IgnoreHandler) { + if (PyCallable_Check(handler)) { + func = signal_handler; + } else if (compare_handler(handler, modstate->ignore_handler)) { func = SIG_IGN; - } - else if (handler == DefaultHandler) { + } else if (compare_handler(handler, modstate->default_handler)) { func = SIG_DFL; - } - else if (!PyCallable_Check(handler)) { + } else { _PyErr_SetString(tstate, PyExc_TypeError, "signal handler must be signal.SIG_IGN, " "signal.SIG_DFL, or a callable object"); return NULL; } - else { - func = signal_handler; - } /* Check for pending signals before changing signal handler */ if (_PyErr_CheckSignalsTstate(tstate)) { @@ -510,9 +558,8 @@ signal_signal_impl(PyObject *module, int signalnum, PyObject *handler) return NULL; } - old_handler = Handlers[signalnum].func; - Py_INCREF(handler); - Handlers[signalnum].func = handler; + old_handler = get_handler(signalnum); + set_handler(signalnum, Py_NewRef(handler)); if (old_handler != NULL) { return old_handler; @@ -548,10 +595,9 @@ signal_getsignal_impl(PyObject *module, int signalnum) "signal number out of range"); return NULL; } - old_handler = Handlers[signalnum].func; + old_handler = get_handler(signalnum); if (old_handler != NULL) { - Py_INCREF(old_handler); - return old_handler; + return Py_NewRef(old_handler); } else { Py_RETURN_NONE; @@ -660,7 +706,19 @@ signal_siginterrupt_impl(PyObject *module, int signalnum, int flag) "signal number out of range"); return NULL; } - if (siginterrupt(signalnum, flag)<0) { +#ifdef HAVE_SIGACTION + struct sigaction act; + (void) sigaction(signalnum, NULL, &act); + if (flag) { + act.sa_flags &= ~SA_RESTART; + } + else { + act.sa_flags |= SA_RESTART; + } + if (sigaction(signalnum, &act, NULL) < 0) { +#else + if (siginterrupt(signalnum, flag) < 0) { +#endif PyErr_SetFromErrno(PyExc_OSError); return NULL; } @@ -694,7 +752,7 @@ signal_set_wakeup_fd(PyObject *self, PyObject *args, PyObject *kwds) if (sockfd == (SOCKET_T)(-1) && PyErr_Occurred()) return NULL; #else - int fd, old_fd; + int fd; if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|$p:set_wakeup_fd", kwlist, &fd, &warn_on_full_buffer)) @@ -776,7 +834,7 @@ signal_set_wakeup_fd(PyObject *self, PyObject *args, PyObject *kwds) } } - old_fd = wakeup.fd; + int old_fd = wakeup.fd; wakeup.fd = fd; wakeup.warn_on_full_buffer = warn_on_full_buffer; @@ -797,14 +855,14 @@ The fd must be non-blocking."); int PySignal_SetWakeupFd(int fd) { - int old_fd; - if (fd < 0) + if (fd < 0) { fd = -1; + } #ifdef MS_WINDOWS - old_fd = Py_SAFE_DOWNCAST(wakeup.fd, SOCKET_T, int); + int old_fd = Py_SAFE_DOWNCAST(wakeup.fd, SOCKET_T, int); #else - old_fd = wakeup.fd; + int old_fd = wakeup.fd; #endif wakeup.fd = fd; wakeup.warn_on_full_buffer = 1; @@ -813,7 +871,6 @@ PySignal_SetWakeupFd(int fd) #ifdef HAVE_SETITIMER - /*[clinic input] signal.setitimer @@ -835,8 +892,9 @@ signal_setitimer_impl(PyObject *module, int which, PyObject *seconds, PyObject *interval) /*[clinic end generated code: output=65f9dcbddc35527b input=de43daf194e6f66f]*/ { - struct itimerval new, old; + _signal_module_state *modstate = get_signal_state(module); + struct itimerval new; if (timeval_from_double(seconds, &new.it_value) < 0) { return NULL; } @@ -845,19 +903,18 @@ signal_setitimer_impl(PyObject *module, int which, PyObject *seconds, } /* Let OS check "which" value */ + struct itimerval old; if (setitimer(which, &new, &old) != 0) { - PyErr_SetFromErrno(ItimerError); + PyErr_SetFromErrno(modstate->itimer_error); return NULL; } return itimer_retval(&old); } - -#endif +#endif // HAVE_SETITIMER #ifdef HAVE_GETITIMER - /*[clinic input] signal.getitimer @@ -871,17 +928,18 @@ static PyObject * signal_getitimer_impl(PyObject *module, int which) /*[clinic end generated code: output=9e053175d517db40 input=f7d21d38f3490627]*/ { - struct itimerval old; + _signal_module_state *modstate = get_signal_state(module); + struct itimerval old; if (getitimer(which, &old) != 0) { - PyErr_SetFromErrno(ItimerError); + PyErr_SetFromErrno(modstate->itimer_error); return NULL; } return itimer_retval(&old); } +#endif // HAVE_GETITIMER -#endif #ifdef HAVE_SIGSET_T #if defined(PYPTHREAD_SIGMASK) || defined(HAVE_SIGPENDING) @@ -1060,7 +1118,6 @@ signal_valid_signals_impl(PyObject *module) #if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT) -static int initialized; static PyStructSequence_Field struct_siginfo_fields[] = { {"si_signo", "signal number"}, {"si_code", "signal code"}, @@ -1304,7 +1361,7 @@ signal_pidfd_send_signal_impl(PyObject *module, int pidfd, int signalnum, /* List of functions defined in the module -- some of the methoddefs are defined to nothing if the corresponding C function is not available. */ static PyMethodDef signal_methods[] = { - {"default_int_handler", signal_default_int_handler, METH_VARARGS, default_int_handler_doc}, + SIGNAL_DEFAULT_INT_HANDLER_METHODDEF SIGNAL_ALARM_METHODDEF SIGNAL_SETITIMER_METHODDEF SIGNAL_GETITIMER_METHODDEF @@ -1365,311 +1422,345 @@ ITIMER_PROF -- decrements both when the process is executing and\n\ A signal handler function is called with two arguments:\n\ the first is the signal number, the second is the interrupted stack frame."); -static struct PyModuleDef signalmodule = { - PyModuleDef_HEAD_INIT, - "_signal", - module_doc, - -1, - signal_methods, - NULL, - NULL, - NULL, - NULL -}; -PyMODINIT_FUNC -PyInit__signal(void) -{ - PyObject *m, *d; - int i; - /* Create the module and add the functions */ - m = PyModule_Create(&signalmodule); - if (m == NULL) - return NULL; - -#if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT) - if (!initialized) { - if (PyStructSequence_InitType2(&SiginfoType, &struct_siginfo_desc) < 0) - return NULL; - } - Py_INCREF((PyObject*) &SiginfoType); - PyModule_AddObject(m, "struct_siginfo", (PyObject*) &SiginfoType); - initialized = 1; -#endif - - /* Add some symbolic constants to the module */ - d = PyModule_GetDict(m); - - DefaultHandler = PyLong_FromVoidPtr((void *)SIG_DFL); - if (!DefaultHandler || - PyDict_SetItemString(d, "SIG_DFL", DefaultHandler) < 0) { - goto finally; - } - - IgnoreHandler = PyLong_FromVoidPtr((void *)SIG_IGN); - if (!IgnoreHandler || - PyDict_SetItemString(d, "SIG_IGN", IgnoreHandler) < 0) { - goto finally; +static int +signal_add_constants(PyObject *module) +{ +#define ADD_INT_MACRO(macro) \ + if (PyModule_AddIntConstant(module, #macro, macro) < 0) { \ + return -1; \ } - if (PyModule_AddIntMacro(m, NSIG)) - goto finally; + ADD_INT_MACRO(NSIG); + // SIG_xxx pthread_sigmask() constants #ifdef SIG_BLOCK - if (PyModule_AddIntMacro(m, SIG_BLOCK)) - goto finally; + ADD_INT_MACRO(SIG_BLOCK); #endif #ifdef SIG_UNBLOCK - if (PyModule_AddIntMacro(m, SIG_UNBLOCK)) - goto finally; + ADD_INT_MACRO(SIG_UNBLOCK); #endif #ifdef SIG_SETMASK - if (PyModule_AddIntMacro(m, SIG_SETMASK)) - goto finally; + ADD_INT_MACRO(SIG_SETMASK); #endif - IntHandler = PyDict_GetItemString(d, "default_int_handler"); - if (!IntHandler) - goto finally; - Py_INCREF(IntHandler); - - _Py_atomic_store_relaxed(&Handlers[0].tripped, 0); - for (i = 1; i < NSIG; i++) { - void (*t)(int); - t = PyOS_getsig(i); - _Py_atomic_store_relaxed(&Handlers[i].tripped, 0); - if (t == SIG_DFL) - Handlers[i].func = DefaultHandler; - else if (t == SIG_IGN) - Handlers[i].func = IgnoreHandler; - else - Handlers[i].func = Py_None; /* None of our business */ - Py_INCREF(Handlers[i].func); - } - if (Handlers[SIGINT].func == DefaultHandler) { - /* Install default int handler */ - Py_INCREF(IntHandler); - Py_SETREF(Handlers[SIGINT].func, IntHandler); - PyOS_setsig(SIGINT, signal_handler); - } - + // SIGxxx signal number constants #ifdef SIGHUP - if (PyModule_AddIntMacro(m, SIGHUP)) - goto finally; + ADD_INT_MACRO(SIGHUP); #endif #ifdef SIGINT - if (PyModule_AddIntMacro(m, SIGINT)) - goto finally; + ADD_INT_MACRO(SIGINT); #endif #ifdef SIGBREAK - if (PyModule_AddIntMacro(m, SIGBREAK)) - goto finally; + ADD_INT_MACRO(SIGBREAK); #endif #ifdef SIGQUIT - if (PyModule_AddIntMacro(m, SIGQUIT)) - goto finally; + ADD_INT_MACRO(SIGQUIT); #endif #ifdef SIGILL - if (PyModule_AddIntMacro(m, SIGILL)) - goto finally; + ADD_INT_MACRO(SIGILL); #endif #ifdef SIGTRAP - if (PyModule_AddIntMacro(m, SIGTRAP)) - goto finally; + ADD_INT_MACRO(SIGTRAP); #endif #ifdef SIGIOT - if (PyModule_AddIntMacro(m, SIGIOT)) - goto finally; + ADD_INT_MACRO(SIGIOT); #endif #ifdef SIGABRT - if (PyModule_AddIntMacro(m, SIGABRT)) - goto finally; + ADD_INT_MACRO(SIGABRT); #endif #ifdef SIGEMT - if (PyModule_AddIntMacro(m, SIGEMT)) - goto finally; + ADD_INT_MACRO(SIGEMT); #endif #ifdef SIGFPE - if (PyModule_AddIntMacro(m, SIGFPE)) - goto finally; + ADD_INT_MACRO(SIGFPE); #endif #ifdef SIGKILL - if (PyModule_AddIntMacro(m, SIGKILL)) - goto finally; + ADD_INT_MACRO(SIGKILL); #endif #ifdef SIGBUS - if (PyModule_AddIntMacro(m, SIGBUS)) - goto finally; + ADD_INT_MACRO(SIGBUS); #endif #ifdef SIGSEGV - if (PyModule_AddIntMacro(m, SIGSEGV)) - goto finally; + ADD_INT_MACRO(SIGSEGV); #endif #ifdef SIGSYS - if (PyModule_AddIntMacro(m, SIGSYS)) - goto finally; + ADD_INT_MACRO(SIGSYS); #endif #ifdef SIGPIPE - if (PyModule_AddIntMacro(m, SIGPIPE)) - goto finally; + ADD_INT_MACRO(SIGPIPE); #endif #ifdef SIGALRM - if (PyModule_AddIntMacro(m, SIGALRM)) - goto finally; + ADD_INT_MACRO(SIGALRM); #endif #ifdef SIGTERM - if (PyModule_AddIntMacro(m, SIGTERM)) - goto finally; + ADD_INT_MACRO(SIGTERM); #endif #ifdef SIGUSR1 - if (PyModule_AddIntMacro(m, SIGUSR1)) - goto finally; + ADD_INT_MACRO(SIGUSR1); #endif #ifdef SIGUSR2 - if (PyModule_AddIntMacro(m, SIGUSR2)) - goto finally; + ADD_INT_MACRO(SIGUSR2); #endif #ifdef SIGCLD - if (PyModule_AddIntMacro(m, SIGCLD)) - goto finally; + ADD_INT_MACRO(SIGCLD); #endif #ifdef SIGCHLD - if (PyModule_AddIntMacro(m, SIGCHLD)) - goto finally; + ADD_INT_MACRO(SIGCHLD); #endif #ifdef SIGPWR - if (PyModule_AddIntMacro(m, SIGPWR)) - goto finally; + ADD_INT_MACRO(SIGPWR); #endif #ifdef SIGIO - if (PyModule_AddIntMacro(m, SIGIO)) - goto finally; + ADD_INT_MACRO(SIGIO); #endif #ifdef SIGURG - if (PyModule_AddIntMacro(m, SIGURG)) - goto finally; + ADD_INT_MACRO(SIGURG); #endif #ifdef SIGWINCH - if (PyModule_AddIntMacro(m, SIGWINCH)) - goto finally; + ADD_INT_MACRO(SIGWINCH); #endif #ifdef SIGPOLL - if (PyModule_AddIntMacro(m, SIGPOLL)) - goto finally; + ADD_INT_MACRO(SIGPOLL); #endif #ifdef SIGSTOP - if (PyModule_AddIntMacro(m, SIGSTOP)) - goto finally; + ADD_INT_MACRO(SIGSTOP); #endif #ifdef SIGTSTP - if (PyModule_AddIntMacro(m, SIGTSTP)) - goto finally; + ADD_INT_MACRO(SIGTSTP); #endif #ifdef SIGCONT - if (PyModule_AddIntMacro(m, SIGCONT)) - goto finally; + ADD_INT_MACRO(SIGCONT); #endif #ifdef SIGTTIN - if (PyModule_AddIntMacro(m, SIGTTIN)) - goto finally; + ADD_INT_MACRO(SIGTTIN); #endif #ifdef SIGTTOU - if (PyModule_AddIntMacro(m, SIGTTOU)) - goto finally; + ADD_INT_MACRO(SIGTTOU); #endif #ifdef SIGVTALRM - if (PyModule_AddIntMacro(m, SIGVTALRM)) - goto finally; + ADD_INT_MACRO(SIGVTALRM); #endif #ifdef SIGPROF - if (PyModule_AddIntMacro(m, SIGPROF)) - goto finally; + ADD_INT_MACRO(SIGPROF); #endif #ifdef SIGXCPU - if (PyModule_AddIntMacro(m, SIGXCPU)) - goto finally; + ADD_INT_MACRO(SIGXCPU); #endif #ifdef SIGXFSZ - if (PyModule_AddIntMacro(m, SIGXFSZ)) - goto finally; + ADD_INT_MACRO(SIGXFSZ); #endif #ifdef SIGRTMIN - if (PyModule_AddIntMacro(m, SIGRTMIN)) - goto finally; + ADD_INT_MACRO(SIGRTMIN); #endif #ifdef SIGRTMAX - if (PyModule_AddIntMacro(m, SIGRTMAX)) - goto finally; + ADD_INT_MACRO(SIGRTMAX); #endif #ifdef SIGINFO - if (PyModule_AddIntMacro(m, SIGINFO)) - goto finally; + ADD_INT_MACRO(SIGINFO); #endif + // ITIMER_xxx constants #ifdef ITIMER_REAL - if (PyModule_AddIntMacro(m, ITIMER_REAL)) - goto finally; + ADD_INT_MACRO(ITIMER_REAL); #endif #ifdef ITIMER_VIRTUAL - if (PyModule_AddIntMacro(m, ITIMER_VIRTUAL)) - goto finally; + ADD_INT_MACRO(ITIMER_VIRTUAL); #endif #ifdef ITIMER_PROF - if (PyModule_AddIntMacro(m, ITIMER_PROF)) - goto finally; + ADD_INT_MACRO(ITIMER_PROF); #endif -#if defined (HAVE_SETITIMER) || defined (HAVE_GETITIMER) - ItimerError = PyErr_NewException("signal.ItimerError", - PyExc_OSError, NULL); - if (!ItimerError || - PyDict_SetItemString(d, "ItimerError", ItimerError) < 0) { - goto finally; - } + // CTRL_xxx Windows signals +#ifdef CTRL_C_EVENT + ADD_INT_MACRO(CTRL_C_EVENT); +#endif +#ifdef CTRL_BREAK_EVENT + ADD_INT_MACRO(CTRL_BREAK_EVENT); #endif -#ifdef CTRL_C_EVENT - if (PyModule_AddIntMacro(m, CTRL_C_EVENT)) - goto finally; + return 0; + +#undef ADD_INT_MACRO +} + + +static int +signal_get_set_handlers(signal_state_t *state, PyObject *mod_dict) +{ + // Get signal handlers + for (int signum = 1; signum < NSIG; signum++) { + void (*c_handler)(int) = PyOS_getsig(signum); + PyObject *func; + if (c_handler == SIG_DFL) { + func = state->default_handler; + } + else if (c_handler == SIG_IGN) { + func = state->ignore_handler; + } + else { + func = Py_None; // None of our business + } + // If signal_module_exec() is called more than one, we must + // clear the strong reference to the previous function. + PyObject* old_func = get_handler(signum); + set_handler(signum, Py_NewRef(func)); + Py_XDECREF(old_func); + } + + // Install Python SIGINT handler which raises KeyboardInterrupt + PyObject* sigint_func = get_handler(SIGINT); + if (sigint_func == state->default_handler) { + PyObject *int_handler = PyMapping_GetItemString(mod_dict, + "default_int_handler"); + if (!int_handler) { + return -1; + } + + set_handler(SIGINT, int_handler); + Py_DECREF(sigint_func); + PyOS_setsig(SIGINT, signal_handler); + } + return 0; +} + + +static int +signal_module_exec(PyObject *m) +{ + assert(!PyErr_Occurred()); + + signal_state_t *state = &signal_global_state; + _signal_module_state *modstate = get_signal_state(m); + + modstate->default_handler = state->default_handler; // borrowed ref + modstate->ignore_handler = state->ignore_handler; // borrowed ref + +#ifdef PYHAVE_ITIMER_ERROR + modstate->itimer_error = PyErr_NewException("signal.itimer_error", + PyExc_OSError, NULL); + if (modstate->itimer_error == NULL) { + return -1; + } #endif -#ifdef CTRL_BREAK_EVENT - if (PyModule_AddIntMacro(m, CTRL_BREAK_EVENT)) - goto finally; + if (signal_add_constants(m) < 0) { + return -1; + } + + /* Add some symbolic constants to the module */ + PyObject *d = PyModule_GetDict(m); + if (PyDict_SetItemString(d, "SIG_DFL", state->default_handler) < 0) { + return -1; + } + if (PyDict_SetItemString(d, "SIG_IGN", state->ignore_handler) < 0) { + return -1; + } +#ifdef PYHAVE_ITIMER_ERROR + if (PyDict_SetItemString(d, "ItimerError", modstate->itimer_error) < 0) { + return -1; + } +#endif +#if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT) + if (PyModule_AddType(m, &SiginfoType) < 0) { + return -1; + } #endif - if (PyErr_Occurred()) { - Py_DECREF(m); - m = NULL; + PyThreadState *tstate = _PyThreadState_GET(); + if (_Py_IsMainInterpreter(tstate->interp)) { + if (signal_get_set_handlers(state, d) < 0) { + return -1; + } } - finally: - return m; + assert(!PyErr_Occurred()); + return 0; +} + + +#ifdef PYHAVE_ITIMER_ERROR +static int +_signal_module_traverse(PyObject *module, visitproc visit, void *arg) +{ + _signal_module_state *modstate = get_signal_state(module); + Py_VISIT(modstate->itimer_error); + return 0; +} + +static int +_signal_module_clear(PyObject *module) +{ + _signal_module_state *modstate = get_signal_state(module); + Py_CLEAR(modstate->itimer_error); + return 0; } static void -finisignal(void) +_signal_module_free(void *module) { - int i; - PyObject *func; + _signal_module_clear((PyObject *)module); +} +#endif // PYHAVE_ITIMER_ERROR - for (i = 1; i < NSIG; i++) { - func = Handlers[i].func; - _Py_atomic_store_relaxed(&Handlers[i].tripped, 0); - Handlers[i].func = NULL; - if (func != NULL && func != Py_None && - func != DefaultHandler && func != IgnoreHandler) - PyOS_setsig(i, SIG_DFL); + +static PyModuleDef_Slot signal_slots[] = { + {Py_mod_exec, signal_module_exec}, + {0, NULL} +}; + +static struct PyModuleDef signal_module = { + PyModuleDef_HEAD_INIT, + "_signal", + .m_doc = module_doc, + .m_size = sizeof(_signal_module_state), + .m_methods = signal_methods, + .m_slots = signal_slots, +#ifdef PYHAVE_ITIMER_ERROR + .m_traverse = _signal_module_traverse, + .m_clear = _signal_module_clear, + .m_free = _signal_module_free, +#endif +}; + + +PyMODINIT_FUNC +PyInit__signal(void) +{ + return PyModuleDef_Init(&signal_module); +} + + +void +_PySignal_Fini(void) +{ + signal_state_t *state = &signal_global_state; + + // Restore default signals and clear handlers + for (int signum = 1; signum < NSIG; signum++) { + PyObject *func = get_handler(signum); + _Py_atomic_store_relaxed(&Handlers[signum].tripped, 0); + set_handler(signum, NULL); + if (func != NULL + && func != Py_None + && !compare_handler(func, state->default_handler) + && !compare_handler(func, state->ignore_handler)) + { + PyOS_setsig(signum, SIG_DFL); + } Py_XDECREF(func); } - Py_CLEAR(IntHandler); - Py_CLEAR(DefaultHandler); - Py_CLEAR(IgnoreHandler); -#ifdef HAVE_GETITIMER - Py_CLEAR(ItimerError); +#ifdef MS_WINDOWS + if (state->sigint_event != NULL) { + CloseHandle(state->sigint_event); + state->sigint_event = NULL; + } #endif + + Py_CLEAR(state->default_handler); + Py_CLEAR(state->ignore_handler); } @@ -1715,6 +1806,7 @@ _PyErr_CheckSignalsTstate(PyThreadState *tstate) frame = Py_None; } + signal_state_t *state = &signal_global_state; for (int i = 1; i < NSIG; i++) { if (!_Py_atomic_load_relaxed(&Handlers[i].tripped)) { continue; @@ -1727,9 +1819,10 @@ _PyErr_CheckSignalsTstate(PyThreadState *tstate) * signal handler for it by the time PyErr_CheckSignals() is called * (see bpo-43406). */ - PyObject *func = Handlers[i].func; - if (func == NULL || func == Py_None || func == IgnoreHandler || - func == DefaultHandler) { + PyObject *func = get_handler(i); + if (func == NULL || func == Py_None || + compare_handler(func, state->ignore_handler) || + compare_handler(func, state->default_handler)) { /* No Python signal handler due to aforementioned race condition. * We can't call raise() as it would break the assumption * that PyErr_SetInterrupt() only *simulates* an incoming @@ -1776,30 +1869,32 @@ _PyErr_CheckSignals(void) } -/* Simulate the effect of a signal.SIGINT signal arriving. The next time - PyErr_CheckSignals is called, the Python SIGINT signal handler will be - raised. +/* Simulate the effect of a signal arriving. The next time PyErr_CheckSignals + is called, the corresponding Python signal handler will be raised. - Missing signal handler for the SIGINT signal is silently ignored. */ -void -PyErr_SetInterrupt(void) + Missing signal handler for the given signal number is silently ignored. */ +int +PyErr_SetInterruptEx(int signum) { - if ((Handlers[SIGINT].func != IgnoreHandler) && - (Handlers[SIGINT].func != DefaultHandler)) { - trip_signal(SIGINT); + if (signum < 1 || signum >= NSIG) { + return -1; } + + signal_state_t *state = &signal_global_state; + PyObject *func = get_handler(signum); + if (!compare_handler(func, state->ignore_handler) + && !compare_handler(func, state->default_handler)) { + trip_signal(signum); + } + return 0; } void -PyOS_InitInterrupts(void) +PyErr_SetInterrupt(void) { - PyObject *m = PyImport_ImportModule("_signal"); - if (m) { - Py_DECREF(m); - } + (void) PyErr_SetInterruptEx(SIGINT); } - static int signal_install_handlers(void) { @@ -1824,18 +1919,65 @@ signal_install_handlers(void) } +/* Restore signals that the interpreter has called SIG_IGN on to SIG_DFL. + * + * All of the code in this function must only use async-signal-safe functions, + * listed at `man 7 signal` or + * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html. + * + * If this function is updated, update also _posix_spawn() of subprocess.py. + */ +void +_Py_RestoreSignals(void) +{ +#ifdef SIGPIPE + PyOS_setsig(SIGPIPE, SIG_DFL); +#endif +#ifdef SIGXFZ + PyOS_setsig(SIGXFZ, SIG_DFL); +#endif +#ifdef SIGXFSZ + PyOS_setsig(SIGXFSZ, SIG_DFL); +#endif +} + + int _PySignal_Init(int install_signal_handlers) { + signal_state_t *state = &signal_global_state; + + state->default_handler = PyLong_FromVoidPtr((void *)SIG_DFL); + if (state->default_handler == NULL) { + return -1; + } + + state->ignore_handler = PyLong_FromVoidPtr((void *)SIG_IGN); + if (state->ignore_handler == NULL) { + return -1; + } + #ifdef MS_WINDOWS /* Create manual-reset event, initially unset */ - sigint_event = CreateEvent(NULL, TRUE, FALSE, FALSE); - if (sigint_event == NULL) { + state->sigint_event = CreateEvent(NULL, TRUE, FALSE, FALSE); + if (state->sigint_event == NULL) { PyErr_SetFromWindowsErr(0); return -1; } #endif +#if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT) + if (SiginfoType.tp_name == NULL) { + if (PyStructSequence_InitType2(&SiginfoType, &struct_siginfo_desc) < 0) { + return -1; + } + } +#endif + + for (int signum = 1; signum < NSIG; signum++) { + _Py_atomic_store_relaxed(&Handlers[signum].tripped, 0); + } + if (install_signal_handlers) { if (signal_install_handlers() < 0) { return -1; @@ -1846,13 +1988,6 @@ _PySignal_Init(int install_signal_handlers) } -void -PyOS_FiniInterrupts(void) -{ - finisignal(); -} - - // The caller doesn't have to hold the GIL int _PyOS_InterruptOccurred(PyThreadState *tstate) @@ -1880,14 +2015,16 @@ PyOS_InterruptOccurred(void) } +#ifdef HAVE_FORK static void _clear_pending_signals(void) { - int i; - if (!_Py_atomic_load(&is_tripped)) + if (!_Py_atomic_load(&is_tripped)) { return; + } + _Py_atomic_store(&is_tripped, 0); - for (i = 1; i < NSIG; ++i) { + for (int i = 1; i < NSIG; ++i) { _Py_atomic_store_relaxed(&Handlers[i].tripped, 0); } } @@ -1900,6 +2037,8 @@ _PySignal_AfterFork(void) * the interpreter had an opportunity to call the handlers. issue9535. */ _clear_pending_signals(); } +#endif /* HAVE_FORK */ + int _PyOS_IsMainThread(void) @@ -1909,13 +2048,14 @@ _PyOS_IsMainThread(void) } #ifdef MS_WINDOWS +/* Returns a manual-reset event which gets tripped whenever + SIGINT is received. + + Python.h does not include windows.h so we do cannot use HANDLE + as the return type of this function. We use void* instead. */ void *_PyOS_SigintEvent(void) { - /* Returns a manual-reset event which gets tripped whenever - SIGINT is received. - - Python.h does not include windows.h so we do cannot use HANDLE - as the return type of this function. We use void* instead. */ - return sigint_event; + signal_state_t *state = &signal_global_state; + return state->sigint_event; } #endif diff --git a/contrib/tools/python3/src/Modules/socketmodule.c b/contrib/tools/python3/src/Modules/socketmodule.c index 5ac2ee510f..e1b8b13d88 100644 --- a/contrib/tools/python3/src/Modules/socketmodule.c +++ b/contrib/tools/python3/src/Modules/socketmodule.c @@ -45,7 +45,7 @@ Module interface: - socket.if_nameindex() -> list of tuples (if_index, if_name) - socket.if_nametoindex(name) -> corresponding interface index - socket.if_indextoname(index) -> corresponding interface name -- an Internet socket address is a pair (hostname, port) +- an internet socket address is a pair (hostname, port) where hostname can be anything recognized by gethostbyname() (including the dd.dd.dd.dd notation) and port is in host byte order - where a hostname is returned, the dd.dd.dd.dd notation is used @@ -201,43 +201,6 @@ shutdown(how) -- shut down traffic in one or both directions\n\ # define USE_GETHOSTBYNAME_LOCK #endif -/* To use __FreeBSD_version, __OpenBSD__, and __NetBSD_Version__ */ -#ifdef HAVE_SYS_PARAM_H -#include <sys/param.h> -#endif -/* On systems on which getaddrinfo() is believed to not be thread-safe, - (this includes the getaddrinfo emulation) protect access with a lock. - - getaddrinfo is thread-safe on Mac OS X 10.5 and later. Originally it was - a mix of code including an unsafe implementation from an old BSD's - libresolv. In 10.5 Apple reimplemented it as a safe IPC call to the - mDNSResponder process. 10.5 is the first be UNIX '03 certified, which - includes the requirement that getaddrinfo be thread-safe. See issue #25924. - - It's thread-safe in OpenBSD starting with 5.4, released Nov 2013: - http://www.openbsd.org/plus54.html - - It's thread-safe in NetBSD starting with 4.0, released Dec 2007: - -http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/net/getaddrinfo.c.diff?r1=1.82&r2=1.83 - */ -#if ((defined(__APPLE__) && \ - MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) || \ - (defined(__FreeBSD__) && __FreeBSD_version+0 < 503000) || \ - (defined(__OpenBSD__) && OpenBSD+0 < 201311) || \ - (defined(__NetBSD__) && __NetBSD_Version__+0 < 400000000) || \ - !defined(HAVE_GETADDRINFO)) -#define USE_GETADDRINFO_LOCK -#endif - -#ifdef USE_GETADDRINFO_LOCK -#define ACQUIRE_GETADDRINFO_LOCK PyThread_acquire_lock(netdb_lock, 1); -#define RELEASE_GETADDRINFO_LOCK PyThread_release_lock(netdb_lock); -#else -#define ACQUIRE_GETADDRINFO_LOCK -#define RELEASE_GETADDRINFO_LOCK -#endif - #if defined(__APPLE__) || defined(__CYGWIN__) || defined(__NetBSD__) # include <sys/ioctl.h> #endif @@ -365,7 +328,7 @@ static FlagRuntimeInfo win_runtime_flags[] = { {14393, "TCP_FASTOPEN"} }; -static void +static int remove_unusable_flags(PyObject *m) { PyObject *dict; @@ -374,7 +337,7 @@ remove_unusable_flags(PyObject *m) dict = PyModule_GetDict(m); if (dict == NULL) { - return; + return -1; } /* set to Windows 10, except BuildNumber. */ @@ -400,19 +363,19 @@ remove_unusable_flags(PyObject *m) break; } else { - if (PyDict_GetItemString( - dict, - win_runtime_flags[i].flag_name) != NULL) - { - if (PyDict_DelItemString( - dict, - win_runtime_flags[i].flag_name)) - { - PyErr_Clear(); - } + PyObject *flag_name = PyUnicode_FromString(win_runtime_flags[i].flag_name); + if (flag_name == NULL) { + return -1; + } + PyObject *v = _PyDict_Pop(dict, flag_name, Py_None); + Py_DECREF(flag_name); + if (v == NULL) { + return -1; } + Py_DECREF(v); } } + return 0; } #endif @@ -555,7 +518,6 @@ remove_unusable_flags(PyObject *m) by this module (but not argument type or memory errors, etc.). */ static PyObject *socket_herror; static PyObject *socket_gaierror; -static PyObject *socket_timeout; /* A forward reference to the socket type object. The sock_type variable contains pointers to various functions, @@ -927,7 +889,7 @@ sock_call_ex(PySocketSockObject *s, if (err) *err = SOCK_TIMEOUT_ERR; else - PyErr_SetString(socket_timeout, "timed out"); + PyErr_SetString(PyExc_TimeoutError, "timed out"); return -1; } @@ -1064,7 +1026,7 @@ new_sockobject(SOCKET_T fd, int family, int type, int proto) /* Lock to allow python interpreter to continue, but only allow one thread to be in gethostbyname or getaddrinfo */ -#if defined(USE_GETHOSTBYNAME_LOCK) || defined(USE_GETADDRINFO_LOCK) +#if defined(USE_GETHOSTBYNAME_LOCK) static PyThread_type_lock netdb_lock; #endif @@ -1089,14 +1051,12 @@ setipaddr(const char *name, struct sockaddr *addr_ret, size_t addr_ret_size, int hints.ai_socktype = SOCK_DGRAM; /*dummy*/ hints.ai_flags = AI_PASSIVE; Py_BEGIN_ALLOW_THREADS - ACQUIRE_GETADDRINFO_LOCK error = getaddrinfo(NULL, "0", &hints, &res); Py_END_ALLOW_THREADS /* We assume that those thread-unsafe getaddrinfo() versions *are* safe regarding their return value, ie. that a subsequent call to getaddrinfo() does not destroy the outcome of the first call. */ - RELEASE_GETADDRINFO_LOCK if (error) { set_gaierror(error); return -1; @@ -1197,7 +1157,6 @@ setipaddr(const char *name, struct sockaddr *addr_ret, size_t addr_ret_size, int memset(&hints, 0, sizeof(hints)); hints.ai_family = af; Py_BEGIN_ALLOW_THREADS - ACQUIRE_GETADDRINFO_LOCK error = getaddrinfo(name, NULL, &hints, &res); #if defined(__digital__) && defined(__unix__) if (error == EAI_NONAME && af == AF_UNSPEC) { @@ -1208,7 +1167,6 @@ setipaddr(const char *name, struct sockaddr *addr_ret, size_t addr_ret_size, int } #endif Py_END_ALLOW_THREADS - RELEASE_GETADDRINFO_LOCK /* see comment in setipaddr() */ if (error) { set_gaierror(error); return -1; @@ -2925,7 +2883,7 @@ sock_settimeout(PySocketSockObject *s, PyObject *arg) /* Blocking mode for a Python socket object means that operations like :meth:`recv` or :meth:`sendall` will block the execution of the current thread until they are complete or aborted with a - `socket.timeout` or `socket.error` errors. When timeout is `None`, + `TimeoutError` or `socket.error` errors. When timeout is `None`, the underlying FD is in a blocking mode. When timeout is a positive number, the FD is in a non-blocking mode, and socket ops are implemented with a `select()` call. @@ -4252,7 +4210,7 @@ sock_sendall(PySocketSockObject *s, PyObject *args) } if (interval <= 0) { - PyErr_SetString(socket_timeout, "timed out"); + PyErr_SetString(PyExc_TimeoutError, "timed out"); goto done; } } @@ -5200,13 +5158,6 @@ sock_initobj(PyObject *self, PyObject *args, PyObject *kwds) else #endif { - - if (PyFloat_Check(fdobj)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float"); - return -1; - } - fd = PyLong_AsSocket_t(fdobj); if (fd == (SOCKET_T)(-1) && PyErr_Occurred()) return -1; @@ -6155,13 +6106,10 @@ socket_ntohs(PyObject *self, PyObject *args) return NULL; } if (x > 0xffff) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "ntohs: Python int too large to convert to C " - "16-bit unsigned integer (The silent truncation " - "is deprecated)", - 1)) { - return NULL; - } + PyErr_SetString(PyExc_OverflowError, + "ntohs: Python int too large to convert to C " + "16-bit unsigned integer"); + return NULL; } return PyLong_FromUnsignedLong(ntohs((unsigned short)x)); } @@ -6169,12 +6117,7 @@ socket_ntohs(PyObject *self, PyObject *args) PyDoc_STRVAR(ntohs_doc, "ntohs(integer) -> integer\n\ \n\ -Convert a 16-bit unsigned integer from network to host byte order.\n\ -Note that in case the received integer does not fit in 16-bit unsigned\n\ -integer, but does fit in a positive C int, it is silently truncated to\n\ -16-bit unsigned integer.\n\ -However, this silent truncation feature is deprecated, and will raise an\n\ -exception in future versions of Python."); +Convert a 16-bit unsigned integer from network to host byte order."); static PyObject * @@ -6226,13 +6169,10 @@ socket_htons(PyObject *self, PyObject *args) return NULL; } if (x > 0xffff) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "htons: Python int too large to convert to C " - "16-bit unsigned integer (The silent truncation " - "is deprecated)", - 1)) { - return NULL; - } + PyErr_SetString(PyExc_OverflowError, + "htons: Python int too large to convert to C " + "16-bit unsigned integer"); + return NULL; } return PyLong_FromUnsignedLong(htons((unsigned short)x)); } @@ -6240,12 +6180,7 @@ socket_htons(PyObject *self, PyObject *args) PyDoc_STRVAR(htons_doc, "htons(integer) -> integer\n\ \n\ -Convert a 16-bit unsigned integer from host to network byte order.\n\ -Note that in case the received integer does not fit in 16-bit unsigned\n\ -integer, but does fit in a positive C int, it is silently truncated to\n\ -16-bit unsigned integer.\n\ -However, this silent truncation feature is deprecated, and will raise an\n\ -exception in future versions of Python."); +Convert a 16-bit unsigned integer from host to network byte order."); static PyObject * @@ -6574,10 +6509,8 @@ socket_getaddrinfo(PyObject *self, PyObject *args, PyObject* kwargs) hints.ai_protocol = protocol; hints.ai_flags = flags; Py_BEGIN_ALLOW_THREADS - ACQUIRE_GETADDRINFO_LOCK error = getaddrinfo(hptr, pptr, &hints, &res0); Py_END_ALLOW_THREADS - RELEASE_GETADDRINFO_LOCK /* see comment in setipaddr() */ if (error) { set_gaierror(error); goto err; @@ -6670,10 +6603,8 @@ socket_getnameinfo(PyObject *self, PyObject *args) hints.ai_socktype = SOCK_DGRAM; /* make numeric port happy */ hints.ai_flags = AI_NUMERICHOST; /* don't do any name resolution */ Py_BEGIN_ALLOW_THREADS - ACQUIRE_GETADDRINFO_LOCK error = getaddrinfo(hostp, pbuf, &hints, &res); Py_END_ALLOW_THREADS - RELEASE_GETADDRINFO_LOCK /* see comment in setipaddr() */ if (error) { set_gaierror(error); goto fail; @@ -7106,16 +7037,36 @@ os_init(void) } #endif +static void +sock_free_api(PySocketModule_APIObject *capi) +{ + Py_DECREF(capi->Sock_Type); + Py_DECREF(capi->error); + Py_DECREF(capi->timeout_error); + PyMem_Free(capi); +} -/* C API table - always add new things to the end for binary - compatibility. */ -static -PySocketModule_APIObject PySocketModuleAPI = +static void +sock_destroy_api(PyObject *capsule) { - &sock_type, - NULL, - NULL -}; + void *capi = PyCapsule_GetPointer(capsule, PySocket_CAPSULE_NAME); + sock_free_api(capi); +} + +static PySocketModule_APIObject * +sock_get_api(void) +{ + PySocketModule_APIObject *capi = PyMem_Malloc(sizeof(PySocketModule_APIObject)); + if (capi == NULL) { + PyErr_NoMemory(); + return NULL; + } + + capi->Sock_Type = (PyTypeObject *)Py_NewRef(&sock_type); + capi->error = Py_NewRef(PyExc_OSError); + capi->timeout_error = Py_NewRef(PyExc_TimeoutError); + return capi; +} /* Initialize the _socket module. @@ -7165,8 +7116,6 @@ PyInit__socket(void) return NULL; Py_INCREF(PyExc_OSError); - PySocketModuleAPI.error = PyExc_OSError; - Py_INCREF(PyExc_OSError); PyModule_AddObject(m, "error", PyExc_OSError); socket_herror = PyErr_NewException("socket.herror", PyExc_OSError, NULL); @@ -7180,13 +7129,8 @@ PyInit__socket(void) return NULL; Py_INCREF(socket_gaierror); PyModule_AddObject(m, "gaierror", socket_gaierror); - socket_timeout = PyErr_NewException("socket.timeout", - PyExc_OSError, NULL); - if (socket_timeout == NULL) - return NULL; - PySocketModuleAPI.timeout_error = socket_timeout; - Py_INCREF(socket_timeout); - PyModule_AddObject(m, "timeout", socket_timeout); + PyModule_AddObjectRef(m, "timeout", PyExc_TimeoutError); + Py_INCREF((PyObject *)&sock_type); if (PyModule_AddObject(m, "SocketType", (PyObject *)&sock_type) != 0) @@ -7205,10 +7149,24 @@ PyInit__socket(void) PyModule_AddObject(m, "has_ipv6", has_ipv6); /* Export C API */ - if (PyModule_AddObject(m, PySocket_CAPI_NAME, - PyCapsule_New(&PySocketModuleAPI, PySocket_CAPSULE_NAME, NULL) - ) != 0) + PySocketModule_APIObject *capi = sock_get_api(); + if (capi == NULL) { + Py_DECREF(m); + return NULL; + } + PyObject *capsule = PyCapsule_New(capi, + PySocket_CAPSULE_NAME, + sock_destroy_api); + if (capsule == NULL) { + sock_free_api(capi); + Py_DECREF(m); return NULL; + } + if (PyModule_AddObject(m, PySocket_CAPI_NAME, capsule) < 0) { + Py_DECREF(capsule); + Py_DECREF(m); + return NULL; + } /* Address families (we only support AF_INET and AF_UNIX) */ #ifdef AF_UNSPEC @@ -7974,6 +7932,9 @@ PyInit__socket(void) #ifdef IPPROTO_BIP PyModule_AddIntMacro(m, IPPROTO_BIP); #endif +#ifdef IPPROTO_MPTCP + PyModule_AddIntMacro(m, IPPROTO_MPTCP); +#endif /**/ #ifdef IPPROTO_RAW PyModule_AddIntMacro(m, IPPROTO_RAW); @@ -8068,6 +8029,9 @@ PyInit__socket(void) #ifdef IP_RECVRETOPTS PyModule_AddIntMacro(m, IP_RECVRETOPTS); #endif +#ifdef IP_RECVTOS + PyModule_AddIntMacro(m, IP_RECVTOS); +#endif #ifdef IP_RECVDSTADDR PyModule_AddIntMacro(m, IP_RECVDSTADDR); #endif @@ -8200,6 +8164,10 @@ PyInit__socket(void) #ifdef TCP_KEEPIDLE PyModule_AddIntMacro(m, TCP_KEEPIDLE); #endif + /* TCP_KEEPALIVE is OSX's TCP_KEEPIDLE equivalent */ +#if defined(__APPLE__) && defined(TCP_KEEPALIVE) + PyModule_AddIntMacro(m, TCP_KEEPALIVE); +#endif #ifdef TCP_KEEPINTVL PyModule_AddIntMacro(m, TCP_KEEPINTVL); #endif @@ -8434,13 +8402,16 @@ PyInit__socket(void) #endif /* _MSTCPIP_ */ /* Initialize gethostbyname lock */ -#if defined(USE_GETHOSTBYNAME_LOCK) || defined(USE_GETADDRINFO_LOCK) +#if defined(USE_GETHOSTBYNAME_LOCK) netdb_lock = PyThread_allocate_lock(); #endif #ifdef MS_WINDOWS /* remove some flags on older version Windows during run-time */ - remove_unusable_flags(m); + if (remove_unusable_flags(m) < 0) { + Py_DECREF(m); + return NULL; + } #endif return m; diff --git a/contrib/tools/python3/src/Modules/socketmodule.h b/contrib/tools/python3/src/Modules/socketmodule.h index ba2c9f5c31..e4f375d5e8 100644 --- a/contrib/tools/python3/src/Modules/socketmodule.h +++ b/contrib/tools/python3/src/Modules/socketmodule.h @@ -342,7 +342,8 @@ typedef struct { */ -/* C API for usage by other Python modules */ +/* C API for usage by other Python modules. + * Always add new things to the end for binary compatibility. */ typedef struct { PyTypeObject *Sock_Type; PyObject *error; diff --git a/contrib/tools/python3/src/Modules/spwdmodule.c b/contrib/tools/python3/src/Modules/spwdmodule.c index 1601ec0f2f..acea30679b 100644 --- a/contrib/tools/python3/src/Modules/spwdmodule.c +++ b/contrib/tools/python3/src/Modules/spwdmodule.c @@ -59,9 +59,19 @@ static PyStructSequence_Desc struct_spwd_type_desc = { 9, }; -static int initialized; -static PyTypeObject StructSpwdType; +typedef struct { + PyTypeObject *StructSpwdType; +} spwdmodulestate; +static inline spwdmodulestate* +get_spwd_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (spwdmodulestate *)state; +} + +static struct PyModuleDef spwdmodule; static void sets(PyObject *v, int i, const char* val) @@ -75,10 +85,10 @@ sets(PyObject *v, int i, const char* val) } } -static PyObject *mkspent(struct spwd *p) +static PyObject *mkspent(PyObject *module, struct spwd *p) { int setIndex = 0; - PyObject *v = PyStructSequence_New(&StructSpwdType); + PyObject *v = PyStructSequence_New(get_spwd_state(module)->StructSpwdType); if (v == NULL) return NULL; @@ -144,7 +154,7 @@ spwd_getspnam_impl(PyObject *module, PyObject *arg) PyErr_SetString(PyExc_KeyError, "getspnam(): name not found"); goto out; } - retval = mkspent(p); + retval = mkspent(module, p); out: Py_DECREF(bytes); return retval; @@ -172,7 +182,7 @@ spwd_getspall_impl(PyObject *module) return NULL; setspent(); while ((p = getspent()) != NULL) { - PyObject *v = mkspent(p); + PyObject *v = mkspent(module, p); if (v == NULL || PyList_Append(d, v) != 0) { Py_XDECREF(v); Py_DECREF(d); @@ -197,34 +207,54 @@ static PyMethodDef spwd_methods[] = { {NULL, NULL} /* sentinel */ }; +static int +spwdmodule_exec(PyObject *module) +{ + spwdmodulestate *state = get_spwd_state(module); + + state->StructSpwdType = PyStructSequence_NewType(&struct_spwd_type_desc); + if (state->StructSpwdType == NULL) { + return -1; + } + if (PyModule_AddType(module, state->StructSpwdType) < 0) { + return -1; + } + return 0; +} + +static PyModuleDef_Slot spwdmodule_slots[] = { + {Py_mod_exec, spwdmodule_exec}, + {0, NULL} +}; + +static int spwdmodule_traverse(PyObject *m, visitproc visit, void *arg) { + Py_VISIT(get_spwd_state(m)->StructSpwdType); + return 0; +} +static int spwdmodule_clear(PyObject *m) { + Py_CLEAR(get_spwd_state(m)->StructSpwdType); + return 0; +} + +static void spwdmodule_free(void *m) { + spwdmodule_clear((PyObject *)m); +} static struct PyModuleDef spwdmodule = { PyModuleDef_HEAD_INIT, - "spwd", - spwd__doc__, - -1, - spwd_methods, - NULL, - NULL, - NULL, - NULL + .m_name = "spwd", + .m_doc = spwd__doc__, + .m_size = sizeof(spwdmodulestate), + .m_methods = spwd_methods, + .m_slots = spwdmodule_slots, + .m_traverse = spwdmodule_traverse, + .m_clear = spwdmodule_clear, + .m_free = spwdmodule_free, }; PyMODINIT_FUNC PyInit_spwd(void) { - PyObject *m; - m=PyModule_Create(&spwdmodule); - if (m == NULL) - return NULL; - if (!initialized) { - if (PyStructSequence_InitType2(&StructSpwdType, - &struct_spwd_type_desc) < 0) - return NULL; - } - Py_INCREF((PyObject *) &StructSpwdType); - PyModule_AddObject(m, "struct_spwd", (PyObject *) &StructSpwdType); - initialized = 1; - return m; + return PyModuleDef_Init(&spwdmodule); } diff --git a/contrib/tools/python3/src/Modules/sre_lib.h b/contrib/tools/python3/src/Modules/sre_lib.h index 2657d8d82c..322f66fb4d 100644 --- a/contrib/tools/python3/src/Modules/sre_lib.h +++ b/contrib/tools/python3/src/Modules/sre_lib.h @@ -323,12 +323,12 @@ SRE(count)(SRE_STATE* state, const SRE_CODE* pattern, Py_ssize_t maxcount) if (!i) break; } - TRACE(("|%p|%p|COUNT %" PY_FORMAT_SIZE_T "d\n", pattern, ptr, + TRACE(("|%p|%p|COUNT %zd\n", pattern, ptr, (SRE_CHAR*) state->ptr - ptr)); return (SRE_CHAR*) state->ptr - ptr; } - TRACE(("|%p|%p|COUNT %" PY_FORMAT_SIZE_T "d\n", pattern, ptr, + TRACE(("|%p|%p|COUNT %zd\n", pattern, ptr, ptr - (SRE_CHAR*) state->ptr)); return ptr - (SRE_CHAR*) state->ptr; } @@ -414,8 +414,7 @@ SRE(info)(SRE_STATE* state, const SRE_CODE* pattern) #define DATA_STACK_ALLOC(state, type, ptr) \ do { \ alloc_pos = state->data_stack_base; \ - TRACE(("allocating %s in %" PY_FORMAT_SIZE_T "d " \ - "(%" PY_FORMAT_SIZE_T "d)\n", \ + TRACE(("allocating %s in %zd (%zd)\n", \ Py_STRINGIFY(type), alloc_pos, sizeof(type))); \ if (sizeof(type) > state->data_stack_size - alloc_pos) { \ int j = data_stack_grow(state, sizeof(type)); \ @@ -429,14 +428,13 @@ do { \ #define DATA_STACK_LOOKUP_AT(state, type, ptr, pos) \ do { \ - TRACE(("looking up %s at %" PY_FORMAT_SIZE_T "d\n", Py_STRINGIFY(type), pos)); \ + TRACE(("looking up %s at %zd\n", Py_STRINGIFY(type), pos)); \ ptr = (type*)(state->data_stack+pos); \ } while (0) #define DATA_STACK_PUSH(state, data, size) \ do { \ - TRACE(("copy data in %p to %" PY_FORMAT_SIZE_T "d " \ - "(%" PY_FORMAT_SIZE_T "d)\n", \ + TRACE(("copy data in %p to %zd (%zd)\n", \ data, state->data_stack_base, size)); \ if (size > state->data_stack_size - state->data_stack_base) { \ int j = data_stack_grow(state, size); \ @@ -453,8 +451,7 @@ do { \ safely casted to `void*`, see bpo-39943 for details. */ #define DATA_STACK_POP(state, data, size, discard) \ do { \ - TRACE(("copy data to %p from %" PY_FORMAT_SIZE_T "d " \ - "(%" PY_FORMAT_SIZE_T "d)\n", \ + TRACE(("copy data to %p from %zd (%zd)\n", \ data, state->data_stack_base-size, size)); \ memcpy((void*) data, state->data_stack+state->data_stack_base-size, size); \ if (discard) \ @@ -463,8 +460,7 @@ do { \ #define DATA_STACK_POP_DISCARD(state, size) \ do { \ - TRACE(("discard data from %" PY_FORMAT_SIZE_T "d " \ - "(%" PY_FORMAT_SIZE_T "d)\n", \ + TRACE(("discard data from %zd (%zd)\n", \ state->data_stack_base-size, size)); \ state->data_stack_base -= size; \ } while(0) @@ -577,8 +573,7 @@ entrance: /* optimization info block */ /* <INFO> <1=skip> <2=flags> <3=min> ... */ if (ctx->pattern[3] && (uintptr_t)(end - ctx->ptr) < ctx->pattern[3]) { - TRACE(("reject (got %" PY_FORMAT_SIZE_T "d chars, " - "need %" PY_FORMAT_SIZE_T "d)\n", + TRACE(("reject (got %zd chars, need %zd)\n", end - ctx->ptr, (Py_ssize_t) ctx->pattern[3])); RETURN_FAILURE; } @@ -991,7 +986,7 @@ entrance: ctx->pattern[1], ctx->pattern[2])); /* install new repeat context */ - ctx->u.rep = (SRE_REPEAT*) PyObject_MALLOC(sizeof(*ctx->u.rep)); + ctx->u.rep = (SRE_REPEAT*) PyObject_Malloc(sizeof(*ctx->u.rep)); if (!ctx->u.rep) { PyErr_NoMemory(); RETURN_FAILURE; @@ -1005,7 +1000,7 @@ entrance: state->ptr = ctx->ptr; DO_JUMP(JUMP_REPEAT, jump_repeat, ctx->pattern+ctx->pattern[0]); state->repeat = ctx->u.rep->prev; - PyObject_FREE(ctx->u.rep); + PyObject_Free(ctx->u.rep); if (ret) { RETURN_ON_ERROR(ret); @@ -1028,7 +1023,7 @@ entrance: ctx->count = ctx->u.rep->count+1; - TRACE(("|%p|%p|MAX_UNTIL %" PY_FORMAT_SIZE_T "d\n", ctx->pattern, + TRACE(("|%p|%p|MAX_UNTIL %zd\n", ctx->pattern, ctx->ptr, ctx->count)); if (ctx->count < (Py_ssize_t) ctx->u.rep->pattern[1]) { @@ -1091,7 +1086,7 @@ entrance: ctx->count = ctx->u.rep->count+1; - TRACE(("|%p|%p|MIN_UNTIL %" PY_FORMAT_SIZE_T "d %p\n", ctx->pattern, + TRACE(("|%p|%p|MIN_UNTIL %zd %p\n", ctx->pattern, ctx->ptr, ctx->count, ctx->u.rep->pattern)); if (ctx->count < (Py_ssize_t) ctx->u.rep->pattern[1]) { @@ -1358,7 +1353,7 @@ exit: TRACE(("|%p|%p|JUMP_ASSERT_NOT\n", ctx->pattern, ctx->ptr)); goto jump_assert_not; case JUMP_NONE: - TRACE(("|%p|%p|RETURN %" PY_FORMAT_SIZE_T "d\n", ctx->pattern, + TRACE(("|%p|%p|RETURN %zd\n", ctx->pattern, ctx->ptr, ret)); break; } @@ -1420,7 +1415,7 @@ SRE(search)(SRE_STATE* state, SRE_CODE* pattern) pattern += 1 + pattern[1]; } - TRACE(("prefix = %p %" PY_FORMAT_SIZE_T "d %" PY_FORMAT_SIZE_T "d\n", + TRACE(("prefix = %p %zd %zd\n", prefix, prefix_len, prefix_skip)); TRACE(("charset = %p\n", charset)); diff --git a/contrib/tools/python3/src/Modules/symtablemodule.c b/contrib/tools/python3/src/Modules/symtablemodule.c index 9180f185e1..c25ecc2b5d 100644 --- a/contrib/tools/python3/src/Modules/symtablemodule.c +++ b/contrib/tools/python3/src/Modules/symtablemodule.c @@ -1,8 +1,5 @@ #include "Python.h" - -#include "code.h" -#include "Python-ast.h" -#include "symtable.h" +#include "pycore_symtable.h" // struct symtable #include "clinic/symtablemodule.c.h" /*[clinic input] @@ -61,8 +58,7 @@ _symtable_symtable_impl(PyObject *module, PyObject *source, } t = (PyObject *)st->st_top; Py_INCREF(t); - PyMem_Free((void *)st->st_future); - PySymtable_Free(st); + _PySymtable_Free(st); return t; } @@ -71,56 +67,60 @@ static PyMethodDef symtable_methods[] = { {NULL, NULL} /* sentinel */ }; +static int +symtable_init_stentry_type(PyObject *m) +{ + return PyType_Ready(&PySTEntry_Type); +} + +static int +symtable_init_constants(PyObject *m) +{ + if (PyModule_AddIntMacro(m, USE) < 0) return -1; + if (PyModule_AddIntMacro(m, DEF_GLOBAL) < 0) return -1; + if (PyModule_AddIntMacro(m, DEF_NONLOCAL) < 0) return -1; + if (PyModule_AddIntMacro(m, DEF_LOCAL) < 0) return -1; + if (PyModule_AddIntMacro(m, DEF_PARAM) < 0) return -1; + if (PyModule_AddIntMacro(m, DEF_FREE) < 0) return -1; + if (PyModule_AddIntMacro(m, DEF_FREE_CLASS) < 0) return -1; + if (PyModule_AddIntMacro(m, DEF_IMPORT) < 0) return -1; + if (PyModule_AddIntMacro(m, DEF_BOUND) < 0) return -1; + if (PyModule_AddIntMacro(m, DEF_ANNOT) < 0) return -1; + + if (PyModule_AddIntConstant(m, "TYPE_FUNCTION", FunctionBlock) < 0) + return -1; + if (PyModule_AddIntConstant(m, "TYPE_CLASS", ClassBlock) < 0) return -1; + if (PyModule_AddIntConstant(m, "TYPE_MODULE", ModuleBlock) < 0) + return -1; + + if (PyModule_AddIntMacro(m, LOCAL) < 0) return -1; + if (PyModule_AddIntMacro(m, GLOBAL_EXPLICIT) < 0) return -1; + if (PyModule_AddIntMacro(m, GLOBAL_IMPLICIT) < 0) return -1; + if (PyModule_AddIntMacro(m, FREE) < 0) return -1; + if (PyModule_AddIntMacro(m, CELL) < 0) return -1; + + if (PyModule_AddIntConstant(m, "SCOPE_OFF", SCOPE_OFFSET) < 0) return -1; + if (PyModule_AddIntMacro(m, SCOPE_MASK) < 0) return -1; + + return 0; +} + +static PyModuleDef_Slot symtable_slots[] = { + {Py_mod_exec, symtable_init_stentry_type}, + {Py_mod_exec, symtable_init_constants}, + {0, NULL} +}; + static struct PyModuleDef symtablemodule = { PyModuleDef_HEAD_INIT, - "_symtable", - NULL, - -1, - symtable_methods, - NULL, - NULL, - NULL, - NULL + .m_name = "_symtable", + .m_size = 0, + .m_methods = symtable_methods, + .m_slots = symtable_slots, }; PyMODINIT_FUNC PyInit__symtable(void) { - PyObject *m; - - if (PyType_Ready(&PySTEntry_Type) < 0) - return NULL; - - m = PyModule_Create(&symtablemodule); - if (m == NULL) - return NULL; - PyModule_AddIntMacro(m, USE); - PyModule_AddIntMacro(m, DEF_GLOBAL); - PyModule_AddIntMacro(m, DEF_NONLOCAL); - PyModule_AddIntMacro(m, DEF_LOCAL); - PyModule_AddIntMacro(m, DEF_PARAM); - PyModule_AddIntMacro(m, DEF_FREE); - PyModule_AddIntMacro(m, DEF_FREE_CLASS); - PyModule_AddIntMacro(m, DEF_IMPORT); - PyModule_AddIntMacro(m, DEF_BOUND); - PyModule_AddIntMacro(m, DEF_ANNOT); - - PyModule_AddIntConstant(m, "TYPE_FUNCTION", FunctionBlock); - PyModule_AddIntConstant(m, "TYPE_CLASS", ClassBlock); - PyModule_AddIntConstant(m, "TYPE_MODULE", ModuleBlock); - - PyModule_AddIntMacro(m, LOCAL); - PyModule_AddIntMacro(m, GLOBAL_EXPLICIT); - PyModule_AddIntMacro(m, GLOBAL_IMPLICIT); - PyModule_AddIntMacro(m, FREE); - PyModule_AddIntMacro(m, CELL); - - PyModule_AddIntConstant(m, "SCOPE_OFF", SCOPE_OFFSET); - PyModule_AddIntMacro(m, SCOPE_MASK); - - if (PyErr_Occurred()) { - Py_DECREF(m); - m = 0; - } - return m; + return PyModuleDef_Init(&symtablemodule); } diff --git a/contrib/tools/python3/src/Modules/termios.c b/contrib/tools/python3/src/Modules/termios.c index 75e5e52320..fdfe589eb8 100644 --- a/contrib/tools/python3/src/Modules/termios.c +++ b/contrib/tools/python3/src/Modules/termios.c @@ -1,4 +1,4 @@ -/* termiosmodule.c -- POSIX terminal I/O module implementation. */ +/* termios.c -- POSIX terminal I/O module implementation. */ #include "Python.h" @@ -29,6 +29,13 @@ #include <sys/bsdtty.h> #endif +/*[clinic input] +module termios +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=01105c85d0ca7252]*/ + +#include "clinic/termios.c.h" + PyDoc_STRVAR(termios__doc__, "This module provides an interface to the Posix calls for tty I/O control.\n\ For a complete description of these calls, see the Posix or Unix manual\n\ @@ -51,59 +58,46 @@ get_termios_state(PyObject *module) return (termiosmodulestate *)state; } -#define modulestate_global get_termios_state(PyState_FindModule(&termiosmodule)) +static struct PyModuleDef termiosmodule; -static int fdconv(PyObject* obj, void* p) -{ - int fd; +/*[clinic input] +termios.tcgetattr - fd = PyObject_AsFileDescriptor(obj); - if (fd >= 0) { - *(int*)p = fd; - return 1; - } - return 0; -} + fd: fildes + / -static struct PyModuleDef termiosmodule; +Get the tty attributes for file descriptor fd. -PyDoc_STRVAR(termios_tcgetattr__doc__, -"tcgetattr(fd) -> list_of_attrs\n\ -\n\ -Get the tty attributes for file descriptor fd, as follows:\n\ -[iflag, oflag, cflag, lflag, ispeed, ospeed, cc] where cc is a list\n\ -of the tty special characters (each a string of length 1, except the items\n\ -with indices VMIN and VTIME, which are integers when these fields are\n\ -defined). The interpretation of the flags and the speeds as well as the\n\ -indexing in the cc array must be done using the symbolic constants defined\n\ -in this module."); +Returns a list [iflag, oflag, cflag, lflag, ispeed, ospeed, cc] +where cc is a list of the tty special characters (each a string of +length 1, except the items with indices VMIN and VTIME, which are +integers when these fields are defined). The interpretation of the +flags and the speeds as well as the indexing in the cc array must be +done using the symbolic constants defined in this module. +[clinic start generated code]*/ static PyObject * -termios_tcgetattr(PyObject *self, PyObject *args) +termios_tcgetattr_impl(PyObject *module, int fd) +/*[clinic end generated code: output=2b3da39db870e629 input=54dad9779ebe74b1]*/ { - int fd; + termiosmodulestate *state = PyModule_GetState(module); struct termios mode; - PyObject *cc; - speed_t ispeed, ospeed; - PyObject *v; - int i; - char ch; - - if (!PyArg_ParseTuple(args, "O&:tcgetattr", - fdconv, (void*)&fd)) - return NULL; - - if (tcgetattr(fd, &mode) == -1) - return PyErr_SetFromErrno(modulestate_global->TermiosError); + if (tcgetattr(fd, &mode) == -1) { + return PyErr_SetFromErrno(state->TermiosError); + } - ispeed = cfgetispeed(&mode); - ospeed = cfgetospeed(&mode); + speed_t ispeed = cfgetispeed(&mode); + speed_t ospeed = cfgetospeed(&mode); - cc = PyList_New(NCCS); - if (cc == NULL) + PyObject *cc = PyList_New(NCCS); + if (cc == NULL) { return NULL; + } + + PyObject *v; + int i; for (i = 0; i < NCCS; i++) { - ch = (char)mode.c_cc[i]; + char ch = (char)mode.c_cc[i]; v = PyBytes_FromStringAndSize(&ch, 1); if (v == NULL) goto err; @@ -144,29 +138,28 @@ termios_tcgetattr(PyObject *self, PyObject *args) return NULL; } -PyDoc_STRVAR(termios_tcsetattr__doc__, -"tcsetattr(fd, when, attributes) -> None\n\ -\n\ -Set the tty attributes for file descriptor fd.\n\ -The attributes to be set are taken from the attributes argument, which\n\ -is a list like the one returned by tcgetattr(). The when argument\n\ -determines when the attributes are changed: termios.TCSANOW to\n\ -change immediately, termios.TCSADRAIN to change after transmitting all\n\ -queued output, or termios.TCSAFLUSH to change after transmitting all\n\ -queued output and discarding all queued input. "); +/*[clinic input] +termios.tcsetattr + + fd: fildes + when: int + attributes as term: object + / + +Set the tty attributes for file descriptor fd. + +The attributes to be set are taken from the attributes argument, which +is a list like the one returned by tcgetattr(). The when argument +determines when the attributes are changed: termios.TCSANOW to +change immediately, termios.TCSADRAIN to change after transmitting all +queued output, or termios.TCSAFLUSH to change after transmitting all +queued output and discarding all queued input. +[clinic start generated code]*/ static PyObject * -termios_tcsetattr(PyObject *self, PyObject *args) +termios_tcsetattr_impl(PyObject *module, int fd, int when, PyObject *term) +/*[clinic end generated code: output=bcd2b0a7b98a4bf5 input=5dafabdd5a08f018]*/ { - int fd, when; - struct termios mode; - speed_t ispeed, ospeed; - PyObject *term, *cc, *v; - int i; - - if (!PyArg_ParseTuple(args, "O&iO:tcsetattr", - fdconv, &fd, &when, &term)) - return NULL; if (!PyList_Check(term) || PyList_Size(term) != 7) { PyErr_SetString(PyExc_TypeError, "tcsetattr, arg 3: must be 7 element list"); @@ -174,18 +167,22 @@ termios_tcsetattr(PyObject *self, PyObject *args) } /* Get the old mode, in case there are any hidden fields... */ - termiosmodulestate *state = modulestate_global; - if (tcgetattr(fd, &mode) == -1) + termiosmodulestate *state = PyModule_GetState(module); + struct termios mode; + if (tcgetattr(fd, &mode) == -1) { return PyErr_SetFromErrno(state->TermiosError); + } + mode.c_iflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 0)); mode.c_oflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 1)); mode.c_cflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 2)); mode.c_lflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 3)); - ispeed = (speed_t) PyLong_AsLong(PyList_GetItem(term, 4)); - ospeed = (speed_t) PyLong_AsLong(PyList_GetItem(term, 5)); - cc = PyList_GetItem(term, 6); - if (PyErr_Occurred()) + speed_t ispeed = (speed_t) PyLong_AsLong(PyList_GetItem(term, 4)); + speed_t ospeed = (speed_t) PyLong_AsLong(PyList_GetItem(term, 5)); + PyObject *cc = PyList_GetItem(term, 6); + if (PyErr_Occurred()) { return NULL; + } if (!PyList_Check(cc) || PyList_Size(cc) != NCCS) { PyErr_Format(PyExc_TypeError, @@ -194,6 +191,8 @@ termios_tcsetattr(PyObject *self, PyObject *args) return NULL; } + int i; + PyObject *v; for (i = 0; i < NCCS; i++) { v = PyList_GetItem(cc, i); @@ -218,104 +217,112 @@ termios_tcsetattr(PyObject *self, PyObject *args) Py_RETURN_NONE; } -PyDoc_STRVAR(termios_tcsendbreak__doc__, -"tcsendbreak(fd, duration) -> None\n\ -\n\ -Send a break on file descriptor fd.\n\ -A zero duration sends a break for 0.25-0.5 seconds; a nonzero duration\n\ -has a system dependent meaning."); +/*[clinic input] +termios.tcsendbreak + + fd: fildes + duration: int + / + +Send a break on file descriptor fd. + +A zero duration sends a break for 0.25-0.5 seconds; a nonzero duration +has a system dependent meaning. +[clinic start generated code]*/ static PyObject * -termios_tcsendbreak(PyObject *self, PyObject *args) +termios_tcsendbreak_impl(PyObject *module, int fd, int duration) +/*[clinic end generated code: output=5945f589b5d3ac66 input=dc2f32417691f8ed]*/ { - int fd, duration; - - if (!PyArg_ParseTuple(args, "O&i:tcsendbreak", - fdconv, &fd, &duration)) - return NULL; - if (tcsendbreak(fd, duration) == -1) - return PyErr_SetFromErrno(modulestate_global->TermiosError); + termiosmodulestate *state = PyModule_GetState(module); + if (tcsendbreak(fd, duration) == -1) { + return PyErr_SetFromErrno(state->TermiosError); + } Py_RETURN_NONE; } -PyDoc_STRVAR(termios_tcdrain__doc__, -"tcdrain(fd) -> None\n\ -\n\ -Wait until all output written to file descriptor fd has been transmitted."); +/*[clinic input] +termios.tcdrain + + fd: fildes + / + +Wait until all output written to file descriptor fd has been transmitted. +[clinic start generated code]*/ static PyObject * -termios_tcdrain(PyObject *self, PyObject *args) +termios_tcdrain_impl(PyObject *module, int fd) +/*[clinic end generated code: output=5fd86944c6255955 input=c99241b140b32447]*/ { - int fd; - - if (!PyArg_ParseTuple(args, "O&:tcdrain", - fdconv, &fd)) - return NULL; - if (tcdrain(fd) == -1) - return PyErr_SetFromErrno(modulestate_global->TermiosError); + termiosmodulestate *state = PyModule_GetState(module); + if (tcdrain(fd) == -1) { + return PyErr_SetFromErrno(state->TermiosError); + } Py_RETURN_NONE; } -PyDoc_STRVAR(termios_tcflush__doc__, -"tcflush(fd, queue) -> None\n\ -\n\ -Discard queued data on file descriptor fd.\n\ -The queue selector specifies which queue: termios.TCIFLUSH for the input\n\ -queue, termios.TCOFLUSH for the output queue, or termios.TCIOFLUSH for\n\ -both queues. "); +/*[clinic input] +termios.tcflush + + fd: fildes + queue: int + / + +Discard queued data on file descriptor fd. + +The queue selector specifies which queue: termios.TCIFLUSH for the input +queue, termios.TCOFLUSH for the output queue, or termios.TCIOFLUSH for +both queues. +[clinic start generated code]*/ static PyObject * -termios_tcflush(PyObject *self, PyObject *args) +termios_tcflush_impl(PyObject *module, int fd, int queue) +/*[clinic end generated code: output=2424f80312ec2f21 input=0f7d08122ddc07b5]*/ { - int fd, queue; - - if (!PyArg_ParseTuple(args, "O&i:tcflush", - fdconv, &fd, &queue)) - return NULL; - if (tcflush(fd, queue) == -1) - return PyErr_SetFromErrno(modulestate_global->TermiosError); + termiosmodulestate *state = PyModule_GetState(module); + if (tcflush(fd, queue) == -1) { + return PyErr_SetFromErrno(state->TermiosError); + } Py_RETURN_NONE; } -PyDoc_STRVAR(termios_tcflow__doc__, -"tcflow(fd, action) -> None\n\ -\n\ -Suspend or resume input or output on file descriptor fd.\n\ -The action argument can be termios.TCOOFF to suspend output,\n\ -termios.TCOON to restart output, termios.TCIOFF to suspend input,\n\ -or termios.TCION to restart input."); +/*[clinic input] +termios.tcflow + + fd: fildes + action: int + / + +Suspend or resume input or output on file descriptor fd. + +The action argument can be termios.TCOOFF to suspend output, +termios.TCOON to restart output, termios.TCIOFF to suspend input, +or termios.TCION to restart input. +[clinic start generated code]*/ static PyObject * -termios_tcflow(PyObject *self, PyObject *args) +termios_tcflow_impl(PyObject *module, int fd, int action) +/*[clinic end generated code: output=afd10928e6ea66eb input=c6aff0640b6efd9c]*/ { - int fd, action; - - if (!PyArg_ParseTuple(args, "O&i:tcflow", - fdconv, &fd, &action)) - return NULL; - if (tcflow(fd, action) == -1) - return PyErr_SetFromErrno(modulestate_global->TermiosError); + termiosmodulestate *state = PyModule_GetState(module); + if (tcflow(fd, action) == -1) { + return PyErr_SetFromErrno(state->TermiosError); + } Py_RETURN_NONE; } static PyMethodDef termios_methods[] = { - {"tcgetattr", termios_tcgetattr, - METH_VARARGS, termios_tcgetattr__doc__}, - {"tcsetattr", termios_tcsetattr, - METH_VARARGS, termios_tcsetattr__doc__}, - {"tcsendbreak", termios_tcsendbreak, - METH_VARARGS, termios_tcsendbreak__doc__}, - {"tcdrain", termios_tcdrain, - METH_VARARGS, termios_tcdrain__doc__}, - {"tcflush", termios_tcflush, - METH_VARARGS, termios_tcflush__doc__}, - {"tcflow", termios_tcflow, - METH_VARARGS, termios_tcflow__doc__}, + TERMIOS_TCGETATTR_METHODDEF + TERMIOS_TCSETATTR_METHODDEF + TERMIOS_TCSENDBREAK_METHODDEF + TERMIOS_TCDRAIN_METHODDEF + TERMIOS_TCFLUSH_METHODDEF + TERMIOS_TCFLOW_METHODDEF {NULL, NULL} }; @@ -997,44 +1004,49 @@ static void termiosmodule_free(void *m) { termiosmodule_clear((PyObject *)m); } -static struct PyModuleDef termiosmodule = { - PyModuleDef_HEAD_INIT, - "termios", - termios__doc__, - sizeof(termiosmodulestate), - termios_methods, - NULL, - termiosmodule_traverse, - termiosmodule_clear, - termiosmodule_free, -}; - -PyMODINIT_FUNC -PyInit_termios(void) +static int +termios_exec(PyObject *mod) { - PyObject *m; struct constant *constant = termios_constants; - - if ((m = PyState_FindModule(&termiosmodule)) != NULL) { - Py_INCREF(m); - return m; - } - - if ((m = PyModule_Create(&termiosmodule)) == NULL) { - return NULL; - } - - termiosmodulestate *state = get_termios_state(m); + termiosmodulestate *state = get_termios_state(mod); state->TermiosError = PyErr_NewException("termios.error", NULL, NULL); if (state->TermiosError == NULL) { - return NULL; + return -1; } Py_INCREF(state->TermiosError); - PyModule_AddObject(m, "error", state->TermiosError); + if (PyModule_AddObject(mod, "error", state->TermiosError) < 0) { + Py_DECREF(state->TermiosError); + return -1; + } while (constant->name != NULL) { - PyModule_AddIntConstant(m, constant->name, constant->value); + if (PyModule_AddIntConstant( + mod, constant->name, constant->value) < 0) { + return -1; + } ++constant; } - return m; + return 0; +} + +static PyModuleDef_Slot termios_slots[] = { + {Py_mod_exec, termios_exec}, + {0, NULL} +}; + +static struct PyModuleDef termiosmodule = { + PyModuleDef_HEAD_INIT, + .m_name = "termios", + .m_doc = termios__doc__, + .m_size = sizeof(termiosmodulestate), + .m_methods = termios_methods, + .m_slots = termios_slots, + .m_traverse = termiosmodule_traverse, + .m_clear = termiosmodule_clear, + .m_free = termiosmodule_free, +}; + +PyMODINIT_FUNC PyInit_termios(void) +{ + return PyModuleDef_Init(&termiosmodule); } diff --git a/contrib/tools/python3/src/Modules/timemodule.c b/contrib/tools/python3/src/Modules/timemodule.c index df59f2aac5..4caacc3b64 100644 --- a/contrib/tools/python3/src/Modules/timemodule.c +++ b/contrib/tools/python3/src/Modules/timemodule.c @@ -74,10 +74,21 @@ _PyFloat_FromPyTime(_PyTime_t t) } +static int +get_system_time(_PyTime_t *t) +{ + // Avoid _PyTime_GetSystemClock() which silently ignores errors. + return _PyTime_GetSystemClockWithInfo(t, NULL); +} + + static PyObject * time_time(PyObject *self, PyObject *unused) { - _PyTime_t t = _PyTime_GetSystemClock(); + _PyTime_t t; + if (get_system_time(&t) < 0) { + return NULL; + } return _PyFloat_FromPyTime(t); } @@ -91,7 +102,10 @@ Fractions of a second may be present if the system clock provides them."); static PyObject * time_time_ns(PyObject *self, PyObject *unused) { - _PyTime_t t = _PyTime_GetSystemClock(); + _PyTime_t t; + if (get_system_time(&t) < 0) { + return NULL; + } return _PyTime_AsNanosecondsObject(t); } @@ -147,15 +161,6 @@ _PyTime_GetClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) } #endif /* HAVE_CLOCK */ -static PyObject* -perf_counter(_Py_clock_info_t *info) -{ - _PyTime_t t; - if (_PyTime_GetPerfCounterWithInfo(&t, info) < 0) { - return NULL; - } - return _PyFloat_FromPyTime(t); -} #ifdef HAVE_CLOCK_GETTIME @@ -1096,10 +1101,22 @@ the local timezone used by methods such as localtime, but this behaviour\n\ should not be relied on."); #endif /* HAVE_WORKING_TZSET */ + +static int +get_monotonic(_PyTime_t *t) +{ + // Avoid _PyTime_GetMonotonicClock() which silently ignores errors. + return _PyTime_GetMonotonicClockWithInfo(t, NULL); +} + + static PyObject * time_monotonic(PyObject *self, PyObject *unused) { - _PyTime_t t = _PyTime_GetMonotonicClock(); + _PyTime_t t; + if (get_monotonic(&t) < 0) { + return NULL; + } return _PyFloat_FromPyTime(t); } @@ -1111,7 +1128,10 @@ Monotonic clock, cannot go backward."); static PyObject * time_monotonic_ns(PyObject *self, PyObject *unused) { - _PyTime_t t = _PyTime_GetMonotonicClock(); + _PyTime_t t; + if (get_monotonic(&t) < 0) { + return NULL; + } return _PyTime_AsNanosecondsObject(t); } @@ -1120,10 +1140,23 @@ PyDoc_STRVAR(monotonic_ns_doc, \n\ Monotonic clock, cannot go backward, as nanoseconds."); + +static int +get_perf_counter(_PyTime_t *t) +{ + // Avoid _PyTime_GetPerfCounter() which silently ignores errors. + return _PyTime_GetPerfCounterWithInfo(t, NULL); +} + + static PyObject * time_perf_counter(PyObject *self, PyObject *unused) { - return perf_counter(NULL); + _PyTime_t t; + if (get_perf_counter(&t) < 0) { + return NULL; + } + return _PyFloat_FromPyTime(t); } PyDoc_STRVAR(perf_counter_doc, @@ -1131,10 +1164,14 @@ PyDoc_STRVAR(perf_counter_doc, \n\ Performance counter for benchmarking."); + static PyObject * time_perf_counter_ns(PyObject *self, PyObject *unused) { - _PyTime_t t = _PyTime_GetPerfCounter(); + _PyTime_t t; + if (get_perf_counter(&t) < 0) { + return NULL; + } return _PyTime_AsNanosecondsObject(t); } @@ -2025,7 +2062,10 @@ pysleep(_PyTime_t secs) HANDLE hInterruptEvent; #endif - deadline = _PyTime_GetMonotonicClock() + secs; + if (get_monotonic(&monotonic) < 0) { + return -1; + } + deadline = monotonic + secs; do { #ifndef MS_WINDOWS @@ -2077,10 +2117,13 @@ pysleep(_PyTime_t secs) if (PyErr_CheckSignals()) return -1; - monotonic = _PyTime_GetMonotonicClock(); + if (get_monotonic(&monotonic) < 0) { + return -1; + } secs = deadline - monotonic; - if (secs < 0) + if (secs < 0) { break; + } /* retry with the recomputed delay */ } while (1); diff --git a/contrib/tools/python3/src/Modules/unicodedata.c b/contrib/tools/python3/src/Modules/unicodedata.c index 8a1198a2b7..f87eb60879 100644 --- a/contrib/tools/python3/src/Modules/unicodedata.c +++ b/contrib/tools/python3/src/Modules/unicodedata.c @@ -16,7 +16,7 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" -#include "ucnhash.h" +#include "pycore_ucnhash.h" // _PyUnicode_Name_CAPI #include "structmember.h" // PyMemberDef #include <stdbool.h> @@ -28,9 +28,9 @@ _Py_IDENTIFIER(NFKD); /*[clinic input] module unicodedata -class unicodedata.UCD 'PreviousDBVersion *' '&UCD_Type' +class unicodedata.UCD 'PreviousDBVersion *' '<not used>' [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=6dac153082d150bc]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e47113e05924be43]*/ /* character properties */ @@ -90,22 +90,26 @@ static PyMemberDef DB_members[] = { {NULL} }; -/* forward declaration */ -static PyTypeObject UCD_Type; -#define UCD_Check(o) Py_IS_TYPE(o, &UCD_Type) +// Check if self is an unicodedata.UCD instance. +// If self is NULL (when the PyCapsule C API is used), return 0. +// PyModule_Check() is used to avoid having to retrieve the ucd_type. +// See unicodedata_functions comment to the rationale of this macro. +#define UCD_Check(self) (self != NULL && !PyModule_Check(self)) static PyObject* -new_previous_version(const char*name, const change_record* (*getrecord)(Py_UCS4), +new_previous_version(PyTypeObject *ucd_type, + const char*name, const change_record* (*getrecord)(Py_UCS4), Py_UCS4 (*normalization)(Py_UCS4)) { - PreviousDBVersion *self; - self = PyObject_New(PreviousDBVersion, &UCD_Type); - if (self == NULL) - return NULL; - self->name = name; - self->getrecord = getrecord; - self->normalization = normalization; - return (PyObject*)self; + PreviousDBVersion *self; + self = PyObject_GC_New(PreviousDBVersion, ucd_type); + if (self == NULL) + return NULL; + self->name = name; + self->getrecord = getrecord; + self->normalization = normalization; + PyObject_GC_Track(self); + return (PyObject*)self; } @@ -135,7 +139,7 @@ unicodedata_UCD_decimal_impl(PyObject *self, int chr, long rc; Py_UCS4 c = (Py_UCS4)chr; - if (self && UCD_Check(self)) { + if (UCD_Check(self)) { const change_record *old = get_old_record(self, c); if (old->category_changed == 0) { /* unassigned */ @@ -223,7 +227,7 @@ unicodedata_UCD_numeric_impl(PyObject *self, int chr, double rc; Py_UCS4 c = (Py_UCS4)chr; - if (self && UCD_Check(self)) { + if (UCD_Check(self)) { const change_record *old = get_old_record(self, c); if (old->category_changed == 0) { /* unassigned */ @@ -268,7 +272,7 @@ unicodedata_UCD_category_impl(PyObject *self, int chr) int index; Py_UCS4 c = (Py_UCS4)chr; index = (int) _getrecord_ex(c)->category; - if (self && UCD_Check(self)) { + if (UCD_Check(self)) { const change_record *old = get_old_record(self, c); if (old->category_changed != 0xFF) index = old->category_changed; @@ -295,7 +299,7 @@ unicodedata_UCD_bidirectional_impl(PyObject *self, int chr) int index; Py_UCS4 c = (Py_UCS4)chr; index = (int) _getrecord_ex(c)->bidirectional; - if (self && UCD_Check(self)) { + if (UCD_Check(self)) { const change_record *old = get_old_record(self, c); if (old->category_changed == 0) index = 0; /* unassigned */ @@ -324,7 +328,7 @@ unicodedata_UCD_combining_impl(PyObject *self, int chr) int index; Py_UCS4 c = (Py_UCS4)chr; index = (int) _getrecord_ex(c)->combining; - if (self && UCD_Check(self)) { + if (UCD_Check(self)) { const change_record *old = get_old_record(self, c); if (old->category_changed == 0) index = 0; /* unassigned */ @@ -352,7 +356,7 @@ unicodedata_UCD_mirrored_impl(PyObject *self, int chr) int index; Py_UCS4 c = (Py_UCS4)chr; index = (int) _getrecord_ex(c)->mirrored; - if (self && UCD_Check(self)) { + if (UCD_Check(self)) { const change_record *old = get_old_record(self, c); if (old->category_changed == 0) index = 0; /* unassigned */ @@ -379,7 +383,7 @@ unicodedata_UCD_east_asian_width_impl(PyObject *self, int chr) int index; Py_UCS4 c = (Py_UCS4)chr; index = (int) _getrecord_ex(c)->east_asian_width; - if (self && UCD_Check(self)) { + if (UCD_Check(self)) { const change_record *old = get_old_record(self, c); if (old->category_changed == 0) index = 0; /* unassigned */ @@ -413,7 +417,7 @@ unicodedata_UCD_decomposition_impl(PyObject *self, int chr) code = (int)c; - if (self && UCD_Check(self)) { + if (UCD_Check(self)) { const change_record *old = get_old_record(self, c); if (old->category_changed == 0) return PyUnicode_FromString(""); /* unassigned */ @@ -456,12 +460,14 @@ unicodedata_UCD_decomposition_impl(PyObject *self, int chr) } static void -get_decomp_record(PyObject *self, Py_UCS4 code, int *index, int *prefix, int *count) +get_decomp_record(PyObject *self, Py_UCS4 code, + int *index, int *prefix, int *count) { if (code >= 0x110000) { *index = 0; - } else if (self && UCD_Check(self) && - get_old_record(self, code)->category_changed==0) { + } + else if (UCD_Check(self) + && get_old_record(self, code)->category_changed==0) { /* unassigned in old version */ *index = 0; } @@ -558,7 +564,7 @@ nfd_nfkd(PyObject *self, PyObject *input, int k) continue; } /* normalization changes */ - if (self && UCD_Check(self)) { + if (UCD_Check(self)) { Py_UCS4 value = ((PreviousDBVersion*)self)->normalization(code); if (value != 0) { stack[stackptr++] = value; @@ -794,13 +800,13 @@ typedef enum {YES = 0, MAYBE = 1, NO = 2} QuickcheckResult; * https://www.unicode.org/reports/tr15/#Detecting_Normalization_Forms */ static QuickcheckResult -is_normalized_quickcheck(PyObject *self, PyObject *input, - bool nfc, bool k, bool yes_only) +is_normalized_quickcheck(PyObject *self, PyObject *input, bool nfc, bool k, + bool yes_only) { - /* An older version of the database is requested, quickchecks must be - disabled. */ - if (self && UCD_Check(self)) + /* UCD 3.2.0 is requested, quickchecks must be disabled. */ + if (UCD_Check(self)) { return NO; + } Py_ssize_t i, len; int kind; @@ -940,28 +946,32 @@ unicodedata_UCD_normalize_impl(PyObject *self, PyObject *form, } if (_PyUnicode_EqualToASCIIId(form, &PyId_NFC)) { - if (is_normalized_quickcheck(self, input, true, false, true) == YES) { + if (is_normalized_quickcheck(self, input, + true, false, true) == YES) { Py_INCREF(input); return input; } return nfc_nfkc(self, input, 0); } if (_PyUnicode_EqualToASCIIId(form, &PyId_NFKC)) { - if (is_normalized_quickcheck(self, input, true, true, true) == YES) { + if (is_normalized_quickcheck(self, input, + true, true, true) == YES) { Py_INCREF(input); return input; } return nfc_nfkc(self, input, 1); } if (_PyUnicode_EqualToASCIIId(form, &PyId_NFD)) { - if (is_normalized_quickcheck(self, input, false, false, true) == YES) { + if (is_normalized_quickcheck(self, input, + false, false, true) == YES) { Py_INCREF(input); return input; } return nfd_nfkd(self, input, 0); } if (_PyUnicode_EqualToASCIIId(form, &PyId_NFKD)) { - if (is_normalized_quickcheck(self, input, false, true, true) == YES) { + if (is_normalized_quickcheck(self, input, + false, true, true) == YES) { Py_INCREF(input); return input; } @@ -1048,8 +1058,8 @@ is_unified_ideograph(Py_UCS4 code) (cp < named_sequences_end)) static int -_getucname(PyObject *self, Py_UCS4 code, char* buffer, int buflen, - int with_alias_and_seq) +_getucname(PyObject *self, + Py_UCS4 code, char* buffer, int buflen, int with_alias_and_seq) { /* Find the name associated with the given code point. * If with_alias_and_seq is 1, check for names in the Private Use Area 15 @@ -1066,7 +1076,7 @@ _getucname(PyObject *self, Py_UCS4 code, char* buffer, int buflen, if (!with_alias_and_seq && (IS_ALIAS(code) || IS_NAMED_SEQ(code))) return 0; - if (self && UCD_Check(self)) { + if (UCD_Check(self)) { /* in 3.2.0 there are no aliases and named sequences */ const change_record *old; if (IS_ALIAS(code) || IS_NAMED_SEQ(code)) @@ -1150,6 +1160,15 @@ _getucname(PyObject *self, Py_UCS4 code, char* buffer, int buflen, } static int +capi_getucname(Py_UCS4 code, + char* buffer, int buflen, + int with_alias_and_seq) +{ + return _getucname(NULL, code, buffer, buflen, with_alias_and_seq); + +} + +static int _cmpname(PyObject *self, int code, const char* name, int namelen) { /* check if code corresponds to the given name */ @@ -1200,8 +1219,8 @@ _check_alias_and_seq(unsigned int cp, Py_UCS4* code, int with_named_seq) } static int -_getcode(PyObject* self, const char* name, int namelen, Py_UCS4* code, - int with_named_seq) +_getcode(PyObject* self, + const char* name, int namelen, Py_UCS4* code, int with_named_seq) { /* Return the code point associated with the given name. * Named aliases are resolved too (unless self != NULL (i.e. we are using @@ -1262,8 +1281,9 @@ _getcode(PyObject* self, const char* name, int namelen, Py_UCS4* code, v = code_hash[i]; if (!v) return 0; - if (_cmpname(self, v, name, namelen)) + if (_cmpname(self, v, name, namelen)) { return _check_alias_and_seq(v, code, with_named_seq); + } incr = (h ^ (h >> 3)) & mask; if (!incr) incr = mask; @@ -1272,21 +1292,51 @@ _getcode(PyObject* self, const char* name, int namelen, Py_UCS4* code, v = code_hash[i]; if (!v) return 0; - if (_cmpname(self, v, name, namelen)) + if (_cmpname(self, v, name, namelen)) { return _check_alias_and_seq(v, code, with_named_seq); + } incr = incr << 1; if (incr > mask) incr = incr ^ code_poly; } } -static const _PyUnicode_Name_CAPI hashAPI = +static int +capi_getcode(const char* name, int namelen, Py_UCS4* code, + int with_named_seq) +{ + return _getcode(NULL, name, namelen, code, with_named_seq); + +} + +static void +unicodedata_destroy_capi(PyObject *capsule) { - sizeof(_PyUnicode_Name_CAPI), - _getucname, - _getcode + void *capi = PyCapsule_GetPointer(capsule, PyUnicodeData_CAPSULE_NAME); + PyMem_Free(capi); +} + +static PyObject * +unicodedata_create_capi(void) +{ + _PyUnicode_Name_CAPI *capi = PyMem_Malloc(sizeof(_PyUnicode_Name_CAPI)); + if (capi == NULL) { + PyErr_NoMemory(); + return NULL; + } + capi->getname = capi_getucname; + capi->getcode = capi_getcode; + + PyObject *capsule = PyCapsule_New(capi, + PyUnicodeData_CAPSULE_NAME, + unicodedata_destroy_capi); + if (capsule == NULL) { + PyMem_Free(capi); + } + return capsule; }; + /* -------------------------------------------------------------------- */ /* Python bindings */ @@ -1365,8 +1415,10 @@ unicodedata_UCD_lookup_impl(PyObject *self, const char *name, return PyUnicode_FromOrdinal(code); } -/* XXX Add doc strings. */ - +// List of functions used to define module functions *AND* unicodedata.UCD +// methods. For module functions, self is the module. For UCD methods, self +// is an UCD instance. The UCD_Check() macro is used to check if self is +// an UCD instance. static PyMethodDef unicodedata_functions[] = { UNICODEDATA_UCD_DECIMAL_METHODDEF UNICODEDATA_UCD_DIGIT_METHODDEF @@ -1384,50 +1436,37 @@ static PyMethodDef unicodedata_functions[] = { {NULL, NULL} /* sentinel */ }; -static PyTypeObject UCD_Type = { - /* The ob_type field must be initialized in the module init function - * to be portable to Windows without using C++. */ - PyVarObject_HEAD_INIT(NULL, 0) - "unicodedata.UCD", /*tp_name*/ - sizeof(PreviousDBVersion), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)PyObject_Del, /*tp_dealloc*/ - 0, /*tp_vectorcall_offset*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_as_async*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - PyObject_GenericGetAttr,/*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - unicodedata_functions, /*tp_methods*/ - DB_members, /*tp_members*/ - 0, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - 0, /*tp_init*/ - 0, /*tp_alloc*/ - 0, /*tp_new*/ - 0, /*tp_free*/ - 0, /*tp_is_gc*/ +static int +ucd_traverse(PreviousDBVersion *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + return 0; +} + +static void +ucd_dealloc(PreviousDBVersion *self) +{ + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); + PyObject_GC_Del(self); + Py_DECREF(tp); +} + +static PyType_Slot ucd_type_slots[] = { + {Py_tp_dealloc, ucd_dealloc}, + {Py_tp_traverse, ucd_traverse}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_methods, unicodedata_functions}, + {Py_tp_members, DB_members}, + {0, 0} +}; + +static PyType_Spec ucd_type_spec = { + .name = "unicodedata.UCD", + .basicsize = sizeof(PreviousDBVersion), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), + .slots = ucd_type_slots }; PyDoc_STRVAR(unicodedata_docstring, @@ -1439,45 +1478,70 @@ this database is based on the UnicodeData.txt file version\n\ The module uses the same names and symbols as defined by the\n\ UnicodeData File Format " UNIDATA_VERSION "."); -static struct PyModuleDef unicodedatamodule = { - PyModuleDef_HEAD_INIT, - "unicodedata", - unicodedata_docstring, - -1, - unicodedata_functions, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit_unicodedata(void) +static int +unicodedata_exec(PyObject *module) { - PyObject *m, *v; - - Py_SET_TYPE(&UCD_Type, &PyType_Type); + if (PyModule_AddStringConstant(module, "unidata_version", UNIDATA_VERSION) < 0) { + return -1; + } - m = PyModule_Create(&unicodedatamodule); - if (!m) - return NULL; + PyTypeObject *ucd_type = (PyTypeObject *)PyType_FromSpec(&ucd_type_spec); + if (ucd_type == NULL) { + return -1; + } - PyModule_AddStringConstant(m, "unidata_version", UNIDATA_VERSION); - Py_INCREF(&UCD_Type); - PyModule_AddObject(m, "UCD", (PyObject*)&UCD_Type); + if (PyModule_AddType(module, ucd_type) < 0) { + Py_DECREF(ucd_type); + return -1; + } - /* Previous versions */ - v = new_previous_version("3.2.0", get_change_3_2_0, normalization_3_2_0); - if (v != NULL) - PyModule_AddObject(m, "ucd_3_2_0", v); + // Unicode database version 3.2.0 used by the IDNA encoding + PyObject *v; + v = new_previous_version(ucd_type, "3.2.0", + get_change_3_2_0, normalization_3_2_0); + Py_DECREF(ucd_type); + if (v == NULL) { + return -1; + } + if (PyModule_AddObject(module, "ucd_3_2_0", v) < 0) { + Py_DECREF(v); + return -1; + } /* Export C API */ - v = PyCapsule_New((void *)&hashAPI, PyUnicodeData_CAPSULE_NAME, NULL); - if (v != NULL) - PyModule_AddObject(m, "ucnhash_CAPI", v); - return m; + PyObject *capsule = unicodedata_create_capi(); + if (capsule == NULL) { + return -1; + } + int rc = PyModule_AddObjectRef(module, "_ucnhash_CAPI", capsule); + Py_DECREF(capsule); + if (rc < 0) { + return -1; + } + return 0; } +static PyModuleDef_Slot unicodedata_slots[] = { + {Py_mod_exec, unicodedata_exec}, + {0, NULL} +}; + +static struct PyModuleDef unicodedata_module = { + PyModuleDef_HEAD_INIT, + .m_name = "unicodedata", + .m_doc = unicodedata_docstring, + .m_size = 0, + .m_methods = unicodedata_functions, + .m_slots = unicodedata_slots, +}; + +PyMODINIT_FUNC +PyInit_unicodedata(void) +{ + return PyModuleDef_Init(&unicodedata_module); +} + + /* Local variables: c-basic-offset: 4 diff --git a/contrib/tools/python3/src/Modules/zlibmodule.c b/contrib/tools/python3/src/Modules/zlibmodule.c index 4dfd4ae672..a6940f2fd4 100644 --- a/contrib/tools/python3/src/Modules/zlibmodule.c +++ b/contrib/tools/python3/src/Modules/zlibmodule.c @@ -9,11 +9,166 @@ #include "structmember.h" // PyMemberDef #include "zlib.h" +// Blocks output buffer wrappers +#include "pycore_blocks_output_buffer.h" -#define ENTER_ZLIB(obj) \ - Py_BEGIN_ALLOW_THREADS; \ - PyThread_acquire_lock((obj)->lock, 1); \ - Py_END_ALLOW_THREADS; +#if OUTPUT_BUFFER_MAX_BLOCK_SIZE > UINT32_MAX + #error "The maximum block size accepted by zlib is UINT32_MAX." +#endif + +/* On success, return value >= 0 + On failure, return -1 */ +static inline Py_ssize_t +OutputBuffer_InitAndGrow(_BlocksOutputBuffer *buffer, Py_ssize_t max_length, + Bytef **next_out, uint32_t *avail_out) +{ + Py_ssize_t allocated; + + allocated = _BlocksOutputBuffer_InitAndGrow( + buffer, max_length, (void**) next_out); + *avail_out = (uint32_t) allocated; + return allocated; +} + +/* On success, return value >= 0 + On failure, return -1 */ +static inline Py_ssize_t +OutputBuffer_Grow(_BlocksOutputBuffer *buffer, + Bytef **next_out, uint32_t *avail_out) +{ + Py_ssize_t allocated; + + allocated = _BlocksOutputBuffer_Grow( + buffer, (void**) next_out, (Py_ssize_t) *avail_out); + *avail_out = (uint32_t) allocated; + return allocated; +} + +static inline Py_ssize_t +OutputBuffer_GetDataSize(_BlocksOutputBuffer *buffer, uint32_t avail_out) +{ + return _BlocksOutputBuffer_GetDataSize(buffer, (Py_ssize_t) avail_out); +} + +static inline PyObject * +OutputBuffer_Finish(_BlocksOutputBuffer *buffer, uint32_t avail_out) +{ + return _BlocksOutputBuffer_Finish(buffer, (Py_ssize_t) avail_out); +} + +static inline void +OutputBuffer_OnError(_BlocksOutputBuffer *buffer) +{ + _BlocksOutputBuffer_OnError(buffer); +} + +/* The max buffer size accepted by zlib is UINT32_MAX, the initial buffer size + `init_size` may > it in 64-bit build. These wrapper functions maintain an + UINT32_MAX sliding window for the first block: + 1. OutputBuffer_WindowInitWithSize() + 2. OutputBuffer_WindowGrow() + 3. OutputBuffer_WindowFinish() + 4. OutputBuffer_WindowOnError() + + ==== is the sliding window: + 1. ====------ + ^ next_posi, left_bytes is 6 + 2. ----====-- + ^ next_posi, left_bytes is 2 + 3. --------== + ^ next_posi, left_bytes is 0 */ +typedef struct { + Py_ssize_t left_bytes; + Bytef *next_posi; +} _Uint32Window; + +/* Initialize the buffer with an initial buffer size. + + On success, return value >= 0 + On failure, return value < 0 */ +static inline Py_ssize_t +OutputBuffer_WindowInitWithSize(_BlocksOutputBuffer *buffer, _Uint32Window *window, + Py_ssize_t init_size, + Bytef **next_out, uint32_t *avail_out) +{ + Py_ssize_t allocated = _BlocksOutputBuffer_InitWithSize( + buffer, init_size, (void**) next_out); + + if (allocated >= 0) { + // the UINT32_MAX sliding window + Py_ssize_t window_size = Py_MIN((size_t)allocated, UINT32_MAX); + *avail_out = (uint32_t) window_size; + + window->left_bytes = allocated - window_size; + window->next_posi = *next_out + window_size; + } + return allocated; +} + +/* Grow the buffer. + + On success, return value >= 0 + On failure, return value < 0 */ +static inline Py_ssize_t +OutputBuffer_WindowGrow(_BlocksOutputBuffer *buffer, _Uint32Window *window, + Bytef **next_out, uint32_t *avail_out) +{ + Py_ssize_t allocated; + + /* ensure no gaps in the data. + if inlined, this check could be optimized away.*/ + if (*avail_out != 0) { + PyErr_SetString(PyExc_SystemError, + "*avail_out != 0 in OutputBuffer_WindowGrow()."); + return -1; + } + + // slide the UINT32_MAX sliding window + if (window->left_bytes > 0) { + Py_ssize_t window_size = Py_MIN((size_t)window->left_bytes, UINT32_MAX); + + *next_out = window->next_posi; + *avail_out = (uint32_t) window_size; + + window->left_bytes -= window_size; + window->next_posi += window_size; + + return window_size; + } + assert(window->left_bytes == 0); + + // only the first block may > UINT32_MAX + allocated = _BlocksOutputBuffer_Grow( + buffer, (void**) next_out, (Py_ssize_t) *avail_out); + *avail_out = (uint32_t) allocated; + return allocated; +} + +/* Finish the buffer. + + On success, return a bytes object + On failure, return NULL */ +static inline PyObject * +OutputBuffer_WindowFinish(_BlocksOutputBuffer *buffer, _Uint32Window *window, + uint32_t avail_out) +{ + Py_ssize_t real_avail_out = (Py_ssize_t) avail_out + window->left_bytes; + return _BlocksOutputBuffer_Finish(buffer, real_avail_out); +} + +static inline void +OutputBuffer_WindowOnError(_BlocksOutputBuffer *buffer, _Uint32Window *window) +{ + _BlocksOutputBuffer_OnError(buffer); +} + + +#define ENTER_ZLIB(obj) do { \ + if (!PyThread_acquire_lock((obj)->lock, 0)) { \ + Py_BEGIN_ALLOW_THREADS \ + PyThread_acquire_lock((obj)->lock, 1); \ + Py_END_ALLOW_THREADS \ + } } while (0) #define LEAVE_ZLIB(obj) PyThread_release_lock((obj)->lock); #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1221 @@ -37,18 +192,16 @@ typedef struct { PyTypeObject *Comptype; PyTypeObject *Decomptype; PyObject *ZlibError; -} _zlibstate; +} zlibstate; -static inline _zlibstate* +static inline zlibstate* get_zlib_state(PyObject *module) { void *state = PyModule_GetState(module); assert(state != NULL); - return (_zlibstate *)state; + return (zlibstate *)state; } -#define _zlibstate_global ((_zlibstate *)PyModule_GetState(PyState_FindModule(&zlibmodule))) - typedef struct { PyObject_HEAD @@ -62,7 +215,7 @@ typedef struct } compobject; static void -zlib_error(z_stream zst, int err, const char *msg) +zlib_error(zlibstate *state, z_stream zst, int err, const char *msg) { const char *zmsg = Z_NULL; /* In case of a version mismatch, zst.msg won't be initialized. @@ -85,9 +238,9 @@ zlib_error(z_stream zst, int err, const char *msg) } } if (zmsg == Z_NULL) - PyErr_Format(_zlibstate_global->ZlibError, "Error %d %s", err, msg); + PyErr_Format(state->ZlibError, "Error %d %s", err, msg); else - PyErr_Format(_zlibstate_global->ZlibError, "Error %d %s: %.200s", err, msg, zmsg); + PyErr_Format(state->ZlibError, "Error %d %s: %.200s", err, msg, zmsg); } /*[clinic input] @@ -149,56 +302,6 @@ arrange_input_buffer(z_stream *zst, Py_ssize_t *remains) *remains -= zst->avail_in; } -static Py_ssize_t -arrange_output_buffer_with_maximum(z_stream *zst, PyObject **buffer, - Py_ssize_t length, - Py_ssize_t max_length) -{ - Py_ssize_t occupied; - - if (*buffer == NULL) { - if (!(*buffer = PyBytes_FromStringAndSize(NULL, length))) - return -1; - occupied = 0; - } - else { - occupied = zst->next_out - (Byte *)PyBytes_AS_STRING(*buffer); - - if (length == occupied) { - Py_ssize_t new_length; - assert(length <= max_length); - /* can not scale the buffer over max_length */ - if (length == max_length) - return -2; - if (length <= (max_length >> 1)) - new_length = length << 1; - else - new_length = max_length; - if (_PyBytes_Resize(buffer, new_length) < 0) - return -1; - length = new_length; - } - } - - zst->avail_out = (uInt)Py_MIN((size_t)(length - occupied), UINT_MAX); - zst->next_out = (Byte *)PyBytes_AS_STRING(*buffer) + occupied; - - return length; -} - -static Py_ssize_t -arrange_output_buffer(z_stream *zst, PyObject **buffer, Py_ssize_t length) -{ - Py_ssize_t ret; - - ret = arrange_output_buffer_with_maximum(zst, buffer, length, - PY_SSIZE_T_MAX); - if (ret == -2) - PyErr_NoMemory(); - - return ret; -} - /*[clinic input] zlib.compress @@ -215,20 +318,25 @@ static PyObject * zlib_compress_impl(PyObject *module, Py_buffer *data, int level) /*[clinic end generated code: output=d80906d73f6294c8 input=638d54b6315dbed3]*/ { - PyObject *RetVal = NULL; - Byte *ibuf; - Py_ssize_t ibuflen, obuflen = DEF_BUF_SIZE; - int err, flush; + PyObject *RetVal; + int flush; z_stream zst; + _BlocksOutputBuffer buffer = {.list = NULL}; - ibuf = data->buf; - ibuflen = data->len; + zlibstate *state = get_zlib_state(module); + + Byte *ibuf = data->buf; + Py_ssize_t ibuflen = data->len; + + if (OutputBuffer_InitAndGrow(&buffer, -1, &zst.next_out, &zst.avail_out) < 0) { + goto error; + } zst.opaque = NULL; zst.zalloc = PyZlib_Malloc; zst.zfree = PyZlib_Free; zst.next_in = ibuf; - err = deflateInit(&zst, level); + int err = deflateInit(&zst, level); switch (err) { case Z_OK: @@ -238,11 +346,11 @@ zlib_compress_impl(PyObject *module, Py_buffer *data, int level) "Out of memory while compressing data"); goto error; case Z_STREAM_ERROR: - PyErr_SetString(_zlibstate_global->ZlibError, "Bad compression level"); + PyErr_SetString(state->ZlibError, "Bad compression level"); goto error; default: deflateEnd(&zst); - zlib_error(zst, err, "while compressing data"); + zlib_error(state, zst, err, "while compressing data"); goto error; } @@ -251,10 +359,11 @@ zlib_compress_impl(PyObject *module, Py_buffer *data, int level) flush = ibuflen == 0 ? Z_FINISH : Z_NO_FLUSH; do { - obuflen = arrange_output_buffer(&zst, &RetVal, obuflen); - if (obuflen < 0) { - deflateEnd(&zst); - goto error; + if (zst.avail_out == 0) { + if (OutputBuffer_Grow(&buffer, &zst.next_out, &zst.avail_out) < 0) { + deflateEnd(&zst); + goto error; + } } Py_BEGIN_ALLOW_THREADS @@ -263,7 +372,7 @@ zlib_compress_impl(PyObject *module, Py_buffer *data, int level) if (err == Z_STREAM_ERROR) { deflateEnd(&zst); - zlib_error(zst, err, "while compressing data"); + zlib_error(state, zst, err, "while compressing data"); goto error; } @@ -275,49 +384,19 @@ zlib_compress_impl(PyObject *module, Py_buffer *data, int level) err = deflateEnd(&zst); if (err == Z_OK) { - if (_PyBytes_Resize(&RetVal, zst.next_out - - (Byte *)PyBytes_AS_STRING(RetVal)) < 0) + RetVal = OutputBuffer_Finish(&buffer, zst.avail_out); + if (RetVal == NULL) { goto error; + } return RetVal; } else - zlib_error(zst, err, "while finishing compression"); + zlib_error(state, zst, err, "while finishing compression"); error: - Py_XDECREF(RetVal); + OutputBuffer_OnError(&buffer); return NULL; } -/*[python input] - -class ssize_t_converter(CConverter): - type = 'Py_ssize_t' - converter = 'ssize_t_converter' - c_ignored_default = "0" - -[python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=5f34ba1b394cb8e7]*/ - -static int -ssize_t_converter(PyObject *obj, void *ptr) -{ - PyObject *long_obj; - Py_ssize_t val; - - /* XXX Should be replaced with PyNumber_AsSsize_t after the end of the - deprecation period. */ - long_obj = _PyLong_FromNbIndexOrNbInt(obj); - if (long_obj == NULL) { - return 0; - } - val = PyLong_AsSsize_t(long_obj); - Py_DECREF(long_obj); - if (val == -1 && PyErr_Occurred()) { - return 0; - } - *(Py_ssize_t *)ptr = val; - return 1; -} - /*[clinic input] zlib.decompress @@ -326,7 +405,7 @@ zlib.decompress / wbits: int(c_default="MAX_WBITS") = MAX_WBITS The window buffer size and container format. - bufsize: ssize_t(c_default="DEF_BUF_SIZE") = DEF_BUF_SIZE + bufsize: Py_ssize_t(c_default="DEF_BUF_SIZE") = DEF_BUF_SIZE The initial output buffer size. Returns a bytes object containing the uncompressed data. @@ -335,13 +414,17 @@ Returns a bytes object containing the uncompressed data. static PyObject * zlib_decompress_impl(PyObject *module, Py_buffer *data, int wbits, Py_ssize_t bufsize) -/*[clinic end generated code: output=77c7e35111dc8c42 input=21960936208e9a5b]*/ +/*[clinic end generated code: output=77c7e35111dc8c42 input=a9ac17beff1f893f]*/ { - PyObject *RetVal = NULL; + PyObject *RetVal; Byte *ibuf; Py_ssize_t ibuflen; int err, flush; z_stream zst; + _BlocksOutputBuffer buffer = {.list = NULL}; + _Uint32Window window; // output buffer's UINT32_MAX sliding window + + zlibstate *state = get_zlib_state(module); if (bufsize < 0) { PyErr_SetString(PyExc_ValueError, "bufsize must be non-negative"); @@ -350,6 +433,11 @@ zlib_decompress_impl(PyObject *module, Py_buffer *data, int wbits, bufsize = 1; } + if (OutputBuffer_WindowInitWithSize(&buffer, &window, bufsize, + &zst.next_out, &zst.avail_out) < 0) { + goto error; + } + ibuf = data->buf; ibuflen = data->len; @@ -369,7 +457,7 @@ zlib_decompress_impl(PyObject *module, Py_buffer *data, int wbits, goto error; default: inflateEnd(&zst); - zlib_error(zst, err, "while preparing to decompress data"); + zlib_error(state, zst, err, "while preparing to decompress data"); goto error; } @@ -378,10 +466,12 @@ zlib_decompress_impl(PyObject *module, Py_buffer *data, int wbits, flush = ibuflen == 0 ? Z_FINISH : Z_NO_FLUSH; do { - bufsize = arrange_output_buffer(&zst, &RetVal, bufsize); - if (bufsize < 0) { - inflateEnd(&zst); - goto error; + if (zst.avail_out == 0) { + if (OutputBuffer_WindowGrow(&buffer, &window, + &zst.next_out, &zst.avail_out) < 0) { + inflateEnd(&zst); + goto error; + } } Py_BEGIN_ALLOW_THREADS @@ -400,7 +490,7 @@ zlib_decompress_impl(PyObject *module, Py_buffer *data, int wbits, goto error; default: inflateEnd(&zst); - zlib_error(zst, err, "while decompressing data"); + zlib_error(state, zst, err, "while decompressing data"); goto error; } @@ -411,24 +501,23 @@ zlib_decompress_impl(PyObject *module, Py_buffer *data, int wbits, if (err != Z_STREAM_END) { inflateEnd(&zst); - zlib_error(zst, err, "while decompressing data"); + zlib_error(state, zst, err, "while decompressing data"); goto error; } err = inflateEnd(&zst); if (err != Z_OK) { - zlib_error(zst, err, "while finishing decompression"); + zlib_error(state, zst, err, "while finishing decompression"); goto error; } - if (_PyBytes_Resize(&RetVal, zst.next_out - - (Byte *)PyBytes_AS_STRING(RetVal)) < 0) - goto error; - - return RetVal; + RetVal = OutputBuffer_WindowFinish(&buffer, &window, zst.avail_out); + if (RetVal != NULL) { + return RetVal; + } error: - Py_XDECREF(RetVal); + OutputBuffer_WindowOnError(&buffer, &window); return NULL; } @@ -465,16 +554,14 @@ zlib_compressobj_impl(PyObject *module, int level, int method, int wbits, int memLevel, int strategy, Py_buffer *zdict) /*[clinic end generated code: output=8b5bed9c8fc3814d input=2fa3d026f90ab8d5]*/ { - compobject *self = NULL; - int err; - + zlibstate *state = get_zlib_state(module); if (zdict->buf != NULL && (size_t)zdict->len > UINT_MAX) { PyErr_SetString(PyExc_OverflowError, "zdict length does not fit in an unsigned int"); - goto error; + return NULL; } - self = newcompobject(_zlibstate_global->Comptype); + compobject *self = newcompobject(state->Comptype); if (self == NULL) goto error; self->zst.opaque = NULL; @@ -482,7 +569,7 @@ zlib_compressobj_impl(PyObject *module, int level, int method, int wbits, self->zst.zfree = PyZlib_Free; self->zst.next_in = NULL; self->zst.avail_in = 0; - err = deflateInit2(&self->zst, level, method, wbits, memLevel, strategy); + int err = deflateInit2(&self->zst, level, method, wbits, memLevel, strategy); switch (err) { case Z_OK: self->is_initialised = 1; @@ -510,7 +597,7 @@ zlib_compressobj_impl(PyObject *module, int level, int method, int wbits, PyErr_SetString(PyExc_ValueError, "Invalid initialization option"); goto error; default: - zlib_error(self->zst, err, "while creating compression object"); + zlib_error(state, self->zst, err, "while creating compression object"); goto error; } @@ -521,11 +608,9 @@ zlib_compressobj_impl(PyObject *module, int level, int method, int wbits, } static int -set_inflate_zdict(compobject *self) +set_inflate_zdict(zlibstate *state, compobject *self) { Py_buffer zdict_buf; - int err; - if (PyObject_GetBuffer(self->zdict, &zdict_buf, PyBUF_SIMPLE) == -1) { return -1; } @@ -535,11 +620,12 @@ set_inflate_zdict(compobject *self) PyBuffer_Release(&zdict_buf); return -1; } + int err; err = inflateSetDictionary(&self->zst, zdict_buf.buf, (unsigned int)zdict_buf.len); PyBuffer_Release(&zdict_buf); if (err != Z_OK) { - zlib_error(self->zst, err, "while setting zdict"); + zlib_error(state, self->zst, err, "while setting zdict"); return -1; } return 0; @@ -561,8 +647,7 @@ static PyObject * zlib_decompressobj_impl(PyObject *module, int wbits, PyObject *zdict) /*[clinic end generated code: output=3069b99994f36906 input=d3832b8511fc977b]*/ { - int err; - compobject *self; + zlibstate *state = get_zlib_state(module); if (zdict != NULL && !PyObject_CheckBuffer(zdict)) { PyErr_SetString(PyExc_TypeError, @@ -570,7 +655,7 @@ zlib_decompressobj_impl(PyObject *module, int wbits, PyObject *zdict) return NULL; } - self = newcompobject(_zlibstate_global->Decomptype); + compobject *self = newcompobject(state->Decomptype); if (self == NULL) return NULL; self->zst.opaque = NULL; @@ -582,18 +667,18 @@ zlib_decompressobj_impl(PyObject *module, int wbits, PyObject *zdict) Py_INCREF(zdict); self->zdict = zdict; } - err = inflateInit2(&self->zst, wbits); + int err = inflateInit2(&self->zst, wbits); switch (err) { case Z_OK: self->is_initialised = 1; if (self->zdict != NULL && wbits < 0) { #ifdef AT_LEAST_ZLIB_1_2_2_1 - if (set_inflate_zdict(self) < 0) { + if (set_inflate_zdict(state, self) < 0) { Py_DECREF(self); return NULL; } #else - PyErr_Format(_zlibstate_global->ZlibError, + PyErr_Format(state->ZlibError, "zlib version %s does not allow raw inflate with dictionary", ZLIB_VERSION); Py_DECREF(self); @@ -611,7 +696,7 @@ zlib_decompressobj_impl(PyObject *module, int wbits, PyObject *zdict) "Can't allocate memory for decompression object"); return NULL; default: - zlib_error(self->zst, err, "while creating decompression object"); + zlib_error(state, self->zst, err, "while creating decompression object"); Py_DECREF(self); return NULL; } @@ -625,7 +710,7 @@ Dealloc(compobject *self) Py_XDECREF(self->unused_data); Py_XDECREF(self->unconsumed_tail); Py_XDECREF(self->zdict); - PyObject_Del(self); + PyObject_Free(self); Py_DECREF(type); } @@ -648,6 +733,7 @@ Decomp_dealloc(compobject *self) /*[clinic input] zlib.Compress.compress + cls: defining_class data: Py_buffer Binary data to be compressed. / @@ -660,32 +746,40 @@ Call the flush() method to clear these buffers. [clinic start generated code]*/ static PyObject * -zlib_Compress_compress_impl(compobject *self, Py_buffer *data) -/*[clinic end generated code: output=5d5cd791cbc6a7f4 input=0d95908d6e64fab8]*/ +zlib_Compress_compress_impl(compobject *self, PyTypeObject *cls, + Py_buffer *data) +/*[clinic end generated code: output=6731b3f0ff357ca6 input=04d00f65ab01d260]*/ { - PyObject *RetVal = NULL; - Py_ssize_t ibuflen, obuflen = DEF_BUF_SIZE; + PyObject *RetVal; int err; + _BlocksOutputBuffer buffer = {.list = NULL}; + zlibstate *state = PyType_GetModuleState(cls); ENTER_ZLIB(self); self->zst.next_in = data->buf; - ibuflen = data->len; + Py_ssize_t ibuflen = data->len; + + if (OutputBuffer_InitAndGrow(&buffer, -1, &self->zst.next_out, &self->zst.avail_out) < 0) { + goto error; + } do { arrange_input_buffer(&self->zst, &ibuflen); do { - obuflen = arrange_output_buffer(&self->zst, &RetVal, obuflen); - if (obuflen < 0) - goto error; + if (self->zst.avail_out == 0) { + if (OutputBuffer_Grow(&buffer, &self->zst.next_out, &self->zst.avail_out) < 0) { + goto error; + } + } Py_BEGIN_ALLOW_THREADS err = deflate(&self->zst, Z_NO_FLUSH); Py_END_ALLOW_THREADS if (err == Z_STREAM_ERROR) { - zlib_error(self->zst, err, "while compressing data"); + zlib_error(state, self->zst, err, "while compressing data"); goto error; } @@ -694,12 +788,14 @@ zlib_Compress_compress_impl(compobject *self, Py_buffer *data) } while (ibuflen != 0); - if (_PyBytes_Resize(&RetVal, self->zst.next_out - - (Byte *)PyBytes_AS_STRING(RetVal)) == 0) + RetVal = OutputBuffer_Finish(&buffer, self->zst.avail_out); + if (RetVal != NULL) { goto success; + } error: - Py_CLEAR(RetVal); + OutputBuffer_OnError(&buffer); + RetVal = NULL; success: LEAVE_ZLIB(self); return RetVal; @@ -753,10 +849,11 @@ save_unconsumed_input(compobject *self, Py_buffer *data, int err) /*[clinic input] zlib.Decompress.decompress + cls: defining_class data: Py_buffer The binary data to decompress. / - max_length: ssize_t = 0 + max_length: Py_ssize_t = 0 The maximum allowable length of the decompressed data. Unconsumed input data will be stored in the unconsumed_tail attribute. @@ -769,45 +866,47 @@ Call the flush() method to clear these buffers. [clinic start generated code]*/ static PyObject * -zlib_Decompress_decompress_impl(compobject *self, Py_buffer *data, - Py_ssize_t max_length) -/*[clinic end generated code: output=6e5173c74e710352 input=b85a212a012b770a]*/ +zlib_Decompress_decompress_impl(compobject *self, PyTypeObject *cls, + Py_buffer *data, Py_ssize_t max_length) +/*[clinic end generated code: output=b024a93c2c922d57 input=bfb37b3864cfb606]*/ { int err = Z_OK; - Py_ssize_t ibuflen, obuflen = DEF_BUF_SIZE, hard_limit; - PyObject *RetVal = NULL; + Py_ssize_t ibuflen; + PyObject *RetVal; + _BlocksOutputBuffer buffer = {.list = NULL}; + PyObject *module = PyType_GetModule(cls); + if (module == NULL) + return NULL; + + zlibstate *state = get_zlib_state(module); if (max_length < 0) { PyErr_SetString(PyExc_ValueError, "max_length must be non-negative"); return NULL; - } else if (max_length == 0) - hard_limit = PY_SSIZE_T_MAX; - else - hard_limit = max_length; + } else if (max_length == 0) { + max_length = -1; + } ENTER_ZLIB(self); self->zst.next_in = data->buf; ibuflen = data->len; - /* limit amount of data allocated to max_length */ - if (max_length && obuflen > max_length) - obuflen = max_length; + if (OutputBuffer_InitAndGrow(&buffer, max_length, &self->zst.next_out, &self->zst.avail_out) < 0) { + goto abort; + } do { arrange_input_buffer(&self->zst, &ibuflen); do { - obuflen = arrange_output_buffer_with_maximum(&self->zst, &RetVal, - obuflen, hard_limit); - if (obuflen == -2) { - if (max_length > 0) { + if (self->zst.avail_out == 0) { + if (OutputBuffer_GetDataSize(&buffer, self->zst.avail_out) == max_length) { goto save; } - PyErr_NoMemory(); - } - if (obuflen < 0) { - goto abort; + if (OutputBuffer_Grow(&buffer, &self->zst.next_out, &self->zst.avail_out) < 0) { + goto abort; + } } Py_BEGIN_ALLOW_THREADS @@ -821,8 +920,9 @@ zlib_Decompress_decompress_impl(compobject *self, Py_buffer *data, break; default: if (err == Z_NEED_DICT && self->zdict != NULL) { - if (set_inflate_zdict(self) < 0) + if (set_inflate_zdict(state, self) < 0) { goto abort; + } else break; } @@ -846,16 +946,18 @@ zlib_Decompress_decompress_impl(compobject *self, Py_buffer *data, but there wasn't more output when we tried again, so it is not an error condition. */ - zlib_error(self->zst, err, "while decompressing data"); + zlib_error(state, self->zst, err, "while decompressing data"); goto abort; } - if (_PyBytes_Resize(&RetVal, self->zst.next_out - - (Byte *)PyBytes_AS_STRING(RetVal)) == 0) + RetVal = OutputBuffer_Finish(&buffer, self->zst.avail_out); + if (RetVal != NULL) { goto success; + } abort: - Py_CLEAR(RetVal); + OutputBuffer_OnError(&buffer); + RetVal = NULL; success: LEAVE_ZLIB(self); return RetVal; @@ -864,6 +966,7 @@ zlib_Decompress_decompress_impl(compobject *self, Py_buffer *data, /*[clinic input] zlib.Compress.flush + cls: defining_class mode: int(c_default="Z_FINISH") = zlib.Z_FINISH One of the constants Z_SYNC_FLUSH, Z_FULL_FLUSH, Z_FINISH. If mode == Z_FINISH, the compressor object can no longer be @@ -875,13 +978,14 @@ Return a bytes object containing any remaining compressed data. [clinic start generated code]*/ static PyObject * -zlib_Compress_flush_impl(compobject *self, int mode) -/*[clinic end generated code: output=a203f4cefc9de727 input=73ed066794bd15bc]*/ +zlib_Compress_flush_impl(compobject *self, PyTypeObject *cls, int mode) +/*[clinic end generated code: output=c7efd13efd62add2 input=286146e29442eb6c]*/ { int err; - Py_ssize_t length = DEF_BUF_SIZE; - PyObject *RetVal = NULL; + PyObject *RetVal; + _BlocksOutputBuffer buffer = {.list = NULL}; + zlibstate *state = PyType_GetModuleState(cls); /* Flushing with Z_NO_FLUSH is a no-op, so there's no point in doing any work at all; just return an empty string. */ if (mode == Z_NO_FLUSH) { @@ -892,11 +996,15 @@ zlib_Compress_flush_impl(compobject *self, int mode) self->zst.avail_in = 0; + if (OutputBuffer_InitAndGrow(&buffer, -1, &self->zst.next_out, &self->zst.avail_out) < 0) { + goto error; + } + do { - length = arrange_output_buffer(&self->zst, &RetVal, length); - if (length < 0) { - Py_CLEAR(RetVal); - goto error; + if (self->zst.avail_out == 0) { + if (OutputBuffer_Grow(&buffer, &self->zst.next_out, &self->zst.avail_out) < 0) { + goto error; + } } Py_BEGIN_ALLOW_THREADS @@ -904,8 +1012,7 @@ zlib_Compress_flush_impl(compobject *self, int mode) Py_END_ALLOW_THREADS if (err == Z_STREAM_ERROR) { - zlib_error(self->zst, err, "while flushing"); - Py_CLEAR(RetVal); + zlib_error(state, self->zst, err, "while flushing"); goto error; } } while (self->zst.avail_out == 0); @@ -917,8 +1024,7 @@ zlib_Compress_flush_impl(compobject *self, int mode) if (err == Z_STREAM_END && mode == Z_FINISH) { err = deflateEnd(&self->zst); if (err != Z_OK) { - zlib_error(self->zst, err, "while finishing compression"); - Py_CLEAR(RetVal); + zlib_error(state, self->zst, err, "while finishing compression"); goto error; } else @@ -929,16 +1035,19 @@ zlib_Compress_flush_impl(compobject *self, int mode) not an error condition. */ } else if (err != Z_OK && err != Z_BUF_ERROR) { - zlib_error(self->zst, err, "while flushing"); - Py_CLEAR(RetVal); + zlib_error(state, self->zst, err, "while flushing"); goto error; } - if (_PyBytes_Resize(&RetVal, self->zst.next_out - - (Byte *)PyBytes_AS_STRING(RetVal)) < 0) - Py_CLEAR(RetVal); + RetVal = OutputBuffer_Finish(&buffer, self->zst.avail_out); + if (RetVal != NULL) { + goto success; + } - error: +error: + OutputBuffer_OnError(&buffer); + RetVal = NULL; +success: LEAVE_ZLIB(self); return RetVal; } @@ -948,24 +1057,25 @@ zlib_Compress_flush_impl(compobject *self, int mode) /*[clinic input] zlib.Compress.copy + cls: defining_class + Return a copy of the compression object. [clinic start generated code]*/ static PyObject * -zlib_Compress_copy_impl(compobject *self) -/*[clinic end generated code: output=5144aa153c21e805 input=c656351f94b82718]*/ +zlib_Compress_copy_impl(compobject *self, PyTypeObject *cls) +/*[clinic end generated code: output=c4d2cfb4b0d7350b input=235497e482d40986]*/ { - compobject *retval = NULL; - int err; + zlibstate *state = PyType_GetModuleState(cls); - retval = newcompobject(_zlibstate_global->Comptype); + compobject *retval = newcompobject(state->Comptype); if (!retval) return NULL; /* Copy the zstream state * We use ENTER_ZLIB / LEAVE_ZLIB to make this thread-safe */ ENTER_ZLIB(self); - err = deflateCopy(&retval->zst, &self->zst); + int err = deflateCopy(&retval->zst, &self->zst); switch (err) { case Z_OK: break; @@ -977,7 +1087,7 @@ zlib_Compress_copy_impl(compobject *self) "Can't allocate memory for compression object"); goto error; default: - zlib_error(self->zst, err, "while copying compression object"); + zlib_error(state, self->zst, err, "while copying compression object"); goto error; } Py_INCREF(self->unused_data); @@ -1002,51 +1112,57 @@ error: /*[clinic input] zlib.Compress.__copy__ + + cls: defining_class + [clinic start generated code]*/ static PyObject * -zlib_Compress___copy___impl(compobject *self) -/*[clinic end generated code: output=1875e6791975442e input=be97a05a788dfd83]*/ +zlib_Compress___copy___impl(compobject *self, PyTypeObject *cls) +/*[clinic end generated code: output=074613db332cb668 input=5c0188367ab0fe64]*/ { - return zlib_Compress_copy_impl(self); + return zlib_Compress_copy_impl(self, cls); } /*[clinic input] zlib.Compress.__deepcopy__ + cls: defining_class memo: object / [clinic start generated code]*/ static PyObject * -zlib_Compress___deepcopy__(compobject *self, PyObject *memo) -/*[clinic end generated code: output=f47a2213282c9eb0 input=a9a8b0b40d83388e]*/ +zlib_Compress___deepcopy___impl(compobject *self, PyTypeObject *cls, + PyObject *memo) +/*[clinic end generated code: output=24b3aed785f54033 input=c90347319a514430]*/ { - return zlib_Compress_copy_impl(self); + return zlib_Compress_copy_impl(self, cls); } /*[clinic input] zlib.Decompress.copy + cls: defining_class + Return a copy of the decompression object. [clinic start generated code]*/ static PyObject * -zlib_Decompress_copy_impl(compobject *self) -/*[clinic end generated code: output=02a883a2a510c8cc input=ba6c3e96712a596b]*/ +zlib_Decompress_copy_impl(compobject *self, PyTypeObject *cls) +/*[clinic end generated code: output=a7ddc016e1d0a781 input=20ef3aa208282ff2]*/ { - compobject *retval = NULL; - int err; + zlibstate *state = PyType_GetModuleState(cls); - retval = newcompobject(_zlibstate_global->Decomptype); + compobject *retval = newcompobject(state->Decomptype); if (!retval) return NULL; /* Copy the zstream state * We use ENTER_ZLIB / LEAVE_ZLIB to make this thread-safe */ ENTER_ZLIB(self); - err = inflateCopy(&retval->zst, &self->zst); + int err = inflateCopy(&retval->zst, &self->zst); switch (err) { case Z_OK: break; @@ -1058,7 +1174,7 @@ zlib_Decompress_copy_impl(compobject *self) "Can't allocate memory for decompression object"); goto error; default: - zlib_error(self->zst, err, "while copying decompression object"); + zlib_error(state, self->zst, err, "while copying decompression object"); goto error; } @@ -1084,28 +1200,33 @@ error: /*[clinic input] zlib.Decompress.__copy__ + + cls: defining_class + [clinic start generated code]*/ static PyObject * -zlib_Decompress___copy___impl(compobject *self) -/*[clinic end generated code: output=80bae8bc43498ad4 input=efcb98b5472c13d2]*/ +zlib_Decompress___copy___impl(compobject *self, PyTypeObject *cls) +/*[clinic end generated code: output=cf1e6473744f53fa input=cc3143067b622bdf]*/ { - return zlib_Decompress_copy_impl(self); + return zlib_Decompress_copy_impl(self, cls); } /*[clinic input] zlib.Decompress.__deepcopy__ + cls: defining_class memo: object / [clinic start generated code]*/ static PyObject * -zlib_Decompress___deepcopy__(compobject *self, PyObject *memo) -/*[clinic end generated code: output=1f77286ab490124b input=6e99bd0ac4b9cd8b]*/ +zlib_Decompress___deepcopy___impl(compobject *self, PyTypeObject *cls, + PyObject *memo) +/*[clinic end generated code: output=34f7b719a0c0d51b input=fc13b9c58622544e]*/ { - return zlib_Decompress_copy_impl(self); + return zlib_Decompress_copy_impl(self, cls); } #endif @@ -1113,7 +1234,8 @@ zlib_Decompress___deepcopy__(compobject *self, PyObject *memo) /*[clinic input] zlib.Decompress.flush - length: ssize_t(c_default="DEF_BUF_SIZE") = zlib.DEF_BUF_SIZE + cls: defining_class + length: Py_ssize_t(c_default="DEF_BUF_SIZE") = zlib.DEF_BUF_SIZE the initial size of the output buffer. / @@ -1121,13 +1243,23 @@ Return a bytes object containing any remaining decompressed data. [clinic start generated code]*/ static PyObject * -zlib_Decompress_flush_impl(compobject *self, Py_ssize_t length) -/*[clinic end generated code: output=68c75ea127cbe654 input=aa4ec37f3aef4da0]*/ +zlib_Decompress_flush_impl(compobject *self, PyTypeObject *cls, + Py_ssize_t length) +/*[clinic end generated code: output=4532fc280bd0f8f2 input=42f1f4b75230e2cd]*/ { int err, flush; Py_buffer data; - PyObject *RetVal = NULL; + PyObject *RetVal; Py_ssize_t ibuflen; + _BlocksOutputBuffer buffer = {.list = NULL}; + _Uint32Window window; // output buffer's UINT32_MAX sliding window + + PyObject *module = PyType_GetModule(cls); + if (module == NULL) { + return NULL; + } + + zlibstate *state = get_zlib_state(module); if (length <= 0) { PyErr_SetString(PyExc_ValueError, "length must be greater than zero"); @@ -1144,14 +1276,22 @@ zlib_Decompress_flush_impl(compobject *self, Py_ssize_t length) self->zst.next_in = data.buf; ibuflen = data.len; + if (OutputBuffer_WindowInitWithSize(&buffer, &window, length, + &self->zst.next_out, &self->zst.avail_out) < 0) { + goto abort; + } + do { arrange_input_buffer(&self->zst, &ibuflen); flush = ibuflen == 0 ? Z_FINISH : Z_NO_FLUSH; do { - length = arrange_output_buffer(&self->zst, &RetVal, length); - if (length < 0) - goto abort; + if (self->zst.avail_out == 0) { + if (OutputBuffer_WindowGrow(&buffer, &window, + &self->zst.next_out, &self->zst.avail_out) < 0) { + goto abort; + } + } Py_BEGIN_ALLOW_THREADS err = inflate(&self->zst, flush); @@ -1164,8 +1304,9 @@ zlib_Decompress_flush_impl(compobject *self, Py_ssize_t length) break; default: if (err == Z_NEED_DICT && self->zdict != NULL) { - if (set_inflate_zdict(self) < 0) + if (set_inflate_zdict(state, self) < 0) { goto abort; + } else break; } @@ -1177,8 +1318,9 @@ zlib_Decompress_flush_impl(compobject *self, Py_ssize_t length) } while (err != Z_STREAM_END && ibuflen != 0); save: - if (save_unconsumed_input(self, &data, err) < 0) + if (save_unconsumed_input(self, &data, err) < 0) { goto abort; + } /* If at end of stream, clean up any memory allocated by zlib. */ if (err == Z_STREAM_END) { @@ -1186,17 +1328,19 @@ zlib_Decompress_flush_impl(compobject *self, Py_ssize_t length) self->is_initialised = 0; err = inflateEnd(&self->zst); if (err != Z_OK) { - zlib_error(self->zst, err, "while finishing decompression"); + zlib_error(state, self->zst, err, "while finishing decompression"); goto abort; } } - if (_PyBytes_Resize(&RetVal, self->zst.next_out - - (Byte *)PyBytes_AS_STRING(RetVal)) == 0) + RetVal = OutputBuffer_WindowFinish(&buffer, &window, self->zst.avail_out); + if (RetVal != NULL) { goto success; + } abort: - Py_CLEAR(RetVal); + OutputBuffer_WindowOnError(&buffer, &window); + RetVal = NULL; success: PyBuffer_Release(&data); LEAVE_ZLIB(self); @@ -1332,11 +1476,10 @@ static PyType_Slot Comptype_slots[] = { }; static PyType_Spec Comptype_spec = { - "zlib.Compress", - sizeof(compobject), - 0, - Py_TPFLAGS_DEFAULT, - Comptype_slots + .name = "zlib.Compress", + .basicsize = sizeof(compobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, + .slots= Comptype_slots, }; static PyType_Slot Decomptype_slots[] = { @@ -1347,11 +1490,10 @@ static PyType_Slot Decomptype_slots[] = { }; static PyType_Spec Decomptype_spec = { - "zlib.Decompress", - sizeof(compobject), - 0, - Py_TPFLAGS_DEFAULT, - Decomptype_slots + .name = "zlib.Decompress", + .basicsize = sizeof(compobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION, + .slots = Decomptype_slots, }; PyDoc_STRVAR(zlib_module_documentation, @@ -1370,9 +1512,9 @@ PyDoc_STRVAR(zlib_module_documentation, "objects support decompress() and flush()."); static int -zlib_clear(PyObject *m) +zlib_clear(PyObject *mod) { - _zlibstate *state = get_zlib_state(m); + zlibstate *state = get_zlib_state(mod); Py_CLEAR(state->Comptype); Py_CLEAR(state->Decomptype); Py_CLEAR(state->ZlibError); @@ -1380,9 +1522,9 @@ zlib_clear(PyObject *m) } static int -zlib_traverse(PyObject *m, visitproc visit, void *arg) +zlib_traverse(PyObject *mod, visitproc visit, void *arg) { - _zlibstate *state = get_zlib_state(m); + zlibstate *state = get_zlib_state(mod); Py_VISIT(state->Comptype); Py_VISIT(state->Decomptype); Py_VISIT(state->ZlibError); @@ -1390,93 +1532,122 @@ zlib_traverse(PyObject *m, visitproc visit, void *arg) } static void -zlib_free(void *m) +zlib_free(void *mod) { - zlib_clear((PyObject *)m); + zlib_clear((PyObject *)mod); } -static struct PyModuleDef zlibmodule = { - PyModuleDef_HEAD_INIT, - "zlib", - zlib_module_documentation, - sizeof(_zlibstate), - zlib_methods, - NULL, - zlib_traverse, - zlib_clear, - zlib_free, -}; - -PyMODINIT_FUNC -PyInit_zlib(void) +static int +zlib_exec(PyObject *mod) { - PyObject *m, *ver; - m = PyState_FindModule(&zlibmodule); - if (m != NULL) { - Py_INCREF(m); - return m; + zlibstate *state = get_zlib_state(mod); + + state->Comptype = (PyTypeObject *)PyType_FromModuleAndSpec( + mod, &Comptype_spec, NULL); + if (state->Comptype == NULL) { + return -1; } - m = PyModule_Create(&zlibmodule); - if (m == NULL) - return NULL; - PyTypeObject *Comptype = (PyTypeObject *)PyType_FromSpec(&Comptype_spec); - if (Comptype == NULL) - return NULL; - get_zlib_state(m)->Comptype = Comptype; + state->Decomptype = (PyTypeObject *)PyType_FromModuleAndSpec( + mod, &Decomptype_spec, NULL); + if (state->Decomptype == NULL) { + return -1; + } - PyTypeObject *Decomptype = (PyTypeObject *)PyType_FromSpec(&Decomptype_spec); - if (Decomptype == NULL) - return NULL; - get_zlib_state(m)->Decomptype = Decomptype; + state->ZlibError = PyErr_NewException("zlib.error", NULL, NULL); + if (state->ZlibError == NULL) { + return -1; + } - PyObject *ZlibError = PyErr_NewException("zlib.error", NULL, NULL); - if (ZlibError != NULL) { - Py_INCREF(ZlibError); - PyModule_AddObject(m, "error", ZlibError); - get_zlib_state(m)->ZlibError = ZlibError; + Py_INCREF(state->ZlibError); + if (PyModule_AddObject(mod, "error", state->ZlibError) < 0) { + Py_DECREF(state->ZlibError); + return -1; } - PyModule_AddIntMacro(m, MAX_WBITS); - PyModule_AddIntMacro(m, DEFLATED); - PyModule_AddIntMacro(m, DEF_MEM_LEVEL); - PyModule_AddIntMacro(m, DEF_BUF_SIZE); + +#define ZLIB_ADD_INT_MACRO(c) \ + do { \ + if ((PyModule_AddIntConstant(mod, #c, c)) < 0) { \ + return -1; \ + } \ + } while(0) + + ZLIB_ADD_INT_MACRO(MAX_WBITS); + ZLIB_ADD_INT_MACRO(DEFLATED); + ZLIB_ADD_INT_MACRO(DEF_MEM_LEVEL); + ZLIB_ADD_INT_MACRO(DEF_BUF_SIZE); // compression levels - PyModule_AddIntMacro(m, Z_NO_COMPRESSION); - PyModule_AddIntMacro(m, Z_BEST_SPEED); - PyModule_AddIntMacro(m, Z_BEST_COMPRESSION); - PyModule_AddIntMacro(m, Z_DEFAULT_COMPRESSION); + ZLIB_ADD_INT_MACRO(Z_NO_COMPRESSION); + ZLIB_ADD_INT_MACRO(Z_BEST_SPEED); + ZLIB_ADD_INT_MACRO(Z_BEST_COMPRESSION); + ZLIB_ADD_INT_MACRO(Z_DEFAULT_COMPRESSION); // compression strategies - PyModule_AddIntMacro(m, Z_FILTERED); - PyModule_AddIntMacro(m, Z_HUFFMAN_ONLY); + ZLIB_ADD_INT_MACRO(Z_FILTERED); + ZLIB_ADD_INT_MACRO(Z_HUFFMAN_ONLY); #ifdef Z_RLE // 1.2.0.1 - PyModule_AddIntMacro(m, Z_RLE); + ZLIB_ADD_INT_MACRO(Z_RLE); #endif #ifdef Z_FIXED // 1.2.2.2 - PyModule_AddIntMacro(m, Z_FIXED); + ZLIB_ADD_INT_MACRO(Z_FIXED); #endif - PyModule_AddIntMacro(m, Z_DEFAULT_STRATEGY); + ZLIB_ADD_INT_MACRO(Z_DEFAULT_STRATEGY); // allowed flush values - PyModule_AddIntMacro(m, Z_NO_FLUSH); - PyModule_AddIntMacro(m, Z_PARTIAL_FLUSH); - PyModule_AddIntMacro(m, Z_SYNC_FLUSH); - PyModule_AddIntMacro(m, Z_FULL_FLUSH); - PyModule_AddIntMacro(m, Z_FINISH); + ZLIB_ADD_INT_MACRO(Z_NO_FLUSH); + ZLIB_ADD_INT_MACRO(Z_PARTIAL_FLUSH); + ZLIB_ADD_INT_MACRO(Z_SYNC_FLUSH); + ZLIB_ADD_INT_MACRO(Z_FULL_FLUSH); + ZLIB_ADD_INT_MACRO(Z_FINISH); #ifdef Z_BLOCK // 1.2.0.5 for inflate, 1.2.3.4 for deflate - PyModule_AddIntMacro(m, Z_BLOCK); + ZLIB_ADD_INT_MACRO(Z_BLOCK); #endif #ifdef Z_TREES // 1.2.3.4, only for inflate - PyModule_AddIntMacro(m, Z_TREES); + ZLIB_ADD_INT_MACRO(Z_TREES); #endif - ver = PyUnicode_FromString(ZLIB_VERSION); - if (ver != NULL) - PyModule_AddObject(m, "ZLIB_VERSION", ver); + PyObject *ver = PyUnicode_FromString(ZLIB_VERSION); + if (ver == NULL) { + return -1; + } + + if (PyModule_AddObject(mod, "ZLIB_VERSION", ver) < 0) { + Py_DECREF(ver); + return -1; + } ver = PyUnicode_FromString(zlibVersion()); - if (ver != NULL) - PyModule_AddObject(m, "ZLIB_RUNTIME_VERSION", ver); + if (ver == NULL) { + return -1; + } + + if (PyModule_AddObject(mod, "ZLIB_RUNTIME_VERSION", ver) < 0) { + Py_DECREF(ver); + return -1; + } - PyModule_AddStringConstant(m, "__version__", "1.0"); + if (PyModule_AddStringConstant(mod, "__version__", "1.0") < 0) { + return -1; + } + return 0; +} + +static PyModuleDef_Slot zlib_slots[] = { + {Py_mod_exec, zlib_exec}, + {0, NULL} +}; - PyState_AddModule(m, &zlibmodule); - return m; +static struct PyModuleDef zlibmodule = { + PyModuleDef_HEAD_INIT, + .m_name = "zlib", + .m_doc = zlib_module_documentation, + .m_size = sizeof(zlibstate), + .m_methods = zlib_methods, + .m_slots = zlib_slots, + .m_traverse = zlib_traverse, + .m_clear = zlib_clear, + .m_free = zlib_free, +}; + +PyMODINIT_FUNC +PyInit_zlib(void) +{ + return PyModuleDef_Init(&zlibmodule); } |