aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Modules
diff options
context:
space:
mode:
Diffstat (limited to 'Modules')
-rw-r--r--Modules/_curses_panel.c369
-rw-r--r--Modules/_hashopenssl.c190
-rw-r--r--Modules/_json.c13
-rw-r--r--Modules/_testcapi/unicode.c7
-rw-r--r--Modules/_zstd/_zstdmodule.c3
-rw-r--r--Modules/_zstd/_zstdmodule.h1
-rw-r--r--Modules/_zstd/clinic/compressor.c.h41
-rw-r--r--Modules/_zstd/compressor.c98
-rw-r--r--Modules/clinic/_curses_panel.c.h159
-rw-r--r--Modules/posixmodule.c24
-rw-r--r--Modules/xxlimited.c11
11 files changed, 581 insertions, 335 deletions
diff --git a/Modules/_curses_panel.c b/Modules/_curses_panel.c
index eecf7a1c8a1..d7acfc6a06a 100644
--- a/Modules/_curses_panel.c
+++ b/Modules/_curses_panel.c
@@ -17,6 +17,7 @@ static const char PyCursesVersion[] = "2.1";
#include "Python.h"
+#define CURSES_PANEL_MODULE
#include "py_curses.h"
#if defined(HAVE_NCURSESW_PANEL_H)
@@ -28,10 +29,12 @@ static const char PyCursesVersion[] = "2.1";
#endif
typedef struct {
- PyObject *PyCursesError;
+ PyObject *error;
PyTypeObject *PyCursesPanel_Type;
} _curses_panel_state;
+typedef struct PyCursesPanelObject PyCursesPanelObject;
+
static inline _curses_panel_state *
get_curses_panel_state(PyObject *module)
{
@@ -40,11 +43,30 @@ get_curses_panel_state(PyObject *module)
return (_curses_panel_state *)state;
}
+static inline _curses_panel_state *
+get_curses_panel_state_by_panel(PyCursesPanelObject *panel)
+{
+ /*
+ * Note: 'state' may be NULL if Py_TYPE(panel) is not a heap
+ * type associated with this module, but the compiler would
+ * have likely already complained with an "invalid pointer
+ * type" at compile-time.
+ *
+ * To make it more robust, all functions recovering a module's
+ * state from an object should expect to return NULL with an
+ * exception set (in contrast to functions recovering a module's
+ * state from a module itself).
+ */
+ void *state = PyType_GetModuleState(Py_TYPE(panel));
+ assert(state != NULL);
+ return (_curses_panel_state *)state;
+}
+
static int
_curses_panel_clear(PyObject *mod)
{
_curses_panel_state *state = get_curses_panel_state(mod);
- Py_CLEAR(state->PyCursesError);
+ Py_CLEAR(state->error);
Py_CLEAR(state->PyCursesPanel_Type);
return 0;
}
@@ -54,7 +76,7 @@ _curses_panel_traverse(PyObject *mod, visitproc visit, void *arg)
{
Py_VISIT(Py_TYPE(mod));
_curses_panel_state *state = get_curses_panel_state(mod);
- Py_VISIT(state->PyCursesError);
+ Py_VISIT(state->error);
Py_VISIT(state->PyCursesPanel_Type);
return 0;
}
@@ -65,28 +87,149 @@ _curses_panel_free(void *mod)
(void)_curses_panel_clear((PyObject *)mod);
}
+/* Utility Error Procedures
+ *
+ * The naming and implementations are identical to those in _cursesmodule.c.
+ * Functions that are not yet needed (for instance, reporting an ERR value
+ * from a module-wide function, namely curses_panel_set_error()) are
+ * omitted and should only be added if needed.
+ */
+
+static void
+_curses_panel_format_error(_curses_panel_state *state,
+ const char *curses_funcname,
+ const char *python_funcname,
+ const char *return_value,
+ const char *default_message)
+{
+ assert(!PyErr_Occurred());
+ if (python_funcname == NULL && curses_funcname == NULL) {
+ PyErr_SetString(state->error, default_message);
+ }
+ else if (python_funcname == NULL) {
+ (void)PyErr_Format(state->error, CURSES_ERROR_FORMAT,
+ curses_funcname, return_value);
+ }
+ else {
+ assert(python_funcname != NULL);
+ (void)PyErr_Format(state->error, CURSES_ERROR_VERBOSE_FORMAT,
+ curses_funcname, python_funcname, return_value);
+ }
+}
+
+/*
+ * Format a curses error for a function that returned ERR.
+ *
+ * Specify a non-NULL 'python_funcname' when the latter differs from
+ * 'curses_funcname'. If both names are NULL, uses the 'catchall_ERR'
+ * message instead.
+ */
+static void
+_curses_panel_set_error(_curses_panel_state *state,
+ const char *curses_funcname,
+ const char *python_funcname)
+{
+ _curses_panel_format_error(state, curses_funcname, python_funcname,
+ "ERR", catchall_ERR);
+}
+
+/*
+ * Format a curses error for a function that returned NULL.
+ *
+ * Specify a non-NULL 'python_funcname' when the latter differs from
+ * 'curses_funcname'. If both names are NULL, uses the 'catchall_NULL'
+ * message instead.
+ */
+static void
+_curses_panel_set_null_error(_curses_panel_state *state,
+ const char *curses_funcname,
+ const char *python_funcname)
+{
+ _curses_panel_format_error(state, curses_funcname, python_funcname,
+ "NULL", catchall_NULL);
+}
+
+/* Same as _curses_panel_set_null_error() for a module object. */
+static void
+curses_panel_set_null_error(PyObject *module,
+ const char *curses_funcname,
+ const char *python_funcname)
+{
+ _curses_panel_state *state = get_curses_panel_state(module);
+ _curses_panel_set_null_error(state, curses_funcname, python_funcname);
+}
+
+/* Same as _curses_panel_set_error() for a panel object. */
+static void
+curses_panel_panel_set_error(PyCursesPanelObject *panel,
+ const char *curses_funcname,
+ const char *python_funcname)
+{
+ _curses_panel_state *state = get_curses_panel_state_by_panel(panel);
+ _curses_panel_set_error(state, curses_funcname, python_funcname);
+}
+
+/* Same as _curses_panel_set_null_error() for a panel object. */
+static void
+curses_panel_panel_set_null_error(PyCursesPanelObject *panel,
+ const char *curses_funcname,
+ const char *python_funcname)
+{
+ _curses_panel_state *state = get_curses_panel_state_by_panel(panel);
+ _curses_panel_set_null_error(state, curses_funcname, python_funcname);
+}
+
+/*
+ * Indicate that a panel object couldn't be found.
+ *
+ * Use it for the following constructions:
+ *
+ * PROC caller_funcname:
+ * pan = called_funcname()
+ * find_po(panel)
+ *
+ * PROC caller_funcname:
+ * find_po(self->pan)
+*/
+static void
+curses_panel_notfound_error(const char *called_funcname,
+ const char *caller_funcname)
+{
+ assert(!(called_funcname == NULL && caller_funcname == NULL));
+ if (caller_funcname == NULL) {
+ (void)PyErr_Format(PyExc_RuntimeError,
+ "%s(): cannot find panel object",
+ called_funcname);
+ }
+ else {
+ (void)PyErr_Format(PyExc_RuntimeError,
+ "%s() (called by %s()): cannot find panel object",
+ called_funcname, caller_funcname);
+ }
+}
+
/* Utility Functions */
/*
- * Check the return code from a curses function and return None
- * or raise an exception as appropriate.
+ * Check the return code from a curses function, returning None
+ * on success and setting an exception on error.
*/
+/*
+ * Return None if 'code' is different from ERR (implementation-defined).
+ * Otherwise, set an exception using curses_panel_panel_set_error() and
+ * the remaining arguments, and return NULL.
+ */
static PyObject *
-PyCursesCheckERR(_curses_panel_state *state, int code, const char *fname)
+curses_panel_panel_check_err(PyCursesPanelObject *panel, int code,
+ const char *curses_funcname,
+ const char *python_funcname)
{
if (code != ERR) {
Py_RETURN_NONE;
}
- else {
- if (fname == NULL) {
- PyErr_SetString(state->PyCursesError, catchall_ERR);
- }
- else {
- PyErr_Format(state->PyCursesError, "%s() returned ERR", fname);
- }
- return NULL;
- }
+ curses_panel_panel_set_error(panel, curses_funcname, python_funcname);
+ return NULL;
}
/*****************************************************************************
@@ -95,7 +238,7 @@ PyCursesCheckERR(_curses_panel_state *state, int code, const char *fname)
/* Definition of the panel object and panel type */
-typedef struct {
+typedef struct PyCursesPanelObject {
PyObject_HEAD
PANEL *pan;
PyCursesWindowObject *wo; /* for reference counts */
@@ -144,8 +287,11 @@ insert_lop(PyCursesPanelObject *po)
return 0;
}
-/* Remove the panel object from lop */
-static void
+/* Remove the panel object from lop.
+ *
+ * Return -1 on error but do NOT set an exception; otherwise return 0.
+ */
+static int
remove_lop(PyCursesPanelObject *po)
{
list_of_panels *temp, *n;
@@ -154,25 +300,23 @@ remove_lop(PyCursesPanelObject *po)
if (temp->po == po) {
lop = temp->next;
PyMem_Free(temp);
- return;
+ return 0;
}
while (temp->next == NULL || temp->next->po != po) {
if (temp->next == NULL) {
- PyErr_SetString(PyExc_RuntimeError,
- "remove_lop: can't find Panel Object");
- return;
+ return -1;
}
temp = temp->next;
}
n = temp->next->next;
PyMem_Free(temp->next);
temp->next = n;
- return;
+ return 0;
}
/* Return the panel object that corresponds to pan */
static PyCursesPanelObject *
-find_po(PANEL *pan)
+find_po_impl(PANEL *pan)
{
list_of_panels *temp;
for (temp = lop; temp->po->pan != pan; temp = temp->next)
@@ -180,6 +324,17 @@ find_po(PANEL *pan)
return temp->po;
}
+/* Same as find_po_impl() but with caller context information. */
+static PyCursesPanelObject *
+find_po(PANEL *pan, const char *called_funcname, const char *caller_funcname)
+{
+ PyCursesPanelObject *res = find_po_impl(pan);
+ if (res == NULL) {
+ curses_panel_notfound_error(called_funcname, caller_funcname);
+ }
+ return res;
+}
+
/*[clinic input]
module _curses_panel
class _curses_panel.panel "PyCursesPanelObject *" "&PyCursesPanel_Type"
@@ -193,67 +348,59 @@ class _curses_panel.panel "PyCursesPanelObject *" "&PyCursesPanel_Type"
/*[clinic input]
_curses_panel.panel.bottom
- cls: defining_class
-
Push the panel to the bottom of the stack.
[clinic start generated code]*/
static PyObject *
-_curses_panel_panel_bottom_impl(PyCursesPanelObject *self, PyTypeObject *cls)
-/*[clinic end generated code: output=8ec7fbbc08554021 input=6b7d2c0578b5a1c4]*/
+_curses_panel_panel_bottom_impl(PyCursesPanelObject *self)
+/*[clinic end generated code: output=7aa7d14d7e1d1ce6 input=b6c920c071b61e2e]*/
{
- _curses_panel_state *state = PyType_GetModuleState(cls);
- return PyCursesCheckERR(state, bottom_panel(self->pan), "bottom");
+ int rtn = bottom_panel(self->pan);
+ return curses_panel_panel_check_err(self, rtn, "bottom_panel", "bottom");
}
/*[clinic input]
_curses_panel.panel.hide
- cls: defining_class
-
Hide the panel.
This does not delete the object, it just makes the window on screen invisible.
[clinic start generated code]*/
static PyObject *
-_curses_panel_panel_hide_impl(PyCursesPanelObject *self, PyTypeObject *cls)
-/*[clinic end generated code: output=cc6ab7203cdc1450 input=1bfc741f473e6055]*/
+_curses_panel_panel_hide_impl(PyCursesPanelObject *self)
+/*[clinic end generated code: output=a7bbbd523e1eab49 input=f6ab884e99386118]*/
{
- _curses_panel_state *state = PyType_GetModuleState(cls);
- return PyCursesCheckERR(state, hide_panel(self->pan), "hide");
+ int rtn = hide_panel(self->pan);
+ return curses_panel_panel_check_err(self, rtn, "hide_panel", "hide");
}
/*[clinic input]
_curses_panel.panel.show
- cls: defining_class
-
Display the panel (which might have been hidden).
[clinic start generated code]*/
static PyObject *
-_curses_panel_panel_show_impl(PyCursesPanelObject *self, PyTypeObject *cls)
-/*[clinic end generated code: output=dc3421de375f0409 input=8122e80151cb4379]*/
+_curses_panel_panel_show_impl(PyCursesPanelObject *self)
+/*[clinic end generated code: output=6b4553ab45c97769 input=57b167bbefaa3755]*/
{
- _curses_panel_state *state = PyType_GetModuleState(cls);
- return PyCursesCheckERR(state, show_panel(self->pan), "show");
+ int rtn = show_panel(self->pan);
+ return curses_panel_panel_check_err(self, rtn, "show_panel", "show");
}
/*[clinic input]
_curses_panel.panel.top
- cls: defining_class
-
Push panel to the top of the stack.
[clinic start generated code]*/
static PyObject *
-_curses_panel_panel_top_impl(PyCursesPanelObject *self, PyTypeObject *cls)
-/*[clinic end generated code: output=10a072e511e873f7 input=1f372d597dda3379]*/
+_curses_panel_panel_top_impl(PyCursesPanelObject *self)
+/*[clinic end generated code: output=0f5f2f8cdd2d1777 input=be33975ec3ca0e9a]*/
{
- _curses_panel_state *state = PyType_GetModuleState(cls);
- return PyCursesCheckERR(state, top_panel(self->pan), "top");
+ int rtn = top_panel(self->pan);
+ return curses_panel_panel_check_err(self, rtn, "top_panel", "top");
}
/* Allocation and deallocation of Panel Objects */
@@ -287,13 +434,22 @@ PyCursesPanel_Dealloc(PyObject *self)
tp = (PyObject *) Py_TYPE(po);
obj = (PyObject *) panel_userptr(po->pan);
if (obj) {
- (void)set_panel_userptr(po->pan, NULL);
Py_DECREF(obj);
+ if (set_panel_userptr(po->pan, NULL) == ERR) {
+ curses_panel_panel_set_error(po, "set_panel_userptr", "__del__");
+ PyErr_FormatUnraisable("Exception ignored in PyCursesPanel_Dealloc()");
+ }
+ }
+ if (del_panel(po->pan) == ERR && !PyErr_Occurred()) {
+ curses_panel_panel_set_error(po, "del_panel", "__del__");
+ PyErr_FormatUnraisable("Exception ignored in PyCursesPanel_Dealloc()");
}
- (void)del_panel(po->pan);
if (po->wo != NULL) {
Py_DECREF(po->wo);
- remove_lop(po);
+ if (remove_lop(po) < 0) {
+ PyErr_SetString(PyExc_RuntimeError, "__del__: no panel object to delete");
+ PyErr_FormatUnraisable("Exception ignored in PyCursesPanel_Dealloc()");
+ }
}
PyObject_Free(po);
Py_DECREF(tp);
@@ -315,18 +471,11 @@ _curses_panel_panel_above_impl(PyCursesPanelObject *self)
PyCursesPanelObject *po;
pan = panel_above(self->pan);
-
- if (pan == NULL) { /* valid output, it means the calling panel
- is on top of the stack */
+ if (pan == NULL) { /* valid output: it means no panel exists yet */
Py_RETURN_NONE;
}
- po = find_po(pan);
- if (po == NULL) {
- PyErr_SetString(PyExc_RuntimeError,
- "panel_above: can't find Panel Object");
- return NULL;
- }
- return Py_NewRef(po);
+ po = find_po(pan, "panel_above", "above");
+ return Py_XNewRef(po);
}
/* panel_below(NULL) returns the top panel in the stack. To get
@@ -345,18 +494,11 @@ _curses_panel_panel_below_impl(PyCursesPanelObject *self)
PyCursesPanelObject *po;
pan = panel_below(self->pan);
-
- if (pan == NULL) { /* valid output, it means the calling panel
- is on the bottom of the stack */
+ if (pan == NULL) { /* valid output: it means no panel exists yet */
Py_RETURN_NONE;
}
- po = find_po(pan);
- if (po == NULL) {
- PyErr_SetString(PyExc_RuntimeError,
- "panel_below: can't find Panel Object");
- return NULL;
- }
- return Py_NewRef(po);
+ po = find_po(pan, "panel_below", "below");
+ return Py_XNewRef(po);
}
/*[clinic input]
@@ -378,7 +520,6 @@ _curses_panel_panel_hidden_impl(PyCursesPanelObject *self)
/*[clinic input]
_curses_panel.panel.move
- cls: defining_class
y: int
x: int
/
@@ -387,12 +528,11 @@ Move the panel to the screen coordinates (y, x).
[clinic start generated code]*/
static PyObject *
-_curses_panel_panel_move_impl(PyCursesPanelObject *self, PyTypeObject *cls,
- int y, int x)
-/*[clinic end generated code: output=ce546c93e56867da input=60a0e7912ff99849]*/
+_curses_panel_panel_move_impl(PyCursesPanelObject *self, int y, int x)
+/*[clinic end generated code: output=d867535a89777415 input=e0b36b78acc03fba]*/
{
- _curses_panel_state *state = PyType_GetModuleState(cls);
- return PyCursesCheckERR(state, move_panel(self->pan, y, x), "move_panel");
+ int rtn = move_panel(self->pan, y, x);
+ return curses_panel_panel_check_err(self, rtn, "move_panel", "move");
}
/*[clinic input]
@@ -411,7 +551,6 @@ _curses_panel_panel_window_impl(PyCursesPanelObject *self)
/*[clinic input]
_curses_panel.panel.replace
- cls: defining_class
win: object(type="PyCursesWindowObject *", subclass_of="&PyCursesWindow_Type")
/
@@ -420,22 +559,17 @@ Change the window associated with the panel to the window win.
static PyObject *
_curses_panel_panel_replace_impl(PyCursesPanelObject *self,
- PyTypeObject *cls,
PyCursesWindowObject *win)
-/*[clinic end generated code: output=c71f95c212d58ae7 input=dbec7180ece41ff5]*/
+/*[clinic end generated code: output=2253a95f7b287255 input=4b1c4283987d9dfa]*/
{
- _curses_panel_state *state = PyType_GetModuleState(cls);
-
- PyCursesPanelObject *po = find_po(self->pan);
+ PyCursesPanelObject *po = find_po(self->pan, "replace", NULL);
if (po == NULL) {
- PyErr_SetString(PyExc_RuntimeError,
- "replace_panel: can't find Panel Object");
return NULL;
}
int rtn = replace_panel(self->pan, win->win);
if (rtn == ERR) {
- PyErr_SetString(state->PyCursesError, "replace_panel() returned ERR");
+ curses_panel_panel_set_error(self, "replace_panel", "replace");
return NULL;
}
Py_SETREF(po->wo, (PyCursesWindowObject*)Py_NewRef(win));
@@ -445,7 +579,6 @@ _curses_panel_panel_replace_impl(PyCursesPanelObject *self,
/*[clinic input]
_curses_panel.panel.set_userptr
- cls: defining_class
obj: object
/
@@ -454,8 +587,8 @@ Set the panel's user pointer to obj.
static PyObject *
_curses_panel_panel_set_userptr_impl(PyCursesPanelObject *self,
- PyTypeObject *cls, PyObject *obj)
-/*[clinic end generated code: output=db74f3db07b28080 input=e3fee2ff7b1b8e48]*/
+ PyObject *obj)
+/*[clinic end generated code: output=7fa1fd23f69db71e input=d2c6a9dbefabbf39]*/
{
PyCursesInitialised;
Py_INCREF(obj);
@@ -464,34 +597,27 @@ _curses_panel_panel_set_userptr_impl(PyCursesPanelObject *self,
if (rc == ERR) {
/* In case of an ncurses error, decref the new object again */
Py_DECREF(obj);
+ curses_panel_panel_set_error(self, "set_panel_userptr", "set_userptr");
+ return NULL;
}
- else {
- Py_XDECREF(oldobj);
- }
-
- _curses_panel_state *state = PyType_GetModuleState(cls);
- return PyCursesCheckERR(state, rc, "set_panel_userptr");
+ Py_XDECREF(oldobj);
+ Py_RETURN_NONE;
}
/*[clinic input]
_curses_panel.panel.userptr
- cls: defining_class
-
Return the user pointer for the panel.
[clinic start generated code]*/
static PyObject *
-_curses_panel_panel_userptr_impl(PyCursesPanelObject *self,
- PyTypeObject *cls)
-/*[clinic end generated code: output=eea6e6f39ffc0179 input=f22ca4f115e30a80]*/
+_curses_panel_panel_userptr_impl(PyCursesPanelObject *self)
+/*[clinic end generated code: output=e849c307b5dc9237 input=f78b7a47aef0fd50]*/
{
- _curses_panel_state *state = PyType_GetModuleState(cls);
-
PyCursesInitialised;
PyObject *obj = (PyObject *) panel_userptr(self->pan);
if (obj == NULL) {
- PyErr_SetString(state->PyCursesError, "no userptr set");
+ curses_panel_panel_set_null_error(self, "panel_userptr", "userptr");
return NULL;
}
@@ -552,18 +678,11 @@ _curses_panel_bottom_panel_impl(PyObject *module)
PyCursesInitialised;
pan = panel_above(NULL);
-
- if (pan == NULL) { /* valid output, it means
- there's no panel at all */
+ if (pan == NULL) { /* valid output: it means no panel exists yet */
Py_RETURN_NONE;
}
- po = find_po(pan);
- if (po == NULL) {
- PyErr_SetString(PyExc_RuntimeError,
- "panel_above: can't find Panel Object");
- return NULL;
- }
- return Py_NewRef(po);
+ po = find_po(pan, "panel_above", "bottom_panel");
+ return Py_XNewRef(po);
}
/*[clinic input]
@@ -579,14 +698,13 @@ static PyObject *
_curses_panel_new_panel_impl(PyObject *module, PyCursesWindowObject *win)
/*[clinic end generated code: output=45e948e0176a9bd2 input=74d4754e0ebe4800]*/
{
- _curses_panel_state *state = get_curses_panel_state(module);
-
PANEL *pan = new_panel(win->win);
if (pan == NULL) {
- PyErr_SetString(state->PyCursesError, catchall_NULL);
+ curses_panel_set_null_error(module, "new_panel", NULL);
return NULL;
}
- return (PyObject *)PyCursesPanel_New(state, pan, win);
+ _curses_panel_state *state = get_curses_panel_state(module);
+ return PyCursesPanel_New(state, pan, win);
}
@@ -610,18 +728,11 @@ _curses_panel_top_panel_impl(PyObject *module)
PyCursesInitialised;
pan = panel_below(NULL);
-
- if (pan == NULL) { /* valid output, it means
- there's no panel at all */
+ if (pan == NULL) { /* valid output: it means no panel exists yet */
Py_RETURN_NONE;
}
- po = find_po(pan);
- if (po == NULL) {
- PyErr_SetString(PyExc_RuntimeError,
- "panel_below: can't find Panel Object");
- return NULL;
- }
- return Py_NewRef(po);
+ po = find_po(pan, "panel_below", "top_panel");
+ return Py_XNewRef(po);
}
/*[clinic input]
@@ -673,10 +784,10 @@ _curses_panel_exec(PyObject *mod)
}
/* For exception _curses_panel.error */
- state->PyCursesError = PyErr_NewException(
+ state->error = PyErr_NewException(
"_curses_panel.error", NULL, NULL);
- if (PyModule_AddObjectRef(mod, "error", state->PyCursesError) < 0) {
+ if (PyModule_AddObjectRef(mod, "error", state->error) < 0) {
return -1;
}
diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c
index 331275076d7..50cf3c57491 100644
--- a/Modules/_hashopenssl.c
+++ b/Modules/_hashopenssl.c
@@ -260,7 +260,7 @@ static PyModuleDef _hashlibmodule;
typedef struct {
PyTypeObject *HASH_type; // based on EVP_MD
- PyTypeObject *HMACtype;
+ PyTypeObject *HMAC_type;
#ifdef PY_OPENSSL_HAS_SHAKE
PyTypeObject *HASHXOF_type; // based on EVP_MD
#endif
@@ -300,11 +300,11 @@ typedef struct {
#include "clinic/_hashopenssl.c.h"
/*[clinic input]
module _hashlib
-class _hashlib.HASH "HASHobject *" "((_hashlibstate *)PyModule_GetState(module))->EVPtype"
-class _hashlib.HASHXOF "HASHobject *" "((_hashlibstate *)PyModule_GetState(module))->EVPXOFtype"
-class _hashlib.HMAC "HMACobject *" "((_hashlibstate *)PyModule_GetState(module))->HMACtype"
+class _hashlib.HASH "HASHobject *" "((_hashlibstate *)PyModule_GetState(module))->HASH_type"
+class _hashlib.HASHXOF "HASHobject *" "((_hashlibstate *)PyModule_GetState(module))->HASHXOF_type"
+class _hashlib.HMAC "HMACobject *" "((_hashlibstate *)PyModule_GetState(module))->HMAC_type"
[clinic start generated code]*/
-/*[clinic end generated code: output=da39a3ee5e6b4b0d input=4f6b8873ed13d1ff]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=eb805ce4b90b1b31]*/
/* LCOV_EXCL_START */
@@ -368,41 +368,83 @@ notify_ssl_error_occurred(void)
}
/* LCOV_EXCL_STOP */
-static const char *
-get_openssl_evp_md_utf8name(const EVP_MD *md)
-{
- assert(md != NULL);
- int nid = EVP_MD_nid(md);
- const char *name = NULL;
- const py_hashentry_t *h;
+/*
+ * OpenSSL provides a way to go from NIDs to digest names for hash functions
+ * but lacks this granularity for MAC objects where it is not possible to get
+ * the underlying digest name (only the block size and digest size are allowed
+ * to be recovered).
+ *
+ * In addition, OpenSSL aliases pollute the list of known digest names
+ * as OpenSSL appears to have its own definition of alias. In particular,
+ * the resulting list still contains duplicate and alternate names for several
+ * algorithms.
+ *
+ * Therefore, digest names, whether they are used by hash functions or HMAC,
+ * are handled through EVP_MD objects or directly by using some NID.
+ */
- for (h = py_hashes; h->py_name != NULL; h++) {
+/* Get a cached entry by OpenSSL NID. */
+static const py_hashentry_t *
+get_hashentry_by_nid(int nid)
+{
+ for (const py_hashentry_t *h = py_hashes; h->py_name != NULL; h++) {
if (h->ossl_nid == nid) {
- name = h->py_name;
- break;
+ return h;
}
}
+ return NULL;
+}
+
+/*
+ * Convert the NID to a string via OBJ_nid2*() functions.
+ *
+ * If 'nid' cannot be resolved, set an exception and return NULL.
+ */
+static const char *
+get_asn1_utf8name_by_nid(int nid)
+{
+ const char *name = OBJ_nid2ln(nid);
if (name == NULL) {
- /* Ignore aliased names and only use long, lowercase name. The aliases
- * pollute the list and OpenSSL appears to have its own definition of
- * alias as the resulting list still contains duplicate and alternate
- * names for several algorithms.
- */
- name = OBJ_nid2ln(nid);
- if (name == NULL)
- name = OBJ_nid2sn(nid);
+ // In OpenSSL 3.0 and later, OBJ_nid*() are thread-safe and may raise.
+ assert(ERR_peek_last_error() != 0);
+ if (ERR_GET_REASON(ERR_peek_last_error()) != OBJ_R_UNKNOWN_NID) {
+ notify_ssl_error_occurred();
+ return NULL;
+ }
+ // fallback to short name and unconditionally propagate errors
+ name = OBJ_nid2sn(nid);
+ if (name == NULL) {
+ raise_ssl_error(PyExc_ValueError, "cannot resolve NID %d", nid);
+ }
}
return name;
}
-static PyObject *
-get_openssl_evp_md_name(const EVP_MD *md)
+/*
+ * Convert the NID to an OpenSSL digest name.
+ *
+ * On error, set an exception and return NULL.
+ */
+static const char *
+get_hashlib_utf8name_by_nid(int nid)
+{
+ const py_hashentry_t *e = get_hashentry_by_nid(nid);
+ return e ? e->py_name : get_asn1_utf8name_by_nid(nid);
+}
+
+/* Same as get_hashlib_utf8name_by_nid() but using an EVP_MD object. */
+static const char *
+get_hashlib_utf8name_by_evp_md(const EVP_MD *md)
{
- const char *name = get_openssl_evp_md_utf8name(md);
- return PyUnicode_FromString(name);
+ assert(md != NULL);
+ return get_hashlib_utf8name_by_nid(EVP_MD_nid(md));
}
-/* Get EVP_MD by HID and purpose */
+/*
+ * Get a new reference to an EVP_MD object described by name and purpose.
+ *
+ * If 'name' is an OpenSSL indexed name, the return value is cached.
+ */
static PY_EVP_MD *
get_openssl_evp_md_by_utf8name(PyObject *module, const char *name,
Py_hash_type py_ht)
@@ -471,42 +513,46 @@ get_openssl_evp_md_by_utf8name(PyObject *module, const char *name,
return digest;
}
-/* Get digest EVP_MD from object
+/*
+ * Raise an exception indicating that 'digestmod' is not supported.
+ */
+static void
+raise_unsupported_digestmod_error(PyObject *module, PyObject *digestmod)
+{
+ _hashlibstate *state = get_hashlib_state(module);
+ PyErr_Format(state->unsupported_digestmod_error,
+ "Unsupported digestmod %R", digestmod);
+}
+
+/*
+ * Get a new reference to an EVP_MD described by 'digestmod' and purpose.
+ *
+ * On error, set an exception and return NULL.
*
- * * string
- * * _hashopenssl builtin function
+ * Parameters
*
- * on error returns NULL with exception set.
+ * digestmod A digest name or a _hashopenssl builtin function
+ * py_ht The message digest purpose.
*/
static PY_EVP_MD *
-get_openssl_evp_md(PyObject *module, PyObject *digestmod,
- Py_hash_type py_ht)
+get_openssl_evp_md(PyObject *module, PyObject *digestmod, Py_hash_type py_ht)
{
- 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_GetItemWithError(state->constructs, digestmod);
+ name = PyUnicode_AsUTF8(digestmod);
}
- if (name_obj == NULL) {
- if (!PyErr_Occurred()) {
- _hashlibstate *state = get_hashlib_state(module);
- PyErr_Format(
- state->unsupported_digestmod_error,
- "Unsupported digestmod %R", digestmod);
- }
- return NULL;
+ else {
+ PyObject *dict = get_hashlib_state(module)->constructs;
+ assert(dict != NULL);
+ PyObject *borrowed_ref = PyDict_GetItemWithError(dict, digestmod);
+ name = borrowed_ref == NULL ? NULL : PyUnicode_AsUTF8(borrowed_ref);
}
-
- name = PyUnicode_AsUTF8(name_obj);
if (name == NULL) {
+ if (!PyErr_Occurred()) {
+ raise_unsupported_digestmod_error(module, digestmod);
+ }
return NULL;
}
-
return get_openssl_evp_md_by_utf8name(module, name, py_ht);
}
@@ -745,7 +791,9 @@ _hashlib_HASH_get_name(PyObject *op, void *Py_UNUSED(closure))
notify_ssl_error_occurred();
return NULL;
}
- return get_openssl_evp_md_name(md);
+ const char *name = get_hashlib_utf8name_by_evp_md(md);
+ assert(name != NULL || PyErr_Occurred());
+ return name == NULL ? NULL : PyUnicode_FromString(name);
}
static PyGetSetDef HASH_getsets[] = {
@@ -1643,7 +1691,7 @@ _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, PyObject *msg_obj,
}
_hashlibstate *state = get_hashlib_state(module);
- self = PyObject_New(HMACobject, state->HMACtype);
+ self = PyObject_New(HMACobject, state->HMAC_type);
if (self == NULL) {
goto error;
}
@@ -1775,20 +1823,15 @@ _hmac_dealloc(PyObject *op)
static PyObject *
_hmac_repr(PyObject *op)
{
+ const char *digest_name;
HMACobject *self = HMACobject_CAST(op);
const EVP_MD *md = _hashlib_hmac_get_md(self);
- if (md == NULL) {
- return NULL;
- }
- PyObject *digest_name = get_openssl_evp_md_name(md);
+ digest_name = md == NULL ? NULL : get_hashlib_utf8name_by_evp_md(md);
if (digest_name == NULL) {
+ assert(PyErr_Occurred());
return NULL;
}
- PyObject *repr = PyUnicode_FromFormat(
- "<%U HMAC object @ %p>", digest_name, self
- );
- Py_DECREF(digest_name);
- return repr;
+ return PyUnicode_FromFormat("<%s HMAC object @ %p>", digest_name, self);
}
/*[clinic input]
@@ -1900,13 +1943,12 @@ _hashlib_hmac_get_name(PyObject *op, void *Py_UNUSED(closure))
if (md == NULL) {
return NULL;
}
- PyObject *digest_name = get_openssl_evp_md_name(md);
+ const char *digest_name = get_hashlib_utf8name_by_evp_md(md);
if (digest_name == NULL) {
+ assert(PyErr_Occurred());
return NULL;
}
- PyObject *name = PyUnicode_FromFormat("hmac-%U", digest_name);
- Py_DECREF(digest_name);
- return name;
+ return PyUnicode_FromFormat("hmac-%s", digest_name);
}
static PyMethodDef HMAC_methods[] = {
@@ -1982,7 +2024,9 @@ _openssl_hash_name_mapper(const EVP_MD *md, const char *from,
return;
}
- py_name = get_openssl_evp_md_name(md);
+ const char *name = get_hashlib_utf8name_by_evp_md(md);
+ assert(name != NULL || PyErr_Occurred());
+ py_name = name == NULL ? NULL : PyUnicode_FromString(name);
if (py_name == NULL) {
state->error = 1;
} else {
@@ -2204,7 +2248,7 @@ hashlib_traverse(PyObject *m, visitproc visit, void *arg)
{
_hashlibstate *state = get_hashlib_state(m);
Py_VISIT(state->HASH_type);
- Py_VISIT(state->HMACtype);
+ Py_VISIT(state->HMAC_type);
#ifdef PY_OPENSSL_HAS_SHAKE
Py_VISIT(state->HASHXOF_type);
#endif
@@ -2218,7 +2262,7 @@ hashlib_clear(PyObject *m)
{
_hashlibstate *state = get_hashlib_state(m);
Py_CLEAR(state->HASH_type);
- Py_CLEAR(state->HMACtype);
+ Py_CLEAR(state->HMAC_type);
#ifdef PY_OPENSSL_HAS_SHAKE
Py_CLEAR(state->HASHXOF_type);
#endif
@@ -2296,11 +2340,11 @@ hashlib_init_hmactype(PyObject *module)
{
_hashlibstate *state = get_hashlib_state(module);
- state->HMACtype = (PyTypeObject *)PyType_FromSpec(&HMACtype_spec);
- if (state->HMACtype == NULL) {
+ state->HMAC_type = (PyTypeObject *)PyType_FromSpec(&HMACtype_spec);
+ if (state->HMAC_type == NULL) {
return -1;
}
- if (PyModule_AddType(module, state->HMACtype) < 0) {
+ if (PyModule_AddType(module, state->HMAC_type) < 0) {
return -1;
}
return 0;
diff --git a/Modules/_json.c b/Modules/_json.c
index 57678ad595f..6b5f6ea42df 100644
--- a/Modules/_json.c
+++ b/Modules/_json.c
@@ -1603,6 +1603,12 @@ encoder_encode_key_value(PyEncoderObject *s, PyUnicodeWriter *writer, bool *firs
if (*first) {
*first = false;
+ if (s->indent != Py_None) {
+ if (write_newline_indent(writer, indent_level, indent_cache) < 0) {
+ Py_DECREF(keystr);
+ return -1;
+ }
+ }
}
else {
if (PyUnicodeWriter_WriteStr(writer, item_separator) < 0) {
@@ -1670,11 +1676,8 @@ encoder_listencode_dict(PyEncoderObject *s, PyUnicodeWriter *writer,
if (s->indent != Py_None) {
indent_level++;
separator = get_item_separator(s, indent_level, indent_cache);
- if (separator == NULL ||
- write_newline_indent(writer, indent_level, indent_cache) < 0)
- {
+ if (separator == NULL)
goto bail;
- }
}
if (s->sort_keys || !PyDict_CheckExact(dct)) {
@@ -1714,7 +1717,7 @@ encoder_listencode_dict(PyEncoderObject *s, PyUnicodeWriter *writer,
goto bail;
Py_CLEAR(ident);
}
- if (s->indent != Py_None) {
+ if (s->indent != Py_None && !first) {
indent_level--;
if (write_newline_indent(writer, indent_level, indent_cache) < 0) {
goto bail;
diff --git a/Modules/_testcapi/unicode.c b/Modules/_testcapi/unicode.c
index e70f5c68bc3..203282dd53d 100644
--- a/Modules/_testcapi/unicode.c
+++ b/Modules/_testcapi/unicode.c
@@ -220,6 +220,12 @@ unicode_copycharacters(PyObject *self, PyObject *args)
return Py_BuildValue("(Nn)", to_copy, copied);
}
+static PyObject*
+unicode_GET_CACHED_HASH(PyObject *self, PyObject *arg)
+{
+ return PyLong_FromSsize_t(PyUnstable_Unicode_GET_CACHED_HASH(arg));
+}
+
// --- PyUnicodeWriter type -------------------------------------------------
@@ -570,6 +576,7 @@ static PyMethodDef TestMethods[] = {
{"unicode_asucs4copy", unicode_asucs4copy, METH_VARARGS},
{"unicode_asutf8", unicode_asutf8, METH_VARARGS},
{"unicode_copycharacters", unicode_copycharacters, METH_VARARGS},
+ {"unicode_GET_CACHED_HASH", unicode_GET_CACHED_HASH, METH_O},
{NULL},
};
diff --git a/Modules/_zstd/_zstdmodule.c b/Modules/_zstd/_zstdmodule.c
index b0e50f873f4..d75c0779474 100644
--- a/Modules/_zstd/_zstdmodule.c
+++ b/Modules/_zstd/_zstdmodule.c
@@ -72,6 +72,9 @@ set_zstd_error(const _zstd_state *state, error_type type, size_t zstd_ret)
case ERR_COMPRESS:
msg = "Unable to compress Zstandard data: %s";
break;
+ case ERR_SET_PLEDGED_INPUT_SIZE:
+ msg = "Unable to set pledged uncompressed content size: %s";
+ break;
case ERR_LOAD_D_DICT:
msg = "Unable to load Zstandard dictionary or prefix for "
diff --git a/Modules/_zstd/_zstdmodule.h b/Modules/_zstd/_zstdmodule.h
index c73f15b3c52..4e8f708f223 100644
--- a/Modules/_zstd/_zstdmodule.h
+++ b/Modules/_zstd/_zstdmodule.h
@@ -27,6 +27,7 @@ typedef struct {
typedef enum {
ERR_DECOMPRESS,
ERR_COMPRESS,
+ ERR_SET_PLEDGED_INPUT_SIZE,
ERR_LOAD_D_DICT,
ERR_LOAD_C_DICT,
diff --git a/Modules/_zstd/clinic/compressor.c.h b/Modules/_zstd/clinic/compressor.c.h
index f69161b590e..4f8d93fd9e8 100644
--- a/Modules/_zstd/clinic/compressor.c.h
+++ b/Modules/_zstd/clinic/compressor.c.h
@@ -252,4 +252,43 @@ skip_optional_pos:
exit:
return return_value;
}
-/*[clinic end generated code: output=ee2d1dc298de790c input=a9049054013a1b77]*/
+
+PyDoc_STRVAR(_zstd_ZstdCompressor_set_pledged_input_size__doc__,
+"set_pledged_input_size($self, size, /)\n"
+"--\n"
+"\n"
+"Set the uncompressed content size to be written into the frame header.\n"
+"\n"
+" size\n"
+" The size of the uncompressed data to be provided to the compressor.\n"
+"\n"
+"This method can be used to ensure the header of the frame about to be written\n"
+"includes the size of the data, unless the CompressionParameter.content_size_flag\n"
+"is set to False. If last_mode != FLUSH_FRAME, then a RuntimeError is raised.\n"
+"\n"
+"It is important to ensure that the pledged data size matches the actual data\n"
+"size. If they do not match the compressed output data may be corrupted and the\n"
+"final chunk written may be lost.");
+
+#define _ZSTD_ZSTDCOMPRESSOR_SET_PLEDGED_INPUT_SIZE_METHODDEF \
+ {"set_pledged_input_size", (PyCFunction)_zstd_ZstdCompressor_set_pledged_input_size, METH_O, _zstd_ZstdCompressor_set_pledged_input_size__doc__},
+
+static PyObject *
+_zstd_ZstdCompressor_set_pledged_input_size_impl(ZstdCompressor *self,
+ unsigned long long size);
+
+static PyObject *
+_zstd_ZstdCompressor_set_pledged_input_size(PyObject *self, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ unsigned long long size;
+
+ if (!zstd_contentsize_converter(arg, &size)) {
+ goto exit;
+ }
+ return_value = _zstd_ZstdCompressor_set_pledged_input_size_impl((ZstdCompressor *)self, size);
+
+exit:
+ return return_value;
+}
+/*[clinic end generated code: output=c1d5c2cf06a8becd input=a9049054013a1b77]*/
diff --git a/Modules/_zstd/compressor.c b/Modules/_zstd/compressor.c
index e1217635f60..bc9e6eff89a 100644
--- a/Modules/_zstd/compressor.c
+++ b/Modules/_zstd/compressor.c
@@ -45,6 +45,52 @@ typedef struct {
#define ZstdCompressor_CAST(op) ((ZstdCompressor *)op)
+/*[python input]
+
+class zstd_contentsize_converter(CConverter):
+ type = 'unsigned long long'
+ converter = 'zstd_contentsize_converter'
+
+[python start generated code]*/
+/*[python end generated code: output=da39a3ee5e6b4b0d input=0932c350d633c7de]*/
+
+
+static int
+zstd_contentsize_converter(PyObject *size, unsigned long long *p)
+{
+ // None means the user indicates the size is unknown.
+ if (size == Py_None) {
+ *p = ZSTD_CONTENTSIZE_UNKNOWN;
+ }
+ else {
+ /* ZSTD_CONTENTSIZE_UNKNOWN is 0ULL - 1
+ ZSTD_CONTENTSIZE_ERROR is 0ULL - 2
+ Users should only pass values < ZSTD_CONTENTSIZE_ERROR */
+ unsigned long long pledged_size = PyLong_AsUnsignedLongLong(size);
+ /* Here we check for (unsigned long long)-1 as a sign of an error in
+ PyLong_AsUnsignedLongLong */
+ if (pledged_size == (unsigned long long)-1 && PyErr_Occurred()) {
+ *p = ZSTD_CONTENTSIZE_ERROR;
+ if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
+ PyErr_Format(PyExc_ValueError,
+ "size argument should be a positive int less "
+ "than %ull", ZSTD_CONTENTSIZE_ERROR);
+ return 0;
+ }
+ return 0;
+ }
+ if (pledged_size >= ZSTD_CONTENTSIZE_ERROR) {
+ *p = ZSTD_CONTENTSIZE_ERROR;
+ PyErr_Format(PyExc_ValueError,
+ "size argument should be a positive int less "
+ "than %ull", ZSTD_CONTENTSIZE_ERROR);
+ return 0;
+ }
+ *p = pledged_size;
+ }
+ return 1;
+}
+
#include "clinic/compressor.c.h"
static int
@@ -643,9 +689,61 @@ _zstd_ZstdCompressor_flush_impl(ZstdCompressor *self, int mode)
return ret;
}
+
+/*[clinic input]
+_zstd.ZstdCompressor.set_pledged_input_size
+
+ size: zstd_contentsize
+ The size of the uncompressed data to be provided to the compressor.
+ /
+
+Set the uncompressed content size to be written into the frame header.
+
+This method can be used to ensure the header of the frame about to be written
+includes the size of the data, unless the CompressionParameter.content_size_flag
+is set to False. If last_mode != FLUSH_FRAME, then a RuntimeError is raised.
+
+It is important to ensure that the pledged data size matches the actual data
+size. If they do not match the compressed output data may be corrupted and the
+final chunk written may be lost.
+[clinic start generated code]*/
+
+static PyObject *
+_zstd_ZstdCompressor_set_pledged_input_size_impl(ZstdCompressor *self,
+ unsigned long long size)
+/*[clinic end generated code: output=3a09e55cc0e3b4f9 input=afd8a7d78cff2eb5]*/
+{
+ // Error occured while converting argument, should be unreachable
+ assert(size != ZSTD_CONTENTSIZE_ERROR);
+
+ /* Thread-safe code */
+ PyMutex_Lock(&self->lock);
+
+ /* Check the current mode */
+ if (self->last_mode != ZSTD_e_end) {
+ PyErr_SetString(PyExc_ValueError,
+ "set_pledged_input_size() method must be called "
+ "when last_mode == FLUSH_FRAME");
+ PyMutex_Unlock(&self->lock);
+ return NULL;
+ }
+
+ /* Set pledged content size */
+ size_t zstd_ret = ZSTD_CCtx_setPledgedSrcSize(self->cctx, size);
+ PyMutex_Unlock(&self->lock);
+ if (ZSTD_isError(zstd_ret)) {
+ _zstd_state* mod_state = PyType_GetModuleState(Py_TYPE(self));
+ set_zstd_error(mod_state, ERR_SET_PLEDGED_INPUT_SIZE, zstd_ret);
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
static PyMethodDef ZstdCompressor_methods[] = {
_ZSTD_ZSTDCOMPRESSOR_COMPRESS_METHODDEF
_ZSTD_ZSTDCOMPRESSOR_FLUSH_METHODDEF
+ _ZSTD_ZSTDCOMPRESSOR_SET_PLEDGED_INPUT_SIZE_METHODDEF
{NULL, NULL}
};
diff --git a/Modules/clinic/_curses_panel.c.h b/Modules/clinic/_curses_panel.c.h
index 6f4966825ec..75cf067c8aa 100644
--- a/Modules/clinic/_curses_panel.c.h
+++ b/Modules/clinic/_curses_panel.c.h
@@ -2,10 +2,7 @@
preserve
[clinic start generated code]*/
-#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
-# include "pycore_runtime.h" // _Py_SINGLETON()
-#endif
-#include "pycore_modsupport.h" // _PyArg_UnpackKeywords()
+#include "pycore_modsupport.h" // _PyArg_CheckPositional()
PyDoc_STRVAR(_curses_panel_panel_bottom__doc__,
"bottom($self, /)\n"
@@ -14,19 +11,15 @@ PyDoc_STRVAR(_curses_panel_panel_bottom__doc__,
"Push the panel to the bottom of the stack.");
#define _CURSES_PANEL_PANEL_BOTTOM_METHODDEF \
- {"bottom", _PyCFunction_CAST(_curses_panel_panel_bottom), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _curses_panel_panel_bottom__doc__},
+ {"bottom", (PyCFunction)_curses_panel_panel_bottom, METH_NOARGS, _curses_panel_panel_bottom__doc__},
static PyObject *
-_curses_panel_panel_bottom_impl(PyCursesPanelObject *self, PyTypeObject *cls);
+_curses_panel_panel_bottom_impl(PyCursesPanelObject *self);
static PyObject *
-_curses_panel_panel_bottom(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+_curses_panel_panel_bottom(PyObject *self, PyObject *Py_UNUSED(ignored))
{
- if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) {
- PyErr_SetString(PyExc_TypeError, "bottom() takes no arguments");
- return NULL;
- }
- return _curses_panel_panel_bottom_impl((PyCursesPanelObject *)self, cls);
+ return _curses_panel_panel_bottom_impl((PyCursesPanelObject *)self);
}
PyDoc_STRVAR(_curses_panel_panel_hide__doc__,
@@ -38,19 +31,15 @@ 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_CAST(_curses_panel_panel_hide), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _curses_panel_panel_hide__doc__},
+ {"hide", (PyCFunction)_curses_panel_panel_hide, METH_NOARGS, _curses_panel_panel_hide__doc__},
static PyObject *
-_curses_panel_panel_hide_impl(PyCursesPanelObject *self, PyTypeObject *cls);
+_curses_panel_panel_hide_impl(PyCursesPanelObject *self);
static PyObject *
-_curses_panel_panel_hide(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+_curses_panel_panel_hide(PyObject *self, PyObject *Py_UNUSED(ignored))
{
- if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) {
- PyErr_SetString(PyExc_TypeError, "hide() takes no arguments");
- return NULL;
- }
- return _curses_panel_panel_hide_impl((PyCursesPanelObject *)self, cls);
+ return _curses_panel_panel_hide_impl((PyCursesPanelObject *)self);
}
PyDoc_STRVAR(_curses_panel_panel_show__doc__,
@@ -60,19 +49,15 @@ PyDoc_STRVAR(_curses_panel_panel_show__doc__,
"Display the panel (which might have been hidden).");
#define _CURSES_PANEL_PANEL_SHOW_METHODDEF \
- {"show", _PyCFunction_CAST(_curses_panel_panel_show), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _curses_panel_panel_show__doc__},
+ {"show", (PyCFunction)_curses_panel_panel_show, METH_NOARGS, _curses_panel_panel_show__doc__},
static PyObject *
-_curses_panel_panel_show_impl(PyCursesPanelObject *self, PyTypeObject *cls);
+_curses_panel_panel_show_impl(PyCursesPanelObject *self);
static PyObject *
-_curses_panel_panel_show(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+_curses_panel_panel_show(PyObject *self, PyObject *Py_UNUSED(ignored))
{
- if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) {
- PyErr_SetString(PyExc_TypeError, "show() takes no arguments");
- return NULL;
- }
- return _curses_panel_panel_show_impl((PyCursesPanelObject *)self, cls);
+ return _curses_panel_panel_show_impl((PyCursesPanelObject *)self);
}
PyDoc_STRVAR(_curses_panel_panel_top__doc__,
@@ -82,19 +67,15 @@ PyDoc_STRVAR(_curses_panel_panel_top__doc__,
"Push panel to the top of the stack.");
#define _CURSES_PANEL_PANEL_TOP_METHODDEF \
- {"top", _PyCFunction_CAST(_curses_panel_panel_top), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _curses_panel_panel_top__doc__},
+ {"top", (PyCFunction)_curses_panel_panel_top, METH_NOARGS, _curses_panel_panel_top__doc__},
static PyObject *
-_curses_panel_panel_top_impl(PyCursesPanelObject *self, PyTypeObject *cls);
+_curses_panel_panel_top_impl(PyCursesPanelObject *self);
static PyObject *
-_curses_panel_panel_top(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+_curses_panel_panel_top(PyObject *self, PyObject *Py_UNUSED(ignored))
{
- if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) {
- PyErr_SetString(PyExc_TypeError, "top() takes no arguments");
- return NULL;
- }
- return _curses_panel_panel_top_impl((PyCursesPanelObject *)self, cls);
+ return _curses_panel_panel_top_impl((PyCursesPanelObject *)self);
}
PyDoc_STRVAR(_curses_panel_panel_above__doc__,
@@ -158,36 +139,19 @@ PyDoc_STRVAR(_curses_panel_panel_move__doc__,
"Move the panel to the screen coordinates (y, x).");
#define _CURSES_PANEL_PANEL_MOVE_METHODDEF \
- {"move", _PyCFunction_CAST(_curses_panel_panel_move), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _curses_panel_panel_move__doc__},
+ {"move", _PyCFunction_CAST(_curses_panel_panel_move), METH_FASTCALL, _curses_panel_panel_move__doc__},
static PyObject *
-_curses_panel_panel_move_impl(PyCursesPanelObject *self, PyTypeObject *cls,
- int y, int x);
+_curses_panel_panel_move_impl(PyCursesPanelObject *self, int y, int x);
static PyObject *
-_curses_panel_panel_move(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+_curses_panel_panel_move(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
- #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty)
- #else
- # define KWTUPLE NULL
- #endif
-
- static const char * const _keywords[] = {"", "", NULL};
- static _PyArg_Parser _parser = {
- .keywords = _keywords,
- .fname = "move",
- .kwtuple = KWTUPLE,
- };
- #undef KWTUPLE
- PyObject *argsbuf[2];
int y;
int x;
- args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
- /*minpos*/ 2, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
- if (!args) {
+ if (!_PyArg_CheckPositional("move", nargs, 2, 2)) {
goto exit;
}
y = PyLong_AsInt(args[0]);
@@ -198,7 +162,7 @@ _curses_panel_panel_move(PyObject *self, PyTypeObject *cls, PyObject *const *arg
if (x == -1 && PyErr_Occurred()) {
goto exit;
}
- return_value = _curses_panel_panel_move_impl((PyCursesPanelObject *)self, cls, y, x);
+ return_value = _curses_panel_panel_move_impl((PyCursesPanelObject *)self, y, x);
exit:
return return_value;
@@ -229,44 +193,24 @@ 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_CAST(_curses_panel_panel_replace), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _curses_panel_panel_replace__doc__},
+ {"replace", (PyCFunction)_curses_panel_panel_replace, METH_O, _curses_panel_panel_replace__doc__},
static PyObject *
_curses_panel_panel_replace_impl(PyCursesPanelObject *self,
- PyTypeObject *cls,
PyCursesWindowObject *win);
static PyObject *
-_curses_panel_panel_replace(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+_curses_panel_panel_replace(PyObject *self, PyObject *arg)
{
PyObject *return_value = NULL;
- #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty)
- #else
- # define KWTUPLE NULL
- #endif
-
- static const char * const _keywords[] = {"", NULL};
- static _PyArg_Parser _parser = {
- .keywords = _keywords,
- .fname = "replace",
- .kwtuple = KWTUPLE,
- };
- #undef KWTUPLE
- PyObject *argsbuf[1];
PyCursesWindowObject *win;
- args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
- /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
- if (!args) {
- goto exit;
- }
- if (!PyObject_TypeCheck(args[0], &PyCursesWindow_Type)) {
- _PyArg_BadArgument("replace", "argument 1", (&PyCursesWindow_Type)->tp_name, args[0]);
+ if (!PyObject_TypeCheck(arg, &PyCursesWindow_Type)) {
+ _PyArg_BadArgument("replace", "argument", (&PyCursesWindow_Type)->tp_name, arg);
goto exit;
}
- win = (PyCursesWindowObject *)args[0];
- return_value = _curses_panel_panel_replace_impl((PyCursesPanelObject *)self, cls, win);
+ win = (PyCursesWindowObject *)arg;
+ return_value = _curses_panel_panel_replace_impl((PyCursesPanelObject *)self, win);
exit:
return return_value;
@@ -279,41 +223,19 @@ 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_CAST(_curses_panel_panel_set_userptr), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _curses_panel_panel_set_userptr__doc__},
+ {"set_userptr", (PyCFunction)_curses_panel_panel_set_userptr, METH_O, _curses_panel_panel_set_userptr__doc__},
static PyObject *
_curses_panel_panel_set_userptr_impl(PyCursesPanelObject *self,
- PyTypeObject *cls, PyObject *obj);
+ PyObject *obj);
static PyObject *
-_curses_panel_panel_set_userptr(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+_curses_panel_panel_set_userptr(PyObject *self, PyObject *obj)
{
PyObject *return_value = NULL;
- #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- # define KWTUPLE (PyObject *)&_Py_SINGLETON(tuple_empty)
- #else
- # define KWTUPLE NULL
- #endif
-
- static const char * const _keywords[] = {"", NULL};
- static _PyArg_Parser _parser = {
- .keywords = _keywords,
- .fname = "set_userptr",
- .kwtuple = KWTUPLE,
- };
- #undef KWTUPLE
- PyObject *argsbuf[1];
- PyObject *obj;
-
- args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
- /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
- if (!args) {
- goto exit;
- }
- obj = args[0];
- return_value = _curses_panel_panel_set_userptr_impl((PyCursesPanelObject *)self, cls, obj);
-exit:
+ return_value = _curses_panel_panel_set_userptr_impl((PyCursesPanelObject *)self, obj);
+
return return_value;
}
@@ -324,20 +246,15 @@ PyDoc_STRVAR(_curses_panel_panel_userptr__doc__,
"Return the user pointer for the panel.");
#define _CURSES_PANEL_PANEL_USERPTR_METHODDEF \
- {"userptr", _PyCFunction_CAST(_curses_panel_panel_userptr), METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _curses_panel_panel_userptr__doc__},
+ {"userptr", (PyCFunction)_curses_panel_panel_userptr, METH_NOARGS, _curses_panel_panel_userptr__doc__},
static PyObject *
-_curses_panel_panel_userptr_impl(PyCursesPanelObject *self,
- PyTypeObject *cls);
+_curses_panel_panel_userptr_impl(PyCursesPanelObject *self);
static PyObject *
-_curses_panel_panel_userptr(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+_curses_panel_panel_userptr(PyObject *self, PyObject *Py_UNUSED(ignored))
{
- if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) {
- PyErr_SetString(PyExc_TypeError, "userptr() takes no arguments");
- return NULL;
- }
- return _curses_panel_panel_userptr_impl((PyCursesPanelObject *)self, cls);
+ return _curses_panel_panel_userptr_impl((PyCursesPanelObject *)self);
}
PyDoc_STRVAR(_curses_panel_bottom_panel__doc__,
@@ -424,4 +341,4 @@ _curses_panel_update_panels(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return _curses_panel_update_panels_impl(module);
}
-/*[clinic end generated code: output=36853ecb4a979814 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=db2fe491582784aa input=a9049054013a1b77]*/
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 588894adeac..7dc5ef39a56 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -8820,14 +8820,14 @@ os_ptsname_impl(PyObject *module, int fd)
#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
#ifdef HAVE_PTY_H
#include <pty.h>
-#ifdef HAVE_UTMP_H
-#include <utmp.h>
-#endif /* HAVE_UTMP_H */
#elif defined(HAVE_LIBUTIL_H)
#include <libutil.h>
#elif defined(HAVE_UTIL_H)
#include <util.h>
#endif /* HAVE_PTY_H */
+#ifdef HAVE_UTMP_H
+#include <utmp.h>
+#endif /* HAVE_UTMP_H */
#ifdef HAVE_STROPTS_H
#include <stropts.h>
#endif
@@ -9562,6 +9562,24 @@ os_getlogin_impl(PyObject *module)
}
else
result = PyErr_SetFromWindowsErr(GetLastError());
+#elif defined (HAVE_GETLOGIN_R)
+# if defined (HAVE_MAXLOGNAME)
+ char name[MAXLOGNAME + 1];
+# elif defined (HAVE_UT_NAMESIZE)
+ char name[UT_NAMESIZE + 1];
+# else
+ char name[256];
+# endif
+ int err = getlogin_r(name, sizeof(name));
+ if (err) {
+ int old_errno = errno;
+ errno = -err;
+ posix_error();
+ errno = old_errno;
+ }
+ else {
+ result = PyUnicode_DecodeFSDefault(name);
+ }
#else
char *name;
int old_errno = errno;
diff --git a/Modules/xxlimited.c b/Modules/xxlimited.c
index 26ac35734fb..0480fb08498 100644
--- a/Modules/xxlimited.c
+++ b/Modules/xxlimited.c
@@ -424,6 +424,13 @@ xx_clear(PyObject *module)
return 0;
}
+static void
+xx_free(void *module)
+{
+ // allow xx_modexec to omit calling xx_clear on error
+ (void)xx_clear((PyObject *)module);
+}
+
static struct PyModuleDef xxmodule = {
PyModuleDef_HEAD_INIT,
.m_name = "xxlimited",
@@ -433,9 +440,7 @@ static struct PyModuleDef xxmodule = {
.m_slots = xx_slots,
.m_traverse = xx_traverse,
.m_clear = xx_clear,
- /* m_free is not necessary here: xx_clear clears all references,
- * and the module state is deallocated along with the module.
- */
+ .m_free = xx_free,
};