Skip to content

Commit

Permalink
Adapt the CPython 3.9+ C-API usage to use newer macros (#864)
Browse files Browse the repository at this point in the history
This patch replaces the C-APIs that have been deprecated in Python 3.9 and later removed in 3.13.
  • Loading branch information
iemelyanov committed Dec 26, 2023
1 parent d2959d0 commit 780a1e1
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 24 deletions.
2 changes: 2 additions & 0 deletions CHANGES/864.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Upgraded the C-API macros that have been deprecated in
Python 3.9 and later removed in 3.13 -- :user:`webknjaz`.
28 changes: 26 additions & 2 deletions multidict/_multidict.c
Original file line number Diff line number Diff line change
Expand Up @@ -709,13 +709,21 @@ static inline void
multidict_tp_dealloc(MultiDictObject *self)
{
PyObject_GC_UnTrack(self);
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 9
Py_TRASHCAN_BEGIN(self, multidict_tp_dealloc)
#else
Py_TRASHCAN_SAFE_BEGIN(self);
#endif
if (self->weaklist != NULL) {
PyObject_ClearWeakRefs((PyObject *)self);
};
pair_list_dealloc(&self->pairs);
Py_TYPE(self)->tp_free((PyObject *)self);
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 9
Py_TRASHCAN_END // there should be no code after this
#else
Py_TRASHCAN_SAFE_END(self);
#endif
}

static inline int
Expand Down Expand Up @@ -777,9 +785,12 @@ multidict_add(MultiDictObject *self, PyObject *const *args,
return NULL;
}
#else
static _PyArg_Parser _parser = {NULL, _keywords, "add", 0};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "add",
.kwtuple = NULL,
};
PyObject *argsbuf[2];

args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames,
&_parser, 2, 2, 0, argsbuf);
if (!args) {
Expand Down Expand Up @@ -1655,6 +1666,9 @@ getversion(PyObject *self, PyObject *md)
static inline void
module_free(void *m)
{
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 9
Py_CLEAR(multidict_str_lower);
#endif
Py_CLEAR(collections_abc_mapping);
Py_CLEAR(collections_abc_mut_mapping);
Py_CLEAR(collections_abc_mut_multi_mapping);
Expand Down Expand Up @@ -1683,6 +1697,13 @@ static PyModuleDef multidict_module = {
PyMODINIT_FUNC
PyInit__multidict()
{
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 9
multidict_str_lower = PyUnicode_InternFromString("lower");
if (multidict_str_lower == NULL) {
goto fail;
}
#endif

PyObject *module = NULL,
*reg_func_call_result = NULL;

Expand Down Expand Up @@ -1813,6 +1834,9 @@ PyInit__multidict()
return module;

fail:
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 9
Py_XDECREF(multidict_str_lower);
#endif
Py_XDECREF(collections_abc_mapping);
Py_XDECREF(collections_abc_mut_mapping);
Py_XDECREF(collections_abc_mut_multi_mapping);
Expand Down
4 changes: 4 additions & 0 deletions multidict/_multilib/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
extern "C" {
#endif

#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 9
static PyObject *multidict_str_lower = NULL;
#else
_Py_IDENTIFIER(lower);
#endif

/* We link this module statically for convenience. If compiled as a shared
library instead, some compilers don't allow addresses of Python objects
Expand Down
4 changes: 4 additions & 0 deletions multidict/_multilib/istr.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ istr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
if (!ret) {
goto fail;
}
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 9
s = PyObject_CallMethodNoArgs(ret, multidict_str_lower);
#else
s =_PyObject_CallMethodId(ret, &PyId_lower, NULL);
#endif
if (!s) {
goto fail;
}
Expand Down
55 changes: 33 additions & 22 deletions multidict/_multilib/pair_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ extern "C" {
#include <string.h>
#include <stddef.h>
#include <stdint.h>

typedef PyObject * (*calc_identity_func)(PyObject *key);
#include <stdbool.h>

typedef struct pair {
PyObject *identity; // 8
Expand Down Expand Up @@ -38,12 +37,12 @@ HTTP headers into the buffer without allocating an extra memory block.
#define EMBEDDED_CAPACITY 29
#endif

typedef struct pair_list { // 40
Py_ssize_t capacity; // 8
Py_ssize_t size; // 8
uint64_t version; // 8
calc_identity_func calc_identity; // 8
pair_t *pairs; // 8
typedef struct pair_list {
Py_ssize_t capacity;
Py_ssize_t size;
uint64_t version;
bool calc_ci_indentity;
pair_t *pairs;
pair_t buffer[EMBEDDED_CAPACITY];
} pair_list_t;

Expand Down Expand Up @@ -111,7 +110,11 @@ ci_key_to_str(PyObject *key)
return ret;
}
if (PyUnicode_Check(key)) {
#if PY_VERSION_HEX < 0x03090000
return _PyObject_CallMethodId(key, &PyId_lower, NULL);
#else
return PyObject_CallMethodNoArgs(key, multidict_str_lower);
#endif
}
PyErr_SetString(PyExc_TypeError,
"CIMultiDict keys should be either str "
Expand Down Expand Up @@ -199,30 +202,38 @@ pair_list_shrink(pair_list_t *list)


static inline int
_pair_list_init(pair_list_t *list, calc_identity_func calc_identity)
_pair_list_init(pair_list_t *list, bool calc_ci_identity)
{
list->calc_ci_indentity = calc_ci_identity;
list->pairs = list->buffer;
list->capacity = EMBEDDED_CAPACITY;
list->size = 0;
list->version = NEXT_VERSION();
list->calc_identity = calc_identity;
return 0;
}

static inline int
pair_list_init(pair_list_t *list)
{
return _pair_list_init(list, key_to_str);
return _pair_list_init(list, /* calc_ci_identity = */ false);
}


static inline int
ci_pair_list_init(pair_list_t *list)
{
return _pair_list_init(list, ci_key_to_str);
return _pair_list_init(list, /* calc_ci_identity = */ true);
}


static inline PyObject *
pair_list_calc_identity(pair_list_t *list, PyObject *key)
{
if (list->calc_ci_indentity)
return ci_key_to_str(key);
return key_to_str(key);
}

static inline void
pair_list_dealloc(pair_list_t *list)
{
Expand Down Expand Up @@ -304,7 +315,7 @@ pair_list_add(pair_list_t *list,
PyObject *identity = NULL;
int ret;

identity = list->calc_identity(key);
identity = pair_list_calc_identity(list, key);
if (identity == NULL) {
goto fail;
}
Expand Down Expand Up @@ -412,7 +423,7 @@ pair_list_del(pair_list_t *list, PyObject *key)
Py_hash_t hash;
int ret;

identity = list->calc_identity(key);
identity = pair_list_calc_identity(list, key);
if (identity == NULL) {
goto fail;
}
Expand Down Expand Up @@ -486,7 +497,7 @@ pair_list_contains(pair_list_t *list, PyObject *key)
PyObject *identity = NULL;
int tmp;

ident = list->calc_identity(key);
ident = pair_list_calc_identity(list, key);
if (ident == NULL) {
goto fail;
}
Expand Down Expand Up @@ -528,7 +539,7 @@ pair_list_get_one(pair_list_t *list, PyObject *key)
PyObject *value = NULL;
int tmp;

ident = list->calc_identity(key);
ident = pair_list_calc_identity(list, key);
if (ident == NULL) {
goto fail;
}
Expand Down Expand Up @@ -573,7 +584,7 @@ pair_list_get_all(pair_list_t *list, PyObject *key)
PyObject *res = NULL;
int tmp;

ident = list->calc_identity(key);
ident = pair_list_calc_identity(list, key);
if (ident == NULL) {
goto fail;
}
Expand Down Expand Up @@ -631,7 +642,7 @@ pair_list_set_default(pair_list_t *list, PyObject *key, PyObject *value)
PyObject *value2 = NULL;
int tmp;

ident = list->calc_identity(key);
ident = pair_list_calc_identity(list, key);
if (ident == NULL) {
goto fail;
}
Expand Down Expand Up @@ -680,7 +691,7 @@ pair_list_pop_one(pair_list_t *list, PyObject *key)
int tmp;
PyObject *ident = NULL;

ident = list->calc_identity(key);
ident = pair_list_calc_identity(list, key);
if (ident == NULL) {
goto fail;
}
Expand Down Expand Up @@ -730,7 +741,7 @@ pair_list_pop_all(pair_list_t *list, PyObject *key)
PyObject *res = NULL;
PyObject *ident = NULL;

ident = list->calc_identity(key);
ident = pair_list_calc_identity(list, key);
if (ident == NULL) {
goto fail;
}
Expand Down Expand Up @@ -826,7 +837,7 @@ pair_list_replace(pair_list_t *list, PyObject * key, PyObject *value)
PyObject *identity = NULL;
Py_hash_t hash;

identity = list->calc_identity(key);
identity = pair_list_calc_identity(list, key);
if (identity == NULL) {
goto fail;
}
Expand Down Expand Up @@ -1101,7 +1112,7 @@ pair_list_update_from_seq(pair_list_t *list, PyObject *seq)
Py_INCREF(key);
Py_INCREF(value);

identity = list->calc_identity(key);
identity = pair_list_calc_identity(list, key);
if (identity == NULL) {
goto fail_1;
}
Expand Down

0 comments on commit 780a1e1

Please sign in to comment.