Python-checkins
Threads by month
- ----- 2025 -----
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
January 2025
- 1 participants
- 705 discussions
Jan. 3, 2025
https://github.com/python/cpython/commit/1c9b0204796ddeaee710646871a4404b4c…
commit: 1c9b0204796ddeaee710646871a4404b4cda1f1b
branch: main
author: Bénédikt Tran <10796600+picnixz(a)users.noreply.github.com>
committer: encukou <encukou(a)gmail.com>
date: 2025-01-03T15:36:41+01:00
summary:
gh-111178: fix UBSan failures in `Modules/zlibmodule.c` (GH-128252)
files:
M Modules/zlibmodule.c
diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c
index 78dcce73cdaade..b90665ae7ef64a 100644
--- a/Modules/zlibmodule.c
+++ b/Modules/zlibmodule.c
@@ -221,6 +221,8 @@ typedef struct
PyThread_type_lock lock;
} compobject;
+#define _compobject_CAST(op) ((compobject *)op)
+
static void
zlib_error(zlibstate *state, z_stream zst, int err, const char *msg)
{
@@ -706,7 +708,7 @@ zlib_decompressobj_impl(PyObject *module, int wbits, PyObject *zdict)
static void
Dealloc(compobject *self)
{
- PyObject *type = (PyObject *)Py_TYPE(self);
+ PyTypeObject *type = Py_TYPE(self);
PyThread_free_lock(self->lock);
Py_XDECREF(self->unused_data);
Py_XDECREF(self->unconsumed_tail);
@@ -716,18 +718,20 @@ Dealloc(compobject *self)
}
static void
-Comp_dealloc(compobject *self)
+Comp_dealloc(PyObject *op)
{
+ compobject *self = _compobject_CAST(op);
if (self->is_initialised)
- deflateEnd(&self->zst);
+ (void)deflateEnd(&self->zst);
Dealloc(self);
}
static void
-Decomp_dealloc(compobject *self)
+Decomp_dealloc(PyObject *op)
{
+ compobject *self = _compobject_CAST(op);
if (self->is_initialised)
- inflateEnd(&self->zst);
+ (void)inflateEnd(&self->zst);
Dealloc(self);
}
1
0
Jan. 3, 2025
https://github.com/python/cpython/commit/56430320536a753236aadde59984c3c8f8…
commit: 56430320536a753236aadde59984c3c8f8777aa2
branch: main
author: Bénédikt Tran <10796600+picnixz(a)users.noreply.github.com>
committer: encukou <encukou(a)gmail.com>
date: 2025-01-03T15:35:05+01:00
summary:
gh-111178: fix UBSan failures in `Objects/tupleobject.c` (GH-128251)
fix UBSan failures for `_PyTupleIterObject`
files:
M Objects/tupleobject.c
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index 49977726eadca9..002002eb455556 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -988,26 +988,29 @@ _PyTuple_Resize(PyObject **pv, Py_ssize_t newsize)
/*********************** Tuple Iterator **************************/
+#define _PyTupleIterObject_CAST(op) ((_PyTupleIterObject *)(op))
static void
-tupleiter_dealloc(_PyTupleIterObject *it)
+tupleiter_dealloc(PyObject *self)
{
+ _PyTupleIterObject *it = _PyTupleIterObject_CAST(self);
_PyObject_GC_UNTRACK(it);
Py_XDECREF(it->it_seq);
PyObject_GC_Del(it);
}
static int
-tupleiter_traverse(_PyTupleIterObject *it, visitproc visit, void *arg)
+tupleiter_traverse(PyObject *self, visitproc visit, void *arg)
{
+ _PyTupleIterObject *it = _PyTupleIterObject_CAST(self);
Py_VISIT(it->it_seq);
return 0;
}
static PyObject *
-tupleiter_next(PyObject *obj)
+tupleiter_next(PyObject *self)
{
- _PyTupleIterObject *it = (_PyTupleIterObject *)obj;
+ _PyTupleIterObject *it = _PyTupleIterObject_CAST(self);
PyTupleObject *seq;
PyObject *item;
@@ -1029,8 +1032,9 @@ tupleiter_next(PyObject *obj)
}
static PyObject *
-tupleiter_len(_PyTupleIterObject *it, PyObject *Py_UNUSED(ignored))
+tupleiter_len(PyObject *self, PyObject *Py_UNUSED(ignored))
{
+ _PyTupleIterObject *it = _PyTupleIterObject_CAST(self);
Py_ssize_t len = 0;
if (it->it_seq)
len = PyTuple_GET_SIZE(it->it_seq) - it->it_index;
@@ -1040,13 +1044,14 @@ tupleiter_len(_PyTupleIterObject *it, PyObject *Py_UNUSED(ignored))
PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
static PyObject *
-tupleiter_reduce(_PyTupleIterObject *it, PyObject *Py_UNUSED(ignored))
+tupleiter_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
{
PyObject *iter = _PyEval_GetBuiltin(&_Py_ID(iter));
/* _PyEval_GetBuiltin can invoke arbitrary code,
* call must be before access of iterator pointers.
* see issue #101765 */
+ _PyTupleIterObject *it = _PyTupleIterObject_CAST(self);
if (it->it_seq)
return Py_BuildValue("N(O)n", iter, it->it_seq, it->it_index);
@@ -1055,8 +1060,9 @@ tupleiter_reduce(_PyTupleIterObject *it, PyObject *Py_UNUSED(ignored))
}
static PyObject *
-tupleiter_setstate(_PyTupleIterObject *it, PyObject *state)
+tupleiter_setstate(PyObject *self, PyObject *state)
{
+ _PyTupleIterObject *it = _PyTupleIterObject_CAST(self);
Py_ssize_t index = PyLong_AsSsize_t(state);
if (index == -1 && PyErr_Occurred())
return NULL;
@@ -1074,19 +1080,19 @@ PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
PyDoc_STRVAR(setstate_doc, "Set state information for unpickling.");
static PyMethodDef tupleiter_methods[] = {
- {"__length_hint__", (PyCFunction)tupleiter_len, METH_NOARGS, length_hint_doc},
- {"__reduce__", (PyCFunction)tupleiter_reduce, METH_NOARGS, reduce_doc},
- {"__setstate__", (PyCFunction)tupleiter_setstate, METH_O, setstate_doc},
- {NULL, NULL} /* sentinel */
+ {"__length_hint__", tupleiter_len, METH_NOARGS, length_hint_doc},
+ {"__reduce__", tupleiter_reduce, METH_NOARGS, reduce_doc},
+ {"__setstate__", tupleiter_setstate, METH_O, setstate_doc},
+ {NULL, NULL, 0, NULL} /* sentinel */
};
PyTypeObject PyTupleIter_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"tuple_iterator", /* tp_name */
- sizeof(_PyTupleIterObject), /* tp_basicsize */
+ sizeof(_PyTupleIterObject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
- (destructor)tupleiter_dealloc, /* tp_dealloc */
+ tupleiter_dealloc, /* tp_dealloc */
0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
@@ -1103,7 +1109,7 @@ PyTypeObject PyTupleIter_Type = {
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
0, /* tp_doc */
- (traverseproc)tupleiter_traverse, /* tp_traverse */
+ tupleiter_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
1
0
Jan. 3, 2025
https://github.com/python/cpython/commit/aad5ba4b6aafd3599d1737c3040b171916…
commit: aad5ba4b6aafd3599d1737c3040b1719165e6e52
branch: main
author: Bénédikt Tran <10796600+picnixz(a)users.noreply.github.com>
committer: encukou <encukou(a)gmail.com>
date: 2025-01-03T15:29:41+01:00
summary:
gh-111178: fix UBSan failures in `Objects/enumobject.c` (GH-128246)
* fix UBSan failures for `enumobject`
* fix UBSan failures for `reversedobject`
files:
M Objects/enumobject.c
diff --git a/Objects/enumobject.c b/Objects/enumobject.c
index 556666779d8522..eb8952675269a2 100644
--- a/Objects/enumobject.c
+++ b/Objects/enumobject.c
@@ -23,6 +23,7 @@ typedef struct {
PyObject* one; /* borrowed reference */
} enumobject;
+#define _enumobject_CAST(op) ((enumobject *)(op))
/*[clinic input]
@classmethod
@@ -150,8 +151,9 @@ enumerate_vectorcall(PyObject *type, PyObject *const *args,
}
static void
-enum_dealloc(enumobject *en)
+enum_dealloc(PyObject *op)
{
+ enumobject *en = _enumobject_CAST(op);
PyObject_GC_UnTrack(en);
Py_XDECREF(en->en_sit);
Py_XDECREF(en->en_result);
@@ -160,8 +162,9 @@ enum_dealloc(enumobject *en)
}
static int
-enum_traverse(enumobject *en, visitproc visit, void *arg)
+enum_traverse(PyObject *op, visitproc visit, void *arg)
{
+ enumobject *en = _enumobject_CAST(op);
Py_VISIT(en->en_sit);
Py_VISIT(en->en_result);
Py_VISIT(en->en_longindex);
@@ -220,8 +223,9 @@ enum_next_long(enumobject *en, PyObject* next_item)
}
static PyObject *
-enum_next(enumobject *en)
+enum_next(PyObject *op)
{
+ enumobject *en = _enumobject_CAST(op);
PyObject *next_index;
PyObject *next_item;
PyObject *result = en->en_result;
@@ -270,8 +274,9 @@ enum_next(enumobject *en)
}
static PyObject *
-enum_reduce(enumobject *en, PyObject *Py_UNUSED(ignored))
+enum_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
{
+ enumobject *en = _enumobject_CAST(op);
if (en->en_longindex != NULL)
return Py_BuildValue("O(OO)", Py_TYPE(en), en->en_sit, en->en_longindex);
else
@@ -281,7 +286,7 @@ enum_reduce(enumobject *en, PyObject *Py_UNUSED(ignored))
PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
static PyMethodDef enum_methods[] = {
- {"__reduce__", (PyCFunction)enum_reduce, METH_NOARGS, reduce_doc},
+ {"__reduce__", enum_reduce, METH_NOARGS, reduce_doc},
{"__class_getitem__", Py_GenericAlias,
METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
{NULL, NULL} /* sentinel */
@@ -293,7 +298,7 @@ PyTypeObject PyEnum_Type = {
sizeof(enumobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
- (destructor)enum_dealloc, /* tp_dealloc */
+ enum_dealloc, /* tp_dealloc */
0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
@@ -311,12 +316,12 @@ PyTypeObject PyEnum_Type = {
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */
enum_new__doc__, /* tp_doc */
- (traverseproc)enum_traverse, /* tp_traverse */
+ enum_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
- (iternextfunc)enum_next, /* tp_iternext */
+ enum_next, /* tp_iternext */
enum_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
@@ -329,7 +334,7 @@ PyTypeObject PyEnum_Type = {
PyType_GenericAlloc, /* tp_alloc */
enum_new, /* tp_new */
PyObject_GC_Del, /* tp_free */
- .tp_vectorcall = (vectorcallfunc)enumerate_vectorcall
+ .tp_vectorcall = enumerate_vectorcall
};
/* Reversed Object ***************************************************************/
@@ -340,6 +345,8 @@ typedef struct {
PyObject* seq;
} reversedobject;
+#define _reversedobject_CAST(op) ((reversedobject *)(op))
+
/*[clinic input]
@classmethod
reversed.__new__ as reversed_new
@@ -411,23 +418,26 @@ reversed_vectorcall(PyObject *type, PyObject * const*args,
}
static void
-reversed_dealloc(reversedobject *ro)
+reversed_dealloc(PyObject *op)
{
+ reversedobject *ro = _reversedobject_CAST(op);
PyObject_GC_UnTrack(ro);
Py_XDECREF(ro->seq);
Py_TYPE(ro)->tp_free(ro);
}
static int
-reversed_traverse(reversedobject *ro, visitproc visit, void *arg)
+reversed_traverse(PyObject *op, visitproc visit, void *arg)
{
+ reversedobject *ro = _reversedobject_CAST(op);
Py_VISIT(ro->seq);
return 0;
}
static PyObject *
-reversed_next(reversedobject *ro)
+reversed_next(PyObject *op)
{
+ reversedobject *ro = _reversedobject_CAST(op);
PyObject *item;
Py_ssize_t index = ro->index;
@@ -447,8 +457,9 @@ reversed_next(reversedobject *ro)
}
static PyObject *
-reversed_len(reversedobject *ro, PyObject *Py_UNUSED(ignored))
+reversed_len(PyObject *op, PyObject *Py_UNUSED(ignored))
{
+ reversedobject *ro = _reversedobject_CAST(op);
Py_ssize_t position, seqsize;
if (ro->seq == NULL)
@@ -463,8 +474,9 @@ reversed_len(reversedobject *ro, PyObject *Py_UNUSED(ignored))
PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
static PyObject *
-reversed_reduce(reversedobject *ro, PyObject *Py_UNUSED(ignored))
+reversed_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
{
+ reversedobject *ro = _reversedobject_CAST(op);
if (ro->seq)
return Py_BuildValue("O(O)n", Py_TYPE(ro), ro->seq, ro->index);
else
@@ -472,8 +484,9 @@ reversed_reduce(reversedobject *ro, PyObject *Py_UNUSED(ignored))
}
static PyObject *
-reversed_setstate(reversedobject *ro, PyObject *state)
+reversed_setstate(PyObject *op, PyObject *state)
{
+ reversedobject *ro = _reversedobject_CAST(op);
Py_ssize_t index = PyLong_AsSsize_t(state);
if (index == -1 && PyErr_Occurred())
return NULL;
@@ -493,9 +506,9 @@ reversed_setstate(reversedobject *ro, PyObject *state)
PyDoc_STRVAR(setstate_doc, "Set state information for unpickling.");
static PyMethodDef reversediter_methods[] = {
- {"__length_hint__", (PyCFunction)reversed_len, METH_NOARGS, length_hint_doc},
- {"__reduce__", (PyCFunction)reversed_reduce, METH_NOARGS, reduce_doc},
- {"__setstate__", (PyCFunction)reversed_setstate, METH_O, setstate_doc},
+ {"__length_hint__", reversed_len, METH_NOARGS, length_hint_doc},
+ {"__reduce__", reversed_reduce, METH_NOARGS, reduce_doc},
+ {"__setstate__", reversed_setstate, METH_O, setstate_doc},
{NULL, NULL} /* sentinel */
};
@@ -505,7 +518,7 @@ PyTypeObject PyReversed_Type = {
sizeof(reversedobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
- (destructor)reversed_dealloc, /* tp_dealloc */
+ reversed_dealloc, /* tp_dealloc */
0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
@@ -523,12 +536,12 @@ PyTypeObject PyReversed_Type = {
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */
reversed_new__doc__, /* tp_doc */
- (traverseproc)reversed_traverse,/* tp_traverse */
+ reversed_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
- (iternextfunc)reversed_next, /* tp_iternext */
+ reversed_next, /* tp_iternext */
reversediter_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
@@ -541,5 +554,5 @@ PyTypeObject PyReversed_Type = {
PyType_GenericAlloc, /* tp_alloc */
reversed_new, /* tp_new */
PyObject_GC_Del, /* tp_free */
- .tp_vectorcall = (vectorcallfunc)reversed_vectorcall,
+ .tp_vectorcall = reversed_vectorcall,
};
1
0
[3.12] gh-125674: Doc: Fix type of newfunc first parameter (GH-125675) (#128448)
by erlend-aasland Jan. 3, 2025
by erlend-aasland Jan. 3, 2025
Jan. 3, 2025
https://github.com/python/cpython/commit/d9e199b491a01bfefab3fd61f6de18f4d2…
commit: d9e199b491a01bfefab3fd61f6de18f4d2fcaeb8
branch: 3.12
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: erlend-aasland <erlend.aasland(a)protonmail.com>
date: 2025-01-03T14:13:18Z
summary:
[3.12] gh-125674: Doc: Fix type of newfunc first parameter (GH-125675) (#128448)
(cherry picked from commit 616468b87bc5bcf5a4db688637ef748e1243db8a)
Co-authored-by: Richard Hansen <rhansen(a)rhansen.org>
Co-authored-by: Jelle Zijlstra <jelle.zijlstra(a)gmail.com>
files:
M Doc/c-api/typeobj.rst
diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst
index 9fc3d358371b17..3d27784d4fe21b 100644
--- a/Doc/c-api/typeobj.rst
+++ b/Doc/c-api/typeobj.rst
@@ -355,7 +355,7 @@ slot typedefs
+-----------------------------+-----------------------------+----------------------+
| :c:type:`newfunc` | .. line-block:: | :c:type:`PyObject` * |
| | | |
-| | :c:type:`PyObject` * | |
+| | :c:type:`PyTypeObject` * | |
| | :c:type:`PyObject` * | |
| | :c:type:`PyObject` * | |
+-----------------------------+-----------------------------+----------------------+
@@ -2610,7 +2610,7 @@ Slot Type typedefs
See :c:member:`~PyTypeObject.tp_free`.
-.. c:type:: PyObject *(*newfunc)(PyObject *, PyObject *, PyObject *)
+.. c:type:: PyObject *(*newfunc)(PyTypeObject *, PyObject *, PyObject *)
See :c:member:`~PyTypeObject.tp_new`.
1
0
Jan. 3, 2025
https://github.com/python/cpython/commit/621d4ff35ec099c1626f77955318c0bc1f…
commit: 621d4ff35ec099c1626f77955318c0bc1febc33d
branch: main
author: Bénédikt Tran <10796600+picnixz(a)users.noreply.github.com>
committer: encukou <encukou(a)gmail.com>
date: 2025-01-03T15:12:40+01:00
summary:
gh-111178: fix UBSan failures in `Modules/curses*.c` (GH-128244)
* fix UBSan failures in `_cursesmodule.c`
* fix UBSan failures in `_curses_panel.c`
* suppress an unused return value
files:
M Modules/_curses_panel.c
M Modules/_cursesmodule.c
diff --git a/Modules/_curses_panel.c b/Modules/_curses_panel.c
index bbbb62c9066df0..eecf7a1c8a1e56 100644
--- a/Modules/_curses_panel.c
+++ b/Modules/_curses_panel.c
@@ -62,7 +62,7 @@ _curses_panel_traverse(PyObject *mod, visitproc visit, void *arg)
static void
_curses_panel_free(void *mod)
{
- _curses_panel_clear((PyObject *) mod);
+ (void)_curses_panel_clear((PyObject *)mod);
}
/* Utility Functions */
@@ -101,6 +101,8 @@ typedef struct {
PyCursesWindowObject *wo; /* for reference counts */
} PyCursesPanelObject;
+#define _PyCursesPanelObject_CAST(op) ((PyCursesPanelObject *)(op))
+
/* Some helper functions. The problem is that there's always a window
associated with a panel. To ensure that Python's GC doesn't pull
this window from under our feet we need to keep track of references
@@ -277,9 +279,10 @@ PyCursesPanel_New(_curses_panel_state *state, PANEL *pan,
}
static void
-PyCursesPanel_Dealloc(PyCursesPanelObject *po)
+PyCursesPanel_Dealloc(PyObject *self)
{
PyObject *tp, *obj;
+ PyCursesPanelObject *po = _PyCursesPanelObject_CAST(self);
tp = (PyObject *) Py_TYPE(po);
obj = (PyObject *) panel_userptr(po->pan);
diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c
index 92961af381b9cb..c6835738348ff9 100644
--- a/Modules/_cursesmodule.c
+++ b/Modules/_cursesmodule.c
@@ -187,6 +187,8 @@ get_cursesmodule_state_by_win(PyCursesWindowObject *win)
return get_cursesmodule_state_by_cls(Py_TYPE(win));
}
+#define _PyCursesWindowObject_CAST(op) ((PyCursesWindowObject *)(op))
+
/*[clinic input]
module _curses
class _curses.window "PyCursesWindowObject *" "clinic_state()->window_type"
@@ -654,53 +656,80 @@ class component_converter(CConverter):
PARSESTR - format string for argument parsing
*/
-#define Window_NoArgNoReturnFunction(X) \
- static PyObject *PyCursesWindow_ ## X \
- (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored)) \
- { return PyCursesCheckERR_ForWin(self, X(self->win), # X); }
+#define Window_NoArgNoReturnFunction(X) \
+ static PyObject *PyCursesWindow_ ## X \
+ (PyObject *op, PyObject *Py_UNUSED(ignored)) \
+ { \
+ PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); \
+ int code = X(self->win); \
+ return PyCursesCheckERR_ForWin(self, code, # X); \
+ }
#define Window_NoArgTrueFalseFunction(X) \
static PyObject * PyCursesWindow_ ## X \
- (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored)) \
+ (PyObject *op, PyObject *Py_UNUSED(ignored)) \
{ \
- return PyBool_FromLong(X(self->win)); }
+ PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); \
+ return PyBool_FromLong(X(self->win)); \
+ }
-#define Window_NoArgNoReturnVoidFunction(X) \
- static PyObject * PyCursesWindow_ ## X \
- (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored)) \
- { \
- X(self->win); Py_RETURN_NONE; }
+#define Window_NoArgNoReturnVoidFunction(X) \
+ static PyObject * PyCursesWindow_ ## X \
+ (PyObject *op, PyObject *Py_UNUSED(ignored)) \
+ { \
+ PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); \
+ X(self->win); \
+ Py_RETURN_NONE; \
+ }
#define Window_NoArg2TupleReturnFunction(X, TYPE, ERGSTR) \
static PyObject * PyCursesWindow_ ## X \
- (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored)) \
+ (PyObject *op, PyObject *Py_UNUSED(ignored)) \
{ \
TYPE arg1, arg2; \
- X(self->win,arg1,arg2); return Py_BuildValue(ERGSTR, arg1, arg2); }
+ PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); \
+ X(self->win, arg1, arg2); \
+ return Py_BuildValue(ERGSTR, arg1, arg2); \
+ }
#define Window_OneArgNoReturnVoidFunction(X, TYPE, PARSESTR) \
static PyObject * PyCursesWindow_ ## X \
- (PyCursesWindowObject *self, PyObject *args) \
+ (PyObject *op, PyObject *args) \
{ \
TYPE arg1; \
- if (!PyArg_ParseTuple(args, PARSESTR, &arg1)) return NULL; \
- X(self->win,arg1); Py_RETURN_NONE; }
+ if (!PyArg_ParseTuple(args, PARSESTR, &arg1)) { \
+ return NULL; \
+ } \
+ PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); \
+ X(self->win, arg1); \
+ Py_RETURN_NONE; \
+ }
#define Window_OneArgNoReturnFunction(X, TYPE, PARSESTR) \
static PyObject * PyCursesWindow_ ## X \
- (PyCursesWindowObject *self, PyObject *args) \
+ (PyObject *op, PyObject *args) \
{ \
TYPE arg1; \
- if (!PyArg_ParseTuple(args,PARSESTR, &arg1)) return NULL; \
- return PyCursesCheckERR_ForWin(self, X(self->win, arg1), # X); }
+ if (!PyArg_ParseTuple(args, PARSESTR, &arg1)) { \
+ return NULL; \
+ } \
+ PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); \
+ int code = X(self->win, arg1); \
+ return PyCursesCheckERR_ForWin(self, code, # X); \
+ }
#define Window_TwoArgNoReturnFunction(X, TYPE, PARSESTR) \
static PyObject * PyCursesWindow_ ## X \
- (PyCursesWindowObject *self, PyObject *args) \
+ (PyObject *op, PyObject *args) \
{ \
TYPE arg1, arg2; \
- if (!PyArg_ParseTuple(args,PARSESTR, &arg1, &arg2)) return NULL; \
- return PyCursesCheckERR_ForWin(self, X(self->win, arg1, arg2), # X); }
+ if (!PyArg_ParseTuple(args,PARSESTR, &arg1, &arg2)) { \
+ return NULL; \
+ } \
+ PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); \
+ int code = X(self->win, arg1, arg2); \
+ return PyCursesCheckERR_ForWin(self, code, # X); \
+ }
/* ------------- WINDOW routines --------------- */
@@ -1302,8 +1331,10 @@ the touchline() method so that the contents will be redisplayed by the next
window refresh.
[-clinic start generated code]*/
static PyObject *
-PyCursesWindow_ChgAt(PyCursesWindowObject *self, PyObject *args)
+PyCursesWindow_ChgAt(PyObject *op, PyObject *args)
{
+ PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op);
+
int rtn;
int x, y;
int num = -1;
@@ -1656,8 +1687,10 @@ Read a string from the user, with primitive line editing capacity.
[-clinic start generated code]*/
static PyObject *
-PyCursesWindow_GetStr(PyCursesWindowObject *self, PyObject *args)
+PyCursesWindow_GetStr(PyObject *op, PyObject *args)
{
+ PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op);
+
int x, y, n;
char rtn[1024]; /* This should be big enough.. I hope */
int rtn2;
@@ -1860,8 +1893,10 @@ from the characters. If n is specified, instr() returns a string at most
n characters long (exclusive of the trailing NUL).
[-clinic start generated code]*/
static PyObject *
-PyCursesWindow_InStr(PyCursesWindowObject *self, PyObject *args)
+PyCursesWindow_InStr(PyObject *op, PyObject *args)
{
+ PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op);
+
int x, y, n;
char rtn[1024]; /* This should be big enough.. I hope */
int rtn2;
@@ -2557,14 +2592,17 @@ _curses_window_vline_impl(PyCursesWindowObject *self, int group_left_1,
}
static PyObject *
-PyCursesWindow_get_encoding(PyCursesWindowObject *self, void *closure)
+PyCursesWindow_get_encoding(PyObject *op, void *closure)
{
+ PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op);
return PyUnicode_FromString(self->encoding);
}
static int
-PyCursesWindow_set_encoding(PyCursesWindowObject *self, PyObject *value, void *Py_UNUSED(ignored))
+PyCursesWindow_set_encoding(PyObject *op, PyObject *value, void *Py_UNUSED(ignored))
{
+ PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op);
+
PyObject *ascii;
char *encoding;
@@ -2607,88 +2645,90 @@ static PyMethodDef PyCursesWindow_methods[] = {
_CURSES_WINDOW_ATTRSET_METHODDEF
_CURSES_WINDOW_BKGD_METHODDEF
#ifdef HAVE_CURSES_WCHGAT
- {"chgat", (PyCFunction)PyCursesWindow_ChgAt, METH_VARARGS},
+ {"chgat", PyCursesWindow_ChgAt, METH_VARARGS},
#endif
_CURSES_WINDOW_BKGDSET_METHODDEF
_CURSES_WINDOW_BORDER_METHODDEF
_CURSES_WINDOW_BOX_METHODDEF
- {"clear", (PyCFunction)PyCursesWindow_wclear, METH_NOARGS},
- {"clearok", (PyCFunction)PyCursesWindow_clearok, METH_VARARGS},
- {"clrtobot", (PyCFunction)PyCursesWindow_wclrtobot, METH_NOARGS},
- {"clrtoeol", (PyCFunction)PyCursesWindow_wclrtoeol, METH_NOARGS},
- {"cursyncup", (PyCFunction)PyCursesWindow_wcursyncup, METH_NOARGS},
+ {"clear", PyCursesWindow_wclear, METH_NOARGS},
+ {"clearok", PyCursesWindow_clearok, METH_VARARGS},
+ {"clrtobot", PyCursesWindow_wclrtobot, METH_NOARGS},
+ {"clrtoeol", PyCursesWindow_wclrtoeol, METH_NOARGS},
+ {"cursyncup", PyCursesWindow_wcursyncup, METH_NOARGS},
_CURSES_WINDOW_DELCH_METHODDEF
- {"deleteln", (PyCFunction)PyCursesWindow_wdeleteln, METH_NOARGS},
+ {"deleteln", PyCursesWindow_wdeleteln, METH_NOARGS},
_CURSES_WINDOW_DERWIN_METHODDEF
_CURSES_WINDOW_ECHOCHAR_METHODDEF
_CURSES_WINDOW_ENCLOSE_METHODDEF
- {"erase", (PyCFunction)PyCursesWindow_werase, METH_NOARGS},
- {"getbegyx", (PyCFunction)PyCursesWindow_getbegyx, METH_NOARGS},
+ {"erase", PyCursesWindow_werase, METH_NOARGS},
+ {"getbegyx", PyCursesWindow_getbegyx, METH_NOARGS},
_CURSES_WINDOW_GETBKGD_METHODDEF
_CURSES_WINDOW_GETCH_METHODDEF
_CURSES_WINDOW_GETKEY_METHODDEF
_CURSES_WINDOW_GET_WCH_METHODDEF
- {"getmaxyx", (PyCFunction)PyCursesWindow_getmaxyx, METH_NOARGS},
- {"getparyx", (PyCFunction)PyCursesWindow_getparyx, METH_NOARGS},
- {"getstr", (PyCFunction)PyCursesWindow_GetStr, METH_VARARGS},
- {"getyx", (PyCFunction)PyCursesWindow_getyx, METH_NOARGS},
+ {"getmaxyx", PyCursesWindow_getmaxyx, METH_NOARGS},
+ {"getparyx", PyCursesWindow_getparyx, METH_NOARGS},
+ {"getstr", PyCursesWindow_GetStr, METH_VARARGS},
+ {"getyx", PyCursesWindow_getyx, METH_NOARGS},
_CURSES_WINDOW_HLINE_METHODDEF
- {"idcok", (PyCFunction)PyCursesWindow_idcok, METH_VARARGS},
- {"idlok", (PyCFunction)PyCursesWindow_idlok, METH_VARARGS},
+ {"idcok", PyCursesWindow_idcok, METH_VARARGS},
+ {"idlok", PyCursesWindow_idlok, METH_VARARGS},
#ifdef HAVE_CURSES_IMMEDOK
- {"immedok", (PyCFunction)PyCursesWindow_immedok, METH_VARARGS},
+ {"immedok", PyCursesWindow_immedok, METH_VARARGS},
#endif
_CURSES_WINDOW_INCH_METHODDEF
_CURSES_WINDOW_INSCH_METHODDEF
- {"insdelln", (PyCFunction)PyCursesWindow_winsdelln, METH_VARARGS},
- {"insertln", (PyCFunction)PyCursesWindow_winsertln, METH_NOARGS},
+ {"insdelln", PyCursesWindow_winsdelln, METH_VARARGS},
+ {"insertln", PyCursesWindow_winsertln, METH_NOARGS},
_CURSES_WINDOW_INSNSTR_METHODDEF
_CURSES_WINDOW_INSSTR_METHODDEF
- {"instr", (PyCFunction)PyCursesWindow_InStr, METH_VARARGS},
+ {"instr", PyCursesWindow_InStr, METH_VARARGS},
_CURSES_WINDOW_IS_LINETOUCHED_METHODDEF
- {"is_wintouched", (PyCFunction)PyCursesWindow_is_wintouched, METH_NOARGS},
- {"keypad", (PyCFunction)PyCursesWindow_keypad, METH_VARARGS},
- {"leaveok", (PyCFunction)PyCursesWindow_leaveok, METH_VARARGS},
- {"move", (PyCFunction)PyCursesWindow_wmove, METH_VARARGS},
- {"mvderwin", (PyCFunction)PyCursesWindow_mvderwin, METH_VARARGS},
- {"mvwin", (PyCFunction)PyCursesWindow_mvwin, METH_VARARGS},
- {"nodelay", (PyCFunction)PyCursesWindow_nodelay, METH_VARARGS},
- {"notimeout", (PyCFunction)PyCursesWindow_notimeout, METH_VARARGS},
+ {"is_wintouched", PyCursesWindow_is_wintouched, METH_NOARGS},
+ {"keypad", PyCursesWindow_keypad, METH_VARARGS},
+ {"leaveok", PyCursesWindow_leaveok, METH_VARARGS},
+ {"move", PyCursesWindow_wmove, METH_VARARGS},
+ {"mvderwin", PyCursesWindow_mvderwin, METH_VARARGS},
+ {"mvwin", PyCursesWindow_mvwin, METH_VARARGS},
+ {"nodelay", PyCursesWindow_nodelay, METH_VARARGS},
+ {"notimeout", PyCursesWindow_notimeout, METH_VARARGS},
_CURSES_WINDOW_NOUTREFRESH_METHODDEF
_CURSES_WINDOW_OVERLAY_METHODDEF
_CURSES_WINDOW_OVERWRITE_METHODDEF
_CURSES_WINDOW_PUTWIN_METHODDEF
_CURSES_WINDOW_REDRAWLN_METHODDEF
- {"redrawwin", (PyCFunction)PyCursesWindow_redrawwin, METH_NOARGS},
+ {"redrawwin", PyCursesWindow_redrawwin, METH_NOARGS},
_CURSES_WINDOW_REFRESH_METHODDEF
#ifndef STRICT_SYSV_CURSES
- {"resize", (PyCFunction)PyCursesWindow_wresize, METH_VARARGS},
+ {"resize", PyCursesWindow_wresize, METH_VARARGS},
#endif
_CURSES_WINDOW_SCROLL_METHODDEF
- {"scrollok", (PyCFunction)PyCursesWindow_scrollok, METH_VARARGS},
+ {"scrollok", PyCursesWindow_scrollok, METH_VARARGS},
_CURSES_WINDOW_SETSCRREG_METHODDEF
- {"standend", (PyCFunction)PyCursesWindow_wstandend, METH_NOARGS},
- {"standout", (PyCFunction)PyCursesWindow_wstandout, METH_NOARGS},
+ {"standend", PyCursesWindow_wstandend, METH_NOARGS},
+ {"standout", PyCursesWindow_wstandout, METH_NOARGS},
{"subpad", (PyCFunction)_curses_window_subwin, METH_VARARGS, _curses_window_subwin__doc__},
_CURSES_WINDOW_SUBWIN_METHODDEF
- {"syncdown", (PyCFunction)PyCursesWindow_wsyncdown, METH_NOARGS},
+ {"syncdown", PyCursesWindow_wsyncdown, METH_NOARGS},
#ifdef HAVE_CURSES_SYNCOK
- {"syncok", (PyCFunction)PyCursesWindow_syncok, METH_VARARGS},
+ {"syncok", PyCursesWindow_syncok, METH_VARARGS},
#endif
- {"syncup", (PyCFunction)PyCursesWindow_wsyncup, METH_NOARGS},
- {"timeout", (PyCFunction)PyCursesWindow_wtimeout, METH_VARARGS},
+ {"syncup", PyCursesWindow_wsyncup, METH_NOARGS},
+ {"timeout", PyCursesWindow_wtimeout, METH_VARARGS},
_CURSES_WINDOW_TOUCHLINE_METHODDEF
- {"touchwin", (PyCFunction)PyCursesWindow_touchwin, METH_NOARGS},
- {"untouchwin", (PyCFunction)PyCursesWindow_untouchwin, METH_NOARGS},
+ {"touchwin", PyCursesWindow_touchwin, METH_NOARGS},
+ {"untouchwin", PyCursesWindow_untouchwin, METH_NOARGS},
_CURSES_WINDOW_VLINE_METHODDEF
{NULL, NULL} /* sentinel */
};
static PyGetSetDef PyCursesWindow_getsets[] = {
- {"encoding",
- (getter)PyCursesWindow_get_encoding,
- (setter)PyCursesWindow_set_encoding,
- "the typecode character used to create the array"},
+ {
+ "encoding",
+ PyCursesWindow_get_encoding,
+ PyCursesWindow_set_encoding,
+ "the typecode character used to create the array"
+ },
{NULL, NULL, NULL, NULL } /* sentinel */
};
1
0
[3.13] gh-125674: Doc: Fix type of newfunc first parameter (GH-125675) (#128449)
by erlend-aasland Jan. 3, 2025
by erlend-aasland Jan. 3, 2025
Jan. 3, 2025
https://github.com/python/cpython/commit/f8b24cdbb91b1905725ea58271519772c6…
commit: f8b24cdbb91b1905725ea58271519772c6a41d86
branch: 3.13
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: erlend-aasland <erlend.aasland(a)protonmail.com>
date: 2025-01-03T14:12:24Z
summary:
[3.13] gh-125674: Doc: Fix type of newfunc first parameter (GH-125675) (#128449)
(cherry picked from commit 616468b87bc5bcf5a4db688637ef748e1243db8a)
Co-authored-by: Richard Hansen <rhansen(a)rhansen.org>
Co-authored-by: Jelle Zijlstra <jelle.zijlstra(a)gmail.com>
files:
M Doc/c-api/typeobj.rst
diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst
index e5a718912e3cef..34dbc699fa1c20 100644
--- a/Doc/c-api/typeobj.rst
+++ b/Doc/c-api/typeobj.rst
@@ -355,7 +355,7 @@ slot typedefs
+-----------------------------+-----------------------------+----------------------+
| :c:type:`newfunc` | .. line-block:: | :c:type:`PyObject` * |
| | | |
-| | :c:type:`PyObject` * | |
+| | :c:type:`PyTypeObject` * | |
| | :c:type:`PyObject` * | |
| | :c:type:`PyObject` * | |
+-----------------------------+-----------------------------+----------------------+
@@ -2618,7 +2618,7 @@ Slot Type typedefs
See :c:member:`~PyTypeObject.tp_free`.
-.. c:type:: PyObject *(*newfunc)(PyObject *, PyObject *, PyObject *)
+.. c:type:: PyObject *(*newfunc)(PyTypeObject *, PyObject *, PyObject *)
See :c:member:`~PyTypeObject.tp_new`.
1
0
https://github.com/python/cpython/commit/8522f8bacb4e2db4b901472c254efad605…
commit: 8522f8bacb4e2db4b901472c254efad6057e9fd1
branch: main
author: Bénédikt Tran <10796600+picnixz(a)users.noreply.github.com>
committer: encukou <encukou(a)gmail.com>
date: 2025-01-03T15:04:33+01:00
summary:
gh-111178: fix UBSan failures in `Modules/_csv.c` (GH-128243)
Also: suppress unused return values
files:
M Modules/_csv.c
diff --git a/Modules/_csv.c b/Modules/_csv.c
index 1a4dc3f1f55ace..7ca30e39e00c0c 100644
--- a/Modules/_csv.c
+++ b/Modules/_csv.c
@@ -77,7 +77,7 @@ _csv_traverse(PyObject *module, visitproc visit, void *arg)
static void
_csv_free(void *module)
{
- _csv_clear((PyObject *)module);
+ (void)_csv_clear((PyObject *)module);
}
typedef enum {
@@ -151,6 +151,10 @@ typedef struct {
PyObject *error_obj; /* cached error object */
} WriterObj;
+#define _DialectObj_CAST(op) ((DialectObj *)(op))
+#define _ReaderObj_CAST(op) ((ReaderObj *)(op))
+#define _WriterObj_CAST(op) ((WriterObj *)(op))
+
/*
* DIALECT class
*/
@@ -176,32 +180,37 @@ get_char_or_None(Py_UCS4 c)
}
static PyObject *
-Dialect_get_lineterminator(DialectObj *self, void *Py_UNUSED(ignored))
+Dialect_get_lineterminator(PyObject *op, void *Py_UNUSED(ignored))
{
+ DialectObj *self = _DialectObj_CAST(op);
return Py_XNewRef(self->lineterminator);
}
static PyObject *
-Dialect_get_delimiter(DialectObj *self, void *Py_UNUSED(ignored))
+Dialect_get_delimiter(PyObject *op, void *Py_UNUSED(ignored))
{
+ DialectObj *self = _DialectObj_CAST(op);
return get_char_or_None(self->delimiter);
}
static PyObject *
-Dialect_get_escapechar(DialectObj *self, void *Py_UNUSED(ignored))
+Dialect_get_escapechar(PyObject *op, void *Py_UNUSED(ignored))
{
+ DialectObj *self = _DialectObj_CAST(op);
return get_char_or_None(self->escapechar);
}
static PyObject *
-Dialect_get_quotechar(DialectObj *self, void *Py_UNUSED(ignored))
+Dialect_get_quotechar(PyObject *op, void *Py_UNUSED(ignored))
{
+ DialectObj *self = _DialectObj_CAST(op);
return get_char_or_None(self->quotechar);
}
static PyObject *
-Dialect_get_quoting(DialectObj *self, void *Py_UNUSED(ignored))
+Dialect_get_quoting(PyObject *op, void *Py_UNUSED(ignored))
{
+ DialectObj *self = _DialectObj_CAST(op);
return PyLong_FromLong(self->quoting);
}
@@ -371,16 +380,16 @@ static struct PyMemberDef Dialect_memberlist[] = {
#undef D_OFF
static PyGetSetDef Dialect_getsetlist[] = {
- { "delimiter", (getter)Dialect_get_delimiter},
- { "escapechar", (getter)Dialect_get_escapechar},
- { "lineterminator", (getter)Dialect_get_lineterminator},
- { "quotechar", (getter)Dialect_get_quotechar},
- { "quoting", (getter)Dialect_get_quoting},
+ {"delimiter", Dialect_get_delimiter},
+ {"escapechar", Dialect_get_escapechar},
+ {"lineterminator", Dialect_get_lineterminator},
+ {"quotechar", Dialect_get_quotechar},
+ {"quoting", Dialect_get_quoting},
{NULL},
};
static void
-Dialect_dealloc(DialectObj *self)
+Dialect_dealloc(PyObject *self)
{
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
@@ -594,15 +603,17 @@ PyDoc_STRVAR(Dialect_Type_doc,
"The Dialect type records CSV parsing and generation options.\n");
static int
-Dialect_clear(DialectObj *self)
+Dialect_clear(PyObject *op)
{
+ DialectObj *self = _DialectObj_CAST(op);
Py_CLEAR(self->lineterminator);
return 0;
}
static int
-Dialect_traverse(DialectObj *self, visitproc visit, void *arg)
+Dialect_traverse(PyObject *op, visitproc visit, void *arg)
{
+ DialectObj *self = _DialectObj_CAST(op);
Py_VISIT(self->lineterminator);
Py_VISIT(Py_TYPE(self));
return 0;
@@ -916,8 +927,10 @@ parse_reset(ReaderObj *self)
}
static PyObject *
-Reader_iternext(ReaderObj *self)
+Reader_iternext(PyObject *op)
{
+ ReaderObj *self = _ReaderObj_CAST(op);
+
PyObject *fields = NULL;
Py_UCS4 c;
Py_ssize_t pos, linelen;
@@ -982,11 +995,12 @@ Reader_iternext(ReaderObj *self)
}
static void
-Reader_dealloc(ReaderObj *self)
+Reader_dealloc(PyObject *op)
{
+ ReaderObj *self = _ReaderObj_CAST(op);
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
- tp->tp_clear((PyObject *)self);
+ (void)tp->tp_clear(op);
if (self->field != NULL) {
PyMem_Free(self->field);
self->field = NULL;
@@ -996,8 +1010,9 @@ Reader_dealloc(ReaderObj *self)
}
static int
-Reader_traverse(ReaderObj *self, visitproc visit, void *arg)
+Reader_traverse(PyObject *op, visitproc visit, void *arg)
{
+ ReaderObj *self = _ReaderObj_CAST(op);
Py_VISIT(self->dialect);
Py_VISIT(self->input_iter);
Py_VISIT(self->fields);
@@ -1006,8 +1021,9 @@ Reader_traverse(ReaderObj *self, visitproc visit, void *arg)
}
static int
-Reader_clear(ReaderObj *self)
+Reader_clear(PyObject *op)
{
+ ReaderObj *self = _ReaderObj_CAST(op);
Py_CLEAR(self->dialect);
Py_CLEAR(self->input_iter);
Py_CLEAR(self->fields);
@@ -1303,8 +1319,9 @@ PyDoc_STRVAR(csv_writerow_doc,
"elements will be converted to string.");
static PyObject *
-csv_writerow(WriterObj *self, PyObject *seq)
+csv_writerow(PyObject *op, PyObject *seq)
{
+ WriterObj *self = _WriterObj_CAST(op);
DialectObj *dialect = self->dialect;
PyObject *iter, *field, *line, *result;
bool null_field = false;
@@ -1412,7 +1429,7 @@ PyDoc_STRVAR(csv_writerows_doc,
"elements will be converted to string.");
static PyObject *
-csv_writerows(WriterObj *self, PyObject *seqseq)
+csv_writerows(PyObject *self, PyObject *seqseq)
{
PyObject *row_iter, *row_obj, *result;
@@ -1437,9 +1454,9 @@ csv_writerows(WriterObj *self, PyObject *seqseq)
}
static struct PyMethodDef Writer_methods[] = {
- { "writerow", (PyCFunction)csv_writerow, METH_O, csv_writerow_doc},
- { "writerows", (PyCFunction)csv_writerows, METH_O, csv_writerows_doc},
- { NULL, NULL }
+ {"writerow", csv_writerow, METH_O, csv_writerow_doc},
+ {"writerows", csv_writerows, METH_O, csv_writerows_doc},
+ {NULL, NULL, 0, NULL} /* sentinel */
};
#define W_OFF(x) offsetof(WriterObj, x)
@@ -1452,8 +1469,9 @@ static struct PyMemberDef Writer_memberlist[] = {
#undef W_OFF
static int
-Writer_traverse(WriterObj *self, visitproc visit, void *arg)
+Writer_traverse(PyObject *op, visitproc visit, void *arg)
{
+ WriterObj *self = _WriterObj_CAST(op);
Py_VISIT(self->dialect);
Py_VISIT(self->write);
Py_VISIT(self->error_obj);
@@ -1462,8 +1480,9 @@ Writer_traverse(WriterObj *self, visitproc visit, void *arg)
}
static int
-Writer_clear(WriterObj *self)
+Writer_clear(PyObject *op)
{
+ WriterObj *self = _WriterObj_CAST(op);
Py_CLEAR(self->dialect);
Py_CLEAR(self->write);
Py_CLEAR(self->error_obj);
@@ -1471,11 +1490,12 @@ Writer_clear(WriterObj *self)
}
static void
-Writer_dealloc(WriterObj *self)
+Writer_dealloc(PyObject *op)
{
+ WriterObj *self = _WriterObj_CAST(op);
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
- tp->tp_clear((PyObject *)self);
+ tp->tp_clear(op);
if (self->rec != NULL) {
PyMem_Free(self->rec);
}
1
0
https://github.com/python/cpython/commit/b4f799b1e78ede17b41de9a2bc51b437a7…
commit: b4f799b1e78ede17b41de9a2bc51b437a7e6dd74
branch: main
author: Rian Hunter <rianhunter(a)users.noreply.github.com>
committer: encukou <encukou(a)gmail.com>
date: 2025-01-03T14:07:07+01:00
summary:
gh-112015: Implement `ctypes.memoryview_at()` (GH-112018)
Co-authored-by: Serhiy Storchaka <storchaka(a)gmail.com>
Co-authored-by: Petr Viktorin <encukou(a)gmail.com>
Co-authored-by: Bénédikt Tran <10796600+picnixz(a)users.noreply.github.com>
files:
A Misc/NEWS.d/next/Library/2023-11-12-21-53-40.gh-issue-112015.2WPRxE.rst
M Doc/library/ctypes.rst
M Doc/whatsnew/3.14.rst
M Lib/ctypes/__init__.py
M Lib/test/test_ctypes/test_memfunctions.py
M Modules/_ctypes/_ctypes.c
diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst
index 09692e56d29a39..398cb92bac809a 100644
--- a/Doc/library/ctypes.rst
+++ b/Doc/library/ctypes.rst
@@ -2182,6 +2182,28 @@ Utility functions
.. audit-event:: ctypes.wstring_at ptr,size ctypes.wstring_at
+.. function:: memoryview_at(ptr, size, readonly=False)
+
+ Return a :class:`memoryview` object of length *size* that references memory
+ starting at *void \*ptr*.
+
+ If *readonly* is true, the returned :class:`!memoryview` object can
+ not be used to modify the underlying memory.
+ (Changes made by other means will still be reflected in the returned
+ object.)
+
+ This function is similar to :func:`string_at` with the key
+ difference of not making a copy of the specified memory.
+ It is a semantically equivalent (but more efficient) alternative to
+ ``memoryview((c_byte * size).from_address(ptr))``.
+ (While :meth:`~_CData.from_address` only takes integers, *ptr* can also
+ be given as a :class:`ctypes.POINTER` or a :func:`~ctypes.byref` object.)
+
+ .. audit-event:: ctypes.memoryview_at address,size,readonly
+
+ .. versionadded:: next
+
+
.. _ctypes-data-types:
Data types
diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index cb9167300260cb..f365db37217e95 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -343,6 +343,14 @@ ctypes
* On Windows, the :func:`~ctypes.CopyComPointer` function is now public.
(Contributed by Jun Komoda in :gh:`127275`.)
+* :func:`ctypes.memoryview_at` now exists to create a
+ :class:`memoryview` object that refers to the supplied pointer and
+ length. This works like :func:`ctypes.string_at` except it avoids a
+ buffer copy, and is typically useful when implementing pure Python
+ callback functions that are passed dynamically-sized buffers.
+ (Contributed by Rian Hunter in :gh:`112018`.)
+
+
datetime
--------
diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py
index 2f2b0ca9f38633..8e2a2926f7a853 100644
--- a/Lib/ctypes/__init__.py
+++ b/Lib/ctypes/__init__.py
@@ -524,6 +524,7 @@ def WinError(code=None, descr=None):
# functions
from _ctypes import _memmove_addr, _memset_addr, _string_at_addr, _cast_addr
+from _ctypes import _memoryview_at_addr
## void *memmove(void *, const void *, size_t);
memmove = CFUNCTYPE(c_void_p, c_void_p, c_void_p, c_size_t)(_memmove_addr)
@@ -549,6 +550,14 @@ def string_at(ptr, size=-1):
Return the byte string at void *ptr."""
return _string_at(ptr, size)
+_memoryview_at = PYFUNCTYPE(
+ py_object, c_void_p, c_ssize_t, c_int)(_memoryview_at_addr)
+def memoryview_at(ptr, size, readonly=False):
+ """memoryview_at(ptr, size[, readonly]) -> memoryview
+
+ Return a memoryview representing the memory at void *ptr."""
+ return _memoryview_at(ptr, size, bool(readonly))
+
try:
from _ctypes import _wstring_at_addr
except ImportError:
diff --git a/Lib/test/test_ctypes/test_memfunctions.py b/Lib/test/test_ctypes/test_memfunctions.py
index 112b27ba48e07e..325487618137f6 100644
--- a/Lib/test/test_ctypes/test_memfunctions.py
+++ b/Lib/test/test_ctypes/test_memfunctions.py
@@ -5,7 +5,9 @@
create_string_buffer, string_at,
create_unicode_buffer, wstring_at,
memmove, memset,
- c_char_p, c_byte, c_ubyte, c_wchar)
+ memoryview_at, c_void_p,
+ c_char_p, c_byte, c_ubyte, c_wchar,
+ addressof, byref)
class MemFunctionsTest(unittest.TestCase):
@@ -77,6 +79,62 @@ def test_wstring_at(self):
self.assertEqual(wstring_at(a, 16), "Hello, World\0\0\0\0")
self.assertEqual(wstring_at(a, 0), "")
+ def test_memoryview_at(self):
+ b = (c_byte * 10)()
+
+ size = len(b)
+ for foreign_ptr in (
+ b,
+ cast(b, c_void_p),
+ byref(b),
+ addressof(b),
+ ):
+ with self.subTest(foreign_ptr=type(foreign_ptr).__name__):
+ b[:] = b"initialval"
+ v = memoryview_at(foreign_ptr, size)
+ self.assertIsInstance(v, memoryview)
+ self.assertEqual(bytes(v), b"initialval")
+
+ # test that writes to source buffer get reflected in memoryview
+ b[:] = b"0123456789"
+ self.assertEqual(bytes(v), b"0123456789")
+
+ # test that writes to memoryview get reflected in source buffer
+ v[:] = b"9876543210"
+ self.assertEqual(bytes(b), b"9876543210")
+
+ with self.assertRaises(ValueError):
+ memoryview_at(foreign_ptr, -1)
+
+ with self.assertRaises(ValueError):
+ memoryview_at(foreign_ptr, sys.maxsize + 1)
+
+ v0 = memoryview_at(foreign_ptr, 0)
+ self.assertEqual(bytes(v0), b'')
+
+ def test_memoryview_at_readonly(self):
+ b = (c_byte * 10)()
+
+ size = len(b)
+ for foreign_ptr in (
+ b,
+ cast(b, c_void_p),
+ byref(b),
+ addressof(b),
+ ):
+ with self.subTest(foreign_ptr=type(foreign_ptr).__name__):
+ b[:] = b"initialval"
+ v = memoryview_at(foreign_ptr, size, readonly=True)
+ self.assertIsInstance(v, memoryview)
+ self.assertEqual(bytes(v), b"initialval")
+
+ # test that writes to source buffer get reflected in memoryview
+ b[:] = b"0123456789"
+ self.assertEqual(bytes(v), b"0123456789")
+
+ # test that writes to the memoryview are blocked
+ with self.assertRaises(TypeError):
+ v[:] = b"9876543210"
if __name__ == "__main__":
unittest.main()
diff --git a/Misc/NEWS.d/next/Library/2023-11-12-21-53-40.gh-issue-112015.2WPRxE.rst b/Misc/NEWS.d/next/Library/2023-11-12-21-53-40.gh-issue-112015.2WPRxE.rst
new file mode 100644
index 00000000000000..4b58ec9d219eff
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-11-12-21-53-40.gh-issue-112015.2WPRxE.rst
@@ -0,0 +1,5 @@
+:func:`ctypes.memoryview_at` now exists to create a
+:class:`memoryview` object that refers to the supplied pointer and
+length. This works like :func:`ctypes.string_at` except it avoids a
+buffer copy, and is typically useful when implementing pure Python
+callback functions that are passed dynamically-sized buffers.
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
index ac520ffaad6c90..ede95bdf98bf76 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -5791,6 +5791,22 @@ wstring_at(const wchar_t *ptr, int size)
return PyUnicode_FromWideChar(ptr, ssize);
}
+static PyObject *
+memoryview_at(void *ptr, Py_ssize_t size, int readonly)
+{
+ if (PySys_Audit("ctypes.memoryview_at", "nni",
+ (Py_ssize_t)ptr, size, readonly) < 0) {
+ return NULL;
+ }
+ if (size < 0) {
+ PyErr_Format(PyExc_ValueError,
+ "memoryview_at: size is negative (or overflowed): %zd",
+ size);
+ return NULL;
+ }
+ return PyMemoryView_FromMemory(ptr, size,
+ readonly ? PyBUF_READ : PyBUF_WRITE);
+}
static int
_ctypes_add_types(PyObject *mod)
@@ -5919,6 +5935,7 @@ _ctypes_add_objects(PyObject *mod)
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));
+ MOD_ADD("_memoryview_at_addr", PyLong_FromVoidPtr(memoryview_at));
/* If RTLD_LOCAL is not defined (Windows!), set it to zero. */
#if !HAVE_DECL_RTLD_LOCAL
1
0
Jan. 3, 2025
https://github.com/python/cpython/commit/f21af186bf21c1c554209ac67d78d3cf99…
commit: f21af186bf21c1c554209ac67d78d3cf99f7d7c0
branch: main
author: Hugo van Kemenade <1324225+hugovk(a)users.noreply.github.com>
committer: hugovk <1324225+hugovk(a)users.noreply.github.com>
date: 2025-01-03T14:56:24+02:00
summary:
gh-128317: Highlight today in colour in calendar CLI output (#128318)
Co-authored-by: Peter Bierma <zintensitydev(a)gmail.com>
files:
A Misc/NEWS.d/next/Library/2024-12-29-00-33-34.gh-issue-128317.WgFina.rst
M Doc/library/calendar.rst
M Doc/whatsnew/3.14.rst
M Lib/_colorize.py
M Lib/calendar.py
diff --git a/Doc/library/calendar.rst b/Doc/library/calendar.rst
index 97ca34b6c6184c..ace8529d6e7e0c 100644
--- a/Doc/library/calendar.rst
+++ b/Doc/library/calendar.rst
@@ -146,26 +146,34 @@ interpreted as prescribed by the ISO 8601 standard. Year 0 is 1 BC, year -1 is
the specified width, representing an empty day. The *weekday* parameter
is unused.
- .. method:: formatweek(theweek, w=0)
+ .. method:: formatweek(theweek, w=0, highlight_day=None)
Return a single week in a string with no newline. If *w* is provided, it
specifies the width of the date columns, which are centered. Depends
on the first weekday as specified in the constructor or set by the
:meth:`setfirstweekday` method.
+ .. versionchanged:: next
+ If *highlight_day* is given, this date is highlighted in color.
+ This can be :ref:`controlled using environment variables
+ <using-on-controlling-color>`.
+
+
.. method:: formatweekday(weekday, width)
Return a string representing the name of a single weekday formatted to
the specified *width*. The *weekday* parameter is an integer representing
the day of the week, where ``0`` is Monday and ``6`` is Sunday.
+
.. method:: formatweekheader(width)
Return a string containing the header row of weekday names, formatted
with the given *width* for each column. The names depend on the locale
settings and are padded to the specified width.
- .. method:: formatmonth(theyear, themonth, w=0, l=0)
+
+ .. method:: formatmonth(theyear, themonth, w=0, l=0, highlight_day=None)
Return a month's calendar in a multi-line string. If *w* is provided, it
specifies the width of the date columns, which are centered. If *l* is
@@ -173,6 +181,12 @@ interpreted as prescribed by the ISO 8601 standard. Year 0 is 1 BC, year -1 is
on the first weekday as specified in the constructor or set by the
:meth:`setfirstweekday` method.
+ .. versionchanged:: next
+ If *highlight_day* is given, this date is highlighted in color.
+ This can be :ref:`controlled using environment variables
+ <using-on-controlling-color>`.
+
+
.. method:: formatmonthname(theyear, themonth, width=0, withyear=True)
Return a string representing the month's name centered within the
@@ -180,12 +194,13 @@ interpreted as prescribed by the ISO 8601 standard. Year 0 is 1 BC, year -1 is
output. The *theyear* and *themonth* parameters specify the year
and month for the name to be formatted respectively.
+
.. method:: prmonth(theyear, themonth, w=0, l=0)
Print a month's calendar as returned by :meth:`formatmonth`.
- .. method:: formatyear(theyear, w=2, l=1, c=6, m=3)
+ .. method:: formatyear(theyear, w=2, l=1, c=6, m=3, highlight_day=None)
Return a *m*-column calendar for an entire year as a multi-line string.
Optional parameters *w*, *l*, and *c* are for date column width, lines per
@@ -194,6 +209,11 @@ interpreted as prescribed by the ISO 8601 standard. Year 0 is 1 BC, year -1 is
:meth:`setfirstweekday` method. The earliest year for which a calendar
can be generated is platform-dependent.
+ .. versionchanged:: next
+ If *highlight_day* is given, this date is highlighted in color.
+ This can be :ref:`controlled using environment variables
+ <using-on-controlling-color>`.
+
.. method:: pryear(theyear, w=2, l=1, c=6, m=3)
@@ -549,7 +569,7 @@ The :mod:`calendar` module defines the following exceptions:
.. _calendar-cli:
-Command-Line Usage
+Command-line usage
------------------
.. versionadded:: 2.5
@@ -687,6 +707,9 @@ The following options are accepted:
The number of months printed per row.
Defaults to 3.
+.. versionchanged:: next
+ By default, today's date is highlighted in color and can be
+ :ref:`controlled using environment variables <using-on-controlling-color>`.
*HTML-mode options:*
diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index 69c356ba60e6d4..cb9167300260cb 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -296,6 +296,19 @@ ast
* The ``repr()`` output for AST nodes now includes more information.
(Contributed by Tomas R in :gh:`116022`.)
+
+calendar
+--------
+
+* By default, today's date is highlighted in color in :mod:`calendar`'s
+ :ref:`command-line <calendar-cli>` text output.
+ This can be controlled via the :envvar:`PYTHON_COLORS` environment
+ variable as well as the canonical |NO_COLOR|_
+ and |FORCE_COLOR|_ environment variables.
+ See also :ref:`using-on-controlling-color`.
+ (Contributed by Hugo van Kemenade in :gh:`128317`.)
+
+
concurrent.futures
------------------
diff --git a/Lib/_colorize.py b/Lib/_colorize.py
index 709081e25ec59b..f609901887a26b 100644
--- a/Lib/_colorize.py
+++ b/Lib/_colorize.py
@@ -6,9 +6,11 @@
class ANSIColors:
+ BACKGROUND_YELLOW = "\x1b[43m"
BOLD_GREEN = "\x1b[1;32m"
BOLD_MAGENTA = "\x1b[1;35m"
BOLD_RED = "\x1b[1;31m"
+ BLACK = "\x1b[30m"
GREEN = "\x1b[32m"
GREY = "\x1b[90m"
MAGENTA = "\x1b[35m"
diff --git a/Lib/calendar.py b/Lib/calendar.py
index 8c1c646da46a98..d2e5e08d02dbb9 100644
--- a/Lib/calendar.py
+++ b/Lib/calendar.py
@@ -349,11 +349,27 @@ def formatday(self, day, weekday, width):
s = '%2i' % day # right-align single-digit days
return s.center(width)
- def formatweek(self, theweek, width):
+ def formatweek(self, theweek, width, *, highlight_day=None):
"""
Returns a single week in a string (no newline).
"""
- return ' '.join(self.formatday(d, wd, width) for (d, wd) in theweek)
+ if highlight_day:
+ from _colorize import get_colors
+
+ ansi = get_colors()
+ highlight = f"{ansi.BLACK}{ansi.BACKGROUND_YELLOW}"
+ reset = ansi.RESET
+ else:
+ highlight = reset = ""
+
+ return ' '.join(
+ (
+ f"{highlight}{self.formatday(d, wd, width)}{reset}"
+ if d == highlight_day
+ else self.formatday(d, wd, width)
+ )
+ for (d, wd) in theweek
+ )
def formatweekday(self, day, width):
"""
@@ -388,10 +404,11 @@ def prmonth(self, theyear, themonth, w=0, l=0):
"""
print(self.formatmonth(theyear, themonth, w, l), end='')
- def formatmonth(self, theyear, themonth, w=0, l=0):
+ def formatmonth(self, theyear, themonth, w=0, l=0, *, highlight_day=None):
"""
Return a month's calendar string (multi-line).
"""
+ highlight_day = highlight_day.day if highlight_day else None
w = max(2, w)
l = max(1, l)
s = self.formatmonthname(theyear, themonth, 7 * (w + 1) - 1)
@@ -400,11 +417,11 @@ def formatmonth(self, theyear, themonth, w=0, l=0):
s += self.formatweekheader(w).rstrip()
s += '\n' * l
for week in self.monthdays2calendar(theyear, themonth):
- s += self.formatweek(week, w).rstrip()
+ s += self.formatweek(week, w, highlight_day=highlight_day).rstrip()
s += '\n' * l
return s
- def formatyear(self, theyear, w=2, l=1, c=6, m=3):
+ def formatyear(self, theyear, w=2, l=1, c=6, m=3, *, highlight_day=None):
"""
Returns a year's calendar as a multi-line string.
"""
@@ -428,15 +445,24 @@ def formatyear(self, theyear, w=2, l=1, c=6, m=3):
headers = (header for k in months)
a(formatstring(headers, colwidth, c).rstrip())
a('\n'*l)
+
+ if highlight_day and highlight_day.month in months:
+ month_pos = months.index(highlight_day.month)
+ else:
+ month_pos = None
+
# max number of weeks for this row
height = max(len(cal) for cal in row)
for j in range(height):
weeks = []
- for cal in row:
+ for k, cal in enumerate(row):
if j >= len(cal):
weeks.append('')
else:
- weeks.append(self.formatweek(cal[j], w))
+ day = highlight_day.day if k == month_pos else None
+ weeks.append(
+ self.formatweek(cal[j], w, highlight_day=day)
+ )
a(formatstring(weeks, colwidth, c).rstrip())
a('\n' * l)
return ''.join(v)
@@ -765,6 +791,7 @@ def main(args=None):
sys.exit(1)
locale = options.locale, options.encoding
+ today = datetime.date.today()
if options.type == "html":
if options.month:
@@ -781,7 +808,7 @@ def main(args=None):
optdict = dict(encoding=encoding, css=options.css)
write = sys.stdout.buffer.write
if options.year is None:
- write(cal.formatyearpage(datetime.date.today().year, **optdict))
+ write(cal.formatyearpage(today.year, **optdict))
else:
write(cal.formatyearpage(options.year, **optdict))
else:
@@ -797,10 +824,15 @@ def main(args=None):
if options.month is not None:
_validate_month(options.month)
if options.year is None:
- result = cal.formatyear(datetime.date.today().year, **optdict)
+ optdict["highlight_day"] = today
+ result = cal.formatyear(today.year, **optdict)
elif options.month is None:
+ if options.year == today.year:
+ optdict["highlight_day"] = today
result = cal.formatyear(options.year, **optdict)
else:
+ if options.year == today.year and options.month == today.month:
+ optdict["highlight_day"] = today
result = cal.formatmonth(options.year, options.month, **optdict)
write = sys.stdout.write
if options.encoding:
diff --git a/Misc/NEWS.d/next/Library/2024-12-29-00-33-34.gh-issue-128317.WgFina.rst b/Misc/NEWS.d/next/Library/2024-12-29-00-33-34.gh-issue-128317.WgFina.rst
new file mode 100644
index 00000000000000..4441108014569e
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-12-29-00-33-34.gh-issue-128317.WgFina.rst
@@ -0,0 +1,2 @@
+Highlight today in colour in :mod:`calendar`'s CLI output. Patch by Hugo van
+Kemenade.
1
0
gh-127787: refactor helpers for `PyUnicodeErrorObject` internal interface (GH-127789)
by encukou Jan. 3, 2025
by encukou Jan. 3, 2025
Jan. 3, 2025
https://github.com/python/cpython/commit/fa985bee6189aabac1c329f2de32aa9a4e…
commit: fa985bee6189aabac1c329f2de32aa9a4e88e550
branch: main
author: Bénédikt Tran <10796600+picnixz(a)users.noreply.github.com>
committer: encukou <encukou(a)gmail.com>
date: 2025-01-03T13:37:02+01:00
summary:
gh-127787: refactor helpers for `PyUnicodeErrorObject` internal interface (GH-127789)
- Unify `get_unicode` and `get_string` in a single function.
- Allow to retrieve the underlying `object` attribute, its
size, and the adjusted 'start' and 'end', all at once.
Add a new `_PyUnicodeError_GetParams` internal function for this.
(In `exceptions.c`, it's somewhat common to not need all the attributes,
but the compiler has opportunity to inline the function and optimize
unneeded work away. Outside that file, we'll usually need all or
most of them at once.)
- Use a common implementation for the following functions:
- `PyUnicode{Decode,Encode}Error_GetEncoding`
- `PyUnicode{Decode,Encode,Translate}Error_GetObject`
- `PyUnicode{Decode,Encode,Translate}Error_{Get,Set}Reason`
- `PyUnicode{Decode,Encode,Translate}Error_{Get,Set}{Start,End}`
files:
M Include/cpython/pyerrors.h
M Objects/exceptions.c
diff --git a/Include/cpython/pyerrors.h b/Include/cpython/pyerrors.h
index b36b4681f5dddb..49a6265e5eb02f 100644
--- a/Include/cpython/pyerrors.h
+++ b/Include/cpython/pyerrors.h
@@ -94,6 +94,12 @@ PyAPI_FUNC(void) _PyErr_ChainExceptions1(PyObject *);
/* In exceptions.c */
+PyAPI_FUNC(int) _PyUnicodeError_GetParams(
+ PyObject *self,
+ PyObject **obj, Py_ssize_t *objlen,
+ Py_ssize_t *start, Py_ssize_t *end,
+ int as_bytes);
+
PyAPI_FUNC(PyObject*) PyUnstable_Exc_PrepReraiseStar(
PyObject *orig,
PyObject *excs);
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index 6880c24196cbb8..714f8c828afbc1 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -2667,47 +2667,167 @@ SimpleExtendsException(PyExc_Exception, ValueError,
SimpleExtendsException(PyExc_ValueError, UnicodeError,
"Unicode related error.");
+
+/*
+ * Check the validity of 'attr' as a unicode or bytes object depending
+ * on 'as_bytes' and return a new reference on it if it is the case.
+ *
+ * The 'name' is the attribute name and is only used for error reporting.
+ *
+ * On success, this returns a strong reference on 'attr'.
+ * On failure, this sets a TypeError and returns NULL.
+ */
static PyObject *
-get_bytes(PyObject *attr, const char *name)
+as_unicode_error_attribute(PyObject *attr, const char *name, int as_bytes)
{
- if (!attr) {
- PyErr_Format(PyExc_TypeError, "%.200s attribute not set", name);
+ assert(as_bytes == 0 || as_bytes == 1);
+ if (attr == NULL) {
+ PyErr_Format(PyExc_TypeError, "%s attribute not set", name);
return NULL;
}
-
- if (!PyBytes_Check(attr)) {
- PyErr_Format(PyExc_TypeError, "%.200s attribute must be bytes", name);
+ if (!(as_bytes ? PyBytes_Check(attr) : PyUnicode_Check(attr))) {
+ PyErr_Format(PyExc_TypeError,
+ "%s attribute must be %s",
+ name,
+ as_bytes ? "bytes" : "unicode");
return NULL;
}
return Py_NewRef(attr);
}
-static PyObject *
-get_unicode(PyObject *attr, const char *name)
-{
- if (!attr) {
- PyErr_Format(PyExc_TypeError, "%.200s attribute not set", name);
- return NULL;
- }
- if (!PyUnicode_Check(attr)) {
+#define PyUnicodeError_Check(PTR) \
+ PyObject_TypeCheck((PTR), (PyTypeObject *)PyExc_UnicodeError)
+#define PyUnicodeError_CAST(PTR) \
+ (assert(PyUnicodeError_Check(PTR)), ((PyUnicodeErrorObject *)(PTR)))
+
+
+/* class names to use when reporting errors */
+#define Py_UNICODE_ENCODE_ERROR_NAME "UnicodeEncodeError"
+#define Py_UNICODE_DECODE_ERROR_NAME "UnicodeDecodeError"
+#define Py_UNICODE_TRANSLATE_ERROR_NAME "UnicodeTranslateError"
+
+
+/*
+ * Check that 'self' is a UnicodeError object.
+ *
+ * On success, this returns 0.
+ * On failure, this sets a TypeError exception and returns -1.
+ *
+ * The 'expect_type' is the name of the expected type, which is
+ * only used for error reporting.
+ *
+ * As an implementation detail, the `PyUnicode*Error_*` functions
+ * currently allow *any* subclass of UnicodeError as 'self'.
+ *
+ * Use one of the `Py_UNICODE_*_ERROR_NAME` macros to avoid typos.
+ */
+static inline int
+check_unicode_error_type(PyObject *self, const char *expect_type)
+{
+ assert(self != NULL);
+ if (!PyUnicodeError_Check(self)) {
PyErr_Format(PyExc_TypeError,
- "%.200s attribute must be unicode", name);
- return NULL;
+ "expecting a %s object, got %T", expect_type, self);
+ return -1;
}
- return Py_NewRef(attr);
+ return 0;
}
-static int
-set_unicodefromstring(PyObject **attr, const char *value)
+
+// --- PyUnicodeEncodeObject: internal helpers --------------------------------
+//
+// In the helpers below, the caller is responsible to ensure that 'self'
+// is a PyUnicodeErrorObject, although this is verified on DEBUG builds
+// through PyUnicodeError_CAST().
+
+/*
+ * Return the underlying (str) 'encoding' attribute of a UnicodeError object.
+ */
+static inline PyObject *
+unicode_error_get_encoding_impl(PyObject *self)
+{
+ assert(self != NULL);
+ PyUnicodeErrorObject *exc = PyUnicodeError_CAST(self);
+ return as_unicode_error_attribute(exc->encoding, "encoding", false);
+}
+
+
+/*
+ * Return the underlying 'object' attribute of a UnicodeError object
+ * as a bytes or a string instance, depending on the 'as_bytes' flag.
+ */
+static inline PyObject *
+unicode_error_get_object_impl(PyObject *self, int as_bytes)
{
- PyObject *obj = PyUnicode_FromString(value);
- if (!obj)
+ assert(self != NULL);
+ PyUnicodeErrorObject *exc = PyUnicodeError_CAST(self);
+ return as_unicode_error_attribute(exc->object, "object", as_bytes);
+}
+
+
+/*
+ * Return the underlying (str) 'reason' attribute of a UnicodeError object.
+ */
+static inline PyObject *
+unicode_error_get_reason_impl(PyObject *self)
+{
+ assert(self != NULL);
+ PyUnicodeErrorObject *exc = PyUnicodeError_CAST(self);
+ return as_unicode_error_attribute(exc->reason, "reason", false);
+}
+
+
+/*
+ * Set the underlying (str) 'reason' attribute of a UnicodeError object.
+ *
+ * Return 0 on success and -1 on failure.
+ */
+static inline int
+unicode_error_set_reason_impl(PyObject *self, const char *reason)
+{
+ assert(self != NULL);
+ PyObject *value = PyUnicode_FromString(reason);
+ if (value == NULL) {
return -1;
- Py_XSETREF(*attr, obj);
+ }
+ PyUnicodeErrorObject *exc = PyUnicodeError_CAST(self);
+ Py_XSETREF(exc->reason, value);
return 0;
}
+
+/*
+ * Set the 'start' attribute of a UnicodeError object.
+ *
+ * Return 0 on success and -1 on failure.
+ */
+static inline int
+unicode_error_set_start_impl(PyObject *self, Py_ssize_t start)
+{
+ assert(self != NULL);
+ PyUnicodeErrorObject *exc = PyUnicodeError_CAST(self);
+ exc->start = start;
+ return 0;
+}
+
+
+/*
+ * Set the 'end' attribute of a UnicodeError object.
+ *
+ * Return 0 on success and -1 on failure.
+ */
+static inline int
+unicode_error_set_end_impl(PyObject *self, Py_ssize_t end)
+{
+ assert(self != NULL);
+ PyUnicodeErrorObject *exc = PyUnicodeError_CAST(self);
+ exc->end = end;
+ return 0;
+}
+
+// --- PyUnicodeEncodeObject: internal getters --------------------------------
+
/*
* Adjust the (inclusive) 'start' value of a UnicodeError object.
*
@@ -2728,6 +2848,7 @@ unicode_error_adjust_start(Py_ssize_t start, Py_ssize_t objlen)
return start;
}
+
/*
* Adjust the (exclusive) 'end' value of a UnicodeError object.
*
@@ -2748,134 +2869,162 @@ unicode_error_adjust_end(Py_ssize_t end, Py_ssize_t objlen)
return end;
}
-#define _PyUnicodeError_CAST(PTR) ((PyUnicodeErrorObject *)(PTR))
-#define PyUnicodeError_Check(PTR) \
- PyObject_TypeCheck((PTR), (PyTypeObject *)PyExc_UnicodeError)
-#define PyUnicodeError_CAST(PTR) \
- (assert(PyUnicodeError_Check(PTR)), _PyUnicodeError_CAST(PTR))
-
-static inline int
-check_unicode_error_type(PyObject *self, const char *expect_type)
+/*
+ * Get various common parameters of a UnicodeError object.
+ *
+ * The caller is responsible to ensure that 'self' is a PyUnicodeErrorObject,
+ * although this condition is verified by this function on DEBUG builds.
+ *
+ * Return 0 on success and -1 on failure.
+ *
+ * Output parameters:
+ *
+ * obj A strong reference to the 'object' attribute.
+ * objlen The 'object' length.
+ * start The clipped 'start' attribute.
+ * end The clipped 'end' attribute.
+ *
+ * An output parameter can be NULL to indicate that
+ * the corresponding value does not need to be stored.
+ *
+ * Input parameter:
+ *
+ * as_bytes If 1, the error's 'object' attribute must be a bytes object,
+ * i.e. the call is for a `UnicodeDecodeError`. Otherwise, the
+ * 'object' attribute must be a string.
+ *
+ * A TypeError is raised if the 'object' type is incompatible.
+ */
+int
+_PyUnicodeError_GetParams(PyObject *self,
+ PyObject **obj, Py_ssize_t *objlen,
+ Py_ssize_t *start, Py_ssize_t *end,
+ int as_bytes)
{
- if (!PyUnicodeError_Check(self)) {
- PyErr_Format(PyExc_TypeError,
- "expecting a %s object, got %T", expect_type, self);
+ assert(self != NULL);
+ assert(as_bytes == 0 || as_bytes == 1);
+ PyUnicodeErrorObject *exc = PyUnicodeError_CAST(self);
+ PyObject *r = as_unicode_error_attribute(exc->object, "object", as_bytes);
+ if (r == NULL) {
return -1;
}
+
+ Py_ssize_t n = as_bytes ? PyBytes_GET_SIZE(r) : PyUnicode_GET_LENGTH(r);
+ if (objlen != NULL) {
+ *objlen = n;
+ }
+ if (start != NULL) {
+ *start = unicode_error_adjust_start(exc->start, n);
+ assert(*start >= 0);
+ assert(*start <= n);
+ }
+ if (end != NULL) {
+ *end = unicode_error_adjust_end(exc->end, n);
+ assert(*end >= 0);
+ assert(*end <= n);
+ }
+ if (obj != NULL) {
+ *obj = r;
+ }
+ else {
+ Py_DECREF(r);
+ }
return 0;
}
-static inline PyUnicodeErrorObject *
-as_unicode_error(PyObject *self, const char *expect_type)
-{
- int rc = check_unicode_error_type(self, expect_type);
- return rc < 0 ? NULL : _PyUnicodeError_CAST(self);
-}
+// --- PyUnicodeEncodeObject: 'encoding' getters ------------------------------
+// Note: PyUnicodeTranslateError does not have an 'encoding' attribute.
PyObject *
PyUnicodeEncodeError_GetEncoding(PyObject *self)
{
- PyUnicodeErrorObject *exc = as_unicode_error(self, "UnicodeEncodeError");
- return exc == NULL ? NULL : get_unicode(exc->encoding, "encoding");
+ int rc = check_unicode_error_type(self, Py_UNICODE_ENCODE_ERROR_NAME);
+ return rc < 0 ? NULL : unicode_error_get_encoding_impl(self);
}
+
PyObject *
PyUnicodeDecodeError_GetEncoding(PyObject *self)
{
- PyUnicodeErrorObject *exc = as_unicode_error(self, "UnicodeDecodeError");
- return exc == NULL ? NULL : get_unicode(exc->encoding, "encoding");
+ int rc = check_unicode_error_type(self, Py_UNICODE_DECODE_ERROR_NAME);
+ return rc < 0 ? NULL : unicode_error_get_encoding_impl(self);
}
+
+// --- PyUnicodeEncodeObject: 'object' getters --------------------------------
+
PyObject *
PyUnicodeEncodeError_GetObject(PyObject *self)
{
- PyUnicodeErrorObject *exc = as_unicode_error(self, "UnicodeEncodeError");
- return exc == NULL ? NULL : get_unicode(exc->object, "object");
+ int rc = check_unicode_error_type(self, Py_UNICODE_ENCODE_ERROR_NAME);
+ return rc < 0 ? NULL : unicode_error_get_object_impl(self, false);
}
+
PyObject *
PyUnicodeDecodeError_GetObject(PyObject *self)
{
- PyUnicodeErrorObject *exc = as_unicode_error(self, "UnicodeDecodeError");
- return exc == NULL ? NULL : get_bytes(exc->object, "object");
+ int rc = check_unicode_error_type(self, Py_UNICODE_DECODE_ERROR_NAME);
+ return rc < 0 ? NULL : unicode_error_get_object_impl(self, true);
}
+
PyObject *
PyUnicodeTranslateError_GetObject(PyObject *self)
{
- PyUnicodeErrorObject *exc = as_unicode_error(self, "UnicodeTranslateError");
- return exc == NULL ? NULL : get_unicode(exc->object, "object");
+ int rc = check_unicode_error_type(self, Py_UNICODE_TRANSLATE_ERROR_NAME);
+ return rc < 0 ? NULL : unicode_error_get_object_impl(self, false);
}
+
+// --- PyUnicodeEncodeObject: 'start' getters ---------------------------------
+
+/*
+ * Specialization of _PyUnicodeError_GetParams() for the 'start' attribute.
+ *
+ * The caller is responsible to ensure that 'self' is a PyUnicodeErrorObject,
+ * although this condition is verified by this function on DEBUG builds.
+ */
+static inline int
+unicode_error_get_start_impl(PyObject *self, Py_ssize_t *start, int as_bytes)
+{
+ assert(self != NULL);
+ return _PyUnicodeError_GetParams(self, NULL, NULL, start, NULL, as_bytes);
+}
+
+
int
PyUnicodeEncodeError_GetStart(PyObject *self, Py_ssize_t *start)
{
- PyUnicodeErrorObject *exc = as_unicode_error(self, "UnicodeEncodeError");
- if (exc == NULL) {
- return -1;
- }
- PyObject *obj = get_unicode(exc->object, "object");
- if (obj == NULL) {
- return -1;
- }
- Py_ssize_t size = PyUnicode_GET_LENGTH(obj);
- Py_DECREF(obj);
- *start = unicode_error_adjust_start(exc->start, size);
- return 0;
+ int rc = check_unicode_error_type(self, Py_UNICODE_ENCODE_ERROR_NAME);
+ return rc < 0 ? -1 : unicode_error_get_start_impl(self, start, false);
}
int
PyUnicodeDecodeError_GetStart(PyObject *self, Py_ssize_t *start)
{
- PyUnicodeErrorObject *exc = as_unicode_error(self, "UnicodeDecodeError");
- if (exc == NULL) {
- return -1;
- }
- PyObject *obj = get_bytes(exc->object, "object");
- if (obj == NULL) {
- return -1;
- }
- Py_ssize_t size = PyBytes_GET_SIZE(obj);
- Py_DECREF(obj);
- *start = unicode_error_adjust_start(exc->start, size);
- return 0;
+ int rc = check_unicode_error_type(self, Py_UNICODE_DECODE_ERROR_NAME);
+ return rc < 0 ? -1 : unicode_error_get_start_impl(self, start, true);
}
int
PyUnicodeTranslateError_GetStart(PyObject *self, Py_ssize_t *start)
{
- PyUnicodeErrorObject *exc = as_unicode_error(self, "UnicodeTranslateError");
- if (exc == NULL) {
- return -1;
- }
- PyObject *obj = get_unicode(exc->object, "object");
- if (obj == NULL) {
- return -1;
- }
- Py_ssize_t size = PyUnicode_GET_LENGTH(obj);
- Py_DECREF(obj);
- *start = unicode_error_adjust_start(exc->start, size);
- return 0;
+ int rc = check_unicode_error_type(self, Py_UNICODE_TRANSLATE_ERROR_NAME);
+ return rc < 0 ? -1 : unicode_error_get_start_impl(self, start, false);
}
-static inline int
-unicode_error_set_start_impl(PyObject *self, Py_ssize_t start)
-{
- PyUnicodeErrorObject *exc = _PyUnicodeError_CAST(self);
- exc->start = start;
- return 0;
-}
-
+// --- PyUnicodeEncodeObject: 'start' setters ---------------------------------
int
PyUnicodeEncodeError_SetStart(PyObject *self, Py_ssize_t start)
{
- int rc = check_unicode_error_type(self, "UnicodeEncodeError");
+ int rc = check_unicode_error_type(self, Py_UNICODE_ENCODE_ERROR_NAME);
return rc < 0 ? -1 : unicode_error_set_start_impl(self, start);
}
@@ -2883,7 +3032,7 @@ PyUnicodeEncodeError_SetStart(PyObject *self, Py_ssize_t start)
int
PyUnicodeDecodeError_SetStart(PyObject *self, Py_ssize_t start)
{
- int rc = check_unicode_error_type(self, "UnicodeDecodeError");
+ int rc = check_unicode_error_type(self, Py_UNICODE_DECODE_ERROR_NAME);
return rc < 0 ? -1 : unicode_error_set_start_impl(self, start);
}
@@ -2891,78 +3040,57 @@ PyUnicodeDecodeError_SetStart(PyObject *self, Py_ssize_t start)
int
PyUnicodeTranslateError_SetStart(PyObject *self, Py_ssize_t start)
{
- int rc = check_unicode_error_type(self, "UnicodeTranslateError");
+ int rc = check_unicode_error_type(self, Py_UNICODE_TRANSLATE_ERROR_NAME);
return rc < 0 ? -1 : unicode_error_set_start_impl(self, start);
}
+// --- PyUnicodeEncodeObject: 'end' getters -----------------------------------
+
+/*
+ * Specialization of _PyUnicodeError_GetParams() for the 'end' attribute.
+ *
+ * The caller is responsible to ensure that 'self' is a PyUnicodeErrorObject,
+ * although this condition is verified by this function on DEBUG builds.
+ */
+static inline int
+unicode_error_get_end_impl(PyObject *self, Py_ssize_t *end, int as_bytes)
+{
+ assert(self != NULL);
+ return _PyUnicodeError_GetParams(self, NULL, NULL, NULL, end, as_bytes);
+}
+
+
int
PyUnicodeEncodeError_GetEnd(PyObject *self, Py_ssize_t *end)
{
- PyUnicodeErrorObject *exc = as_unicode_error(self, "UnicodeEncodeError");
- if (exc == NULL) {
- return -1;
- }
- PyObject *obj = get_unicode(exc->object, "object");
- if (obj == NULL) {
- return -1;
- }
- Py_ssize_t size = PyUnicode_GET_LENGTH(obj);
- Py_DECREF(obj);
- *end = unicode_error_adjust_end(exc->end, size);
- return 0;
+ int rc = check_unicode_error_type(self, Py_UNICODE_ENCODE_ERROR_NAME);
+ return rc < 0 ? -1 : unicode_error_get_end_impl(self, end, false);
}
int
PyUnicodeDecodeError_GetEnd(PyObject *self, Py_ssize_t *end)
{
- PyUnicodeErrorObject *exc = as_unicode_error(self, "UnicodeDecodeError");
- if (exc == NULL) {
- return -1;
- }
- PyObject *obj = get_bytes(exc->object, "object");
- if (obj == NULL) {
- return -1;
- }
- Py_ssize_t size = PyBytes_GET_SIZE(obj);
- Py_DECREF(obj);
- *end = unicode_error_adjust_end(exc->end, size);
- return 0;
+ int rc = check_unicode_error_type(self, Py_UNICODE_DECODE_ERROR_NAME);
+ return rc < 0 ? -1 : unicode_error_get_end_impl(self, end, true);
}
int
PyUnicodeTranslateError_GetEnd(PyObject *self, Py_ssize_t *end)
{
- PyUnicodeErrorObject *exc = as_unicode_error(self, "UnicodeTranslateError");
- if (exc == NULL) {
- return -1;
- }
- PyObject *obj = get_unicode(exc->object, "object");
- if (obj == NULL) {
- return -1;
- }
- Py_ssize_t size = PyUnicode_GET_LENGTH(obj);
- Py_DECREF(obj);
- *end = unicode_error_adjust_end(exc->end, size);
- return 0;
+ int rc = check_unicode_error_type(self, Py_UNICODE_TRANSLATE_ERROR_NAME);
+ return rc < 0 ? -1 : unicode_error_get_end_impl(self, end, false);
}
-static inline int
-unicode_error_set_end_impl(PyObject *self, Py_ssize_t end)
-{
- PyUnicodeErrorObject *exc = _PyUnicodeError_CAST(self);
- exc->end = end;
- return 0;
-}
-
+// --- PyUnicodeEncodeObject: 'end' setters -----------------------------------
int
PyUnicodeEncodeError_SetEnd(PyObject *self, Py_ssize_t end)
{
- int rc = check_unicode_error_type(self, "UnicodeEncodeError");
+ int rc = check_unicode_error_type(self, Py_UNICODE_ENCODE_ERROR_NAME);
return rc < 0 ? -1 : unicode_error_set_end_impl(self, end);
}
@@ -2970,7 +3098,7 @@ PyUnicodeEncodeError_SetEnd(PyObject *self, Py_ssize_t end)
int
PyUnicodeDecodeError_SetEnd(PyObject *self, Py_ssize_t end)
{
- int rc = check_unicode_error_type(self, "UnicodeDecodeError");
+ int rc = check_unicode_error_type(self, Py_UNICODE_DECODE_ERROR_NAME);
return rc < 0 ? -1 : unicode_error_set_end_impl(self, end);
}
@@ -2978,56 +3106,60 @@ PyUnicodeDecodeError_SetEnd(PyObject *self, Py_ssize_t end)
int
PyUnicodeTranslateError_SetEnd(PyObject *self, Py_ssize_t end)
{
- int rc = check_unicode_error_type(self, "UnicodeTranslateError");
+ int rc = check_unicode_error_type(self, Py_UNICODE_TRANSLATE_ERROR_NAME);
return rc < 0 ? -1 : unicode_error_set_end_impl(self, end);
}
+// --- PyUnicodeEncodeObject: 'reason' getters --------------------------------
+
PyObject *
PyUnicodeEncodeError_GetReason(PyObject *self)
{
- PyUnicodeErrorObject *exc = as_unicode_error(self, "UnicodeEncodeError");
- return exc == NULL ? NULL : get_unicode(exc->reason, "reason");
+ int rc = check_unicode_error_type(self, Py_UNICODE_ENCODE_ERROR_NAME);
+ return rc < 0 ? NULL : unicode_error_get_reason_impl(self);
}
PyObject *
PyUnicodeDecodeError_GetReason(PyObject *self)
{
- PyUnicodeErrorObject *exc = as_unicode_error(self, "UnicodeDecodeError");
- return exc == NULL ? NULL : get_unicode(exc->reason, "reason");
+ int rc = check_unicode_error_type(self, Py_UNICODE_DECODE_ERROR_NAME);
+ return rc < 0 ? NULL : unicode_error_get_reason_impl(self);
}
PyObject *
PyUnicodeTranslateError_GetReason(PyObject *self)
{
- PyUnicodeErrorObject *exc = as_unicode_error(self, "UnicodeTranslateError");
- return exc == NULL ? NULL : get_unicode(exc->reason, "reason");
+ int rc = check_unicode_error_type(self, Py_UNICODE_TRANSLATE_ERROR_NAME);
+ return rc < 0 ? NULL : unicode_error_get_reason_impl(self);
}
+// --- PyUnicodeEncodeObject: 'reason' setters --------------------------------
+
int
PyUnicodeEncodeError_SetReason(PyObject *self, const char *reason)
{
- PyUnicodeErrorObject *exc = as_unicode_error(self, "UnicodeEncodeError");
- return exc == NULL ? -1 : set_unicodefromstring(&exc->reason, reason);
+ int rc = check_unicode_error_type(self, Py_UNICODE_ENCODE_ERROR_NAME);
+ return rc < 0 ? -1 : unicode_error_set_reason_impl(self, reason);
}
int
PyUnicodeDecodeError_SetReason(PyObject *self, const char *reason)
{
- PyUnicodeErrorObject *exc = as_unicode_error(self, "UnicodeDecodeError");
- return exc == NULL ? -1 : set_unicodefromstring(&exc->reason, reason);
+ int rc = check_unicode_error_type(self, Py_UNICODE_DECODE_ERROR_NAME);
+ return rc < 0 ? -1 : unicode_error_set_reason_impl(self, reason);
}
int
PyUnicodeTranslateError_SetReason(PyObject *self, const char *reason)
{
- PyUnicodeErrorObject *exc = as_unicode_error(self, "UnicodeTranslateError");
- return exc == NULL ? -1 : set_unicodefromstring(&exc->reason, reason);
+ int rc = check_unicode_error_type(self, Py_UNICODE_TRANSLATE_ERROR_NAME);
+ return rc < 0 ? -1 : unicode_error_set_reason_impl(self, reason);
}
1
0