Skip to content

Commit 2b653ea

Browse files
committed
Implement MultiDict_SetDefault()
1 parent ea64d9c commit 2b653ea

6 files changed

Lines changed: 60 additions & 1 deletion

File tree

multidict/_multilib/capsule.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,18 @@ MultiDict_Clear(void *state_, PyObject *self)
6464
return md_clear((MultiDictObject *)self);
6565
}
6666

67+
static inline int
68+
MultiDict_SetDefault(void *state_, PyObject *self, PyObject *key,
69+
PyObject *default_, PyObject **result)
70+
{
71+
mod_state *state = (mod_state *)state_;
72+
if (MultiDict_Check(state, self) <= 0) {
73+
_invalid_type();
74+
return -1;
75+
}
76+
return md_set_default((MultiDictObject *)self, key, default_, result);
77+
}
78+
6779
static void
6880
capsule_free(MultiDict_CAPI *capi)
6981
{
@@ -91,6 +103,7 @@ new_capsule(mod_state *state)
91103
capi->MultiDict_New = MultiDict_New;
92104
capi->MultiDict_Add = MultiDict_Add;
93105
capi->MultiDict_Clear = MultiDict_Clear;
106+
capi->MultiDict_SetDefault = MultiDict_SetDefault;
94107

95108
PyObject *ret =
96109
PyCapsule_New(capi, MultiDict_CAPSULE_NAME, capsule_destructor);

multidict/multidict_api.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ typedef struct {
3030
int (*MultiDict_Add)(void *state, PyObject *self, PyObject *key,
3131
PyObject *value);
3232
int (*MultiDict_Clear)(void *state, PyObject *self);
33+
int (*MultiDict_SetDefault)(void *state, PyObject *self, PyObject *key,
34+
PyObject *default_, PyObject **result);
3335
} MultiDict_CAPI;
3436

3537
#ifndef MULTIDICT_IMPL
@@ -83,6 +85,13 @@ MultiDict_Clear(MultiDict_CAPI *api, PyObject *self)
8385
return api->MultiDict_Clear(api->state, self);
8486
}
8587

88+
static inline int
89+
MultiDict_SetDefault(MultiDict_CAPI *api, PyObject *self, PyObject *key,
90+
PyObject *default_, PyObject **result)
91+
{
92+
return api->MultiDict_SetDefault(api->state, self, key, default_, result);
93+
}
94+
8695
#endif
8796

8897
#ifdef __cplusplus

setup.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
NO_EXTENSIONS = True
1212

1313
CFLAGS = ["-O0", "-g3", "-UNDEBUG"] if DEBUG_BUILD else ["-O3"]
14-
1514
if platform.system() != "Windows":
1615
CFLAGS.extend(
1716
[

testcapi/setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"testcapi._api",
1010
["testcapi/_api.c"],
1111
include_dirs=multidict.__path__,
12+
extra_compile_args=["-O0", "-g3", "-UNDEBUG"],
1213
),
1314
]
1415

testcapi/testcapi/_api.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,29 @@ md_clear(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
8383
Py_RETURN_NONE;
8484
}
8585

86+
static PyObject *
87+
md_setdefault(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
88+
{
89+
printf("000000\n");
90+
mod_state *state = get_mod_state(self);
91+
if (check_nargs("md_setdefault", nargs, 3) < 0) {
92+
return NULL;
93+
}
94+
PyObject *result = NULL;
95+
int ret =
96+
MultiDict_SetDefault(state->capi, args[0], args[1], args[2], &result);
97+
if (ret < 0) {
98+
return NULL;
99+
}
100+
assert(result != NULL);
101+
PyObject *val = PyBool_FromLong(ret);
102+
if (val == NULL) {
103+
Py_CLEAR(result);
104+
return NULL;
105+
}
106+
return PyTuple_Pack(2, result, val);
107+
}
108+
86109
/* module slots */
87110

88111
static int
@@ -108,6 +131,7 @@ static PyMethodDef module_methods[] = {
108131
{"md_new", (PyCFunction)md_new, METH_FASTCALL},
109132
{"md_add", (PyCFunction)md_add, METH_FASTCALL},
110133
{"md_clear", (PyCFunction)md_clear, METH_FASTCALL},
134+
{"md_setdefault", (PyCFunction)md_setdefault, METH_FASTCALL},
111135
{NULL, NULL} /* sentinel */
112136
};
113137

tests/test_capi.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,16 @@ def test_md_clear() -> None:
3030
md: MultiDictStr = multidict.MultiDict(key="val")
3131
testcapi.md_clear(md)
3232
assert len(md) == 0
33+
34+
35+
@pytest.mark.parametrize(
36+
"key, expected",
37+
[
38+
pytest.param("key", ("val", True), id="found"),
39+
pytest.param("key2", ("default", False), id="notfound"),
40+
],
41+
)
42+
def test_md_setdefault(key: str, expected: tuple[str, bool]) -> None:
43+
md: MultiDictStr = multidict.MultiDict(key="val")
44+
ret = testcapi.md_setdefault(md, key, "default")
45+
assert ret == expected

0 commit comments

Comments
 (0)