Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 34 additions & 53 deletions msgspec/_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
#include "atof.h"

/* Python version checks */
#define PY39_PLUS (PY_VERSION_HEX >= 0x03090000)
#define PY310_PLUS (PY_VERSION_HEX >= 0x030a0000)
#define PY311_PLUS (PY_VERSION_HEX >= 0x030b0000)
#define PY312_PLUS (PY_VERSION_HEX >= 0x030c0000)
Expand Down Expand Up @@ -44,20 +43,6 @@ ms_popcount(uint64_t i) { \
}
#endif

#if PY39_PLUS
#define CALL_ONE_ARG(f, a) PyObject_CallOneArg(f, a)
#define CALL_NO_ARGS(f) PyObject_CallNoArgs(f)
#define CALL_METHOD_ONE_ARG(o, n, a) PyObject_CallMethodOneArg(o, n, a)
#define CALL_METHOD_NO_ARGS(o, n) PyObject_CallMethodNoArgs(o, n)
#define SET_SIZE(obj, size) Py_SET_SIZE(obj, size)
#else
#define CALL_ONE_ARG(f, a) PyObject_CallFunctionObjArgs(f, a, NULL)
#define CALL_NO_ARGS(f) PyObject_CallFunctionObjArgs(f, NULL)
#define CALL_METHOD_ONE_ARG(o, n, a) PyObject_CallMethodObjArgs(o, n, a, NULL)
#define CALL_METHOD_NO_ARGS(o, n) PyObject_CallMethodObjArgs(o, n, NULL)
#define SET_SIZE(obj, size) (((PyVarObject *)obj)->ob_size = size)
#endif

/* In Python 3.12+, tp_dict is NULL for some core types, PyType_GetDict returns
* a borrowed reference to the interpreter or cls mapping */
#if PY312_PLUS
Expand Down Expand Up @@ -102,12 +87,12 @@ ms_popcount(uint64_t i) { \
* memory usage. */
# define FAST_BYTES_SHRINK(obj, size) \
do { \
SET_SIZE(obj, size); \
Py_SET_SIZE(obj, size); \
PyBytes_AS_STRING(obj)[size] = '\0'; \
} while (0);
# define FAST_BYTEARRAY_SHRINK(obj, size) \
do { \
SET_SIZE(obj, size); \
Py_SET_SIZE(obj, size); \
PyByteArray_AS_STRING(obj)[size] = '\0'; \
} while (0);

Expand Down Expand Up @@ -789,7 +774,7 @@ _Lookup_OnMissing(Lookup *lookup, PyObject *val, PathNode *path) {
MsgspecState *mod = msgspec_get_global_state();

if (lookup->cls != NULL) {
PyObject *out = CALL_METHOD_ONE_ARG(lookup->cls, mod->str__missing_, val);
PyObject *out = PyObject_CallMethodOneArg(lookup->cls, mod->str__missing_, val);
if (out == NULL) {
PyErr_Clear();
}
Expand Down Expand Up @@ -927,7 +912,7 @@ IntLookup_New(PyObject *arg, PyObject *tag_field, PyObject *cls, bool array_like
);
if (out == NULL) goto cleanup;
/* XXX: overwrite `ob_size`, since we lied above */
SET_SIZE(out, size);
Py_SET_SIZE(out, size);

out->offset = imin;
for (size_t i = 0; i < size; i++) {
Expand Down Expand Up @@ -977,7 +962,7 @@ IntLookup_New(PyObject *arg, PyObject *tag_field, PyObject *cls, bool array_like
);
if (out == NULL) goto cleanup;
/* XXX: overwrite `ob_size`, since we lied above */
SET_SIZE(out, size);
Py_SET_SIZE(out, size);

for (size_t i = 0; i < size; i++) {
out->table[i].key = 0;
Expand Down Expand Up @@ -1828,7 +1813,7 @@ Meta_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) {
/* regex compile pattern if provided */
if (pattern != NULL) {
MsgspecState *mod = msgspec_get_global_state();
regex = CALL_ONE_ARG(mod->re_compile, pattern);
regex = PyObject_CallOneArg(mod->re_compile, pattern);
if (regex == NULL) return NULL;
}

Expand Down Expand Up @@ -2331,7 +2316,7 @@ Factory_Call(PyObject *self) {
else if (factory == (PyObject *)(&PyDict_Type)) {
return PyDict_New();
}
return CALL_NO_ARGS(factory);
return PyObject_CallNoArgs(factory);
}

static PyObject *
Expand Down Expand Up @@ -5404,7 +5389,7 @@ rename_pascal(PyObject *rename, PyObject *field) {

static PyObject*
rename_callable(PyObject *rename, PyObject *field) {
PyObject *temp = CALL_ONE_ARG(rename, field);
PyObject *temp = PyObject_CallOneArg(rename, field);
if (temp == NULL) return NULL;
if (PyUnicode_CheckExact(temp)) return temp;
if (temp == Py_None) {
Expand Down Expand Up @@ -6112,7 +6097,7 @@ structmeta_construct_tag(StructMetaInfo *info, MsgspecState *mod, PyObject *cls)
if (PyCallable_Check(info->temp_tag)) {
PyObject *qualname = simple_qualname(cls);
if (qualname == NULL) return -1;
info->tag_value = CALL_ONE_ARG(info->temp_tag, qualname);
info->tag_value = PyObject_CallOneArg(info->temp_tag, qualname);
Py_DECREF(qualname);
if (info->tag_value == NULL) return -1;
}
Expand Down Expand Up @@ -6746,7 +6731,7 @@ StructInfo_Convert(PyObject *obj) {
}

/* Extract annotations from the original type object */
annotations = CALL_ONE_ARG(mod->get_class_annotations, obj);
annotations = PyObject_CallOneArg(mod->get_class_annotations, obj);
if (annotations == NULL) goto error;

/* Allocate and zero-out a new StructInfo */
Expand Down Expand Up @@ -6891,7 +6876,7 @@ StructMeta_signature(StructMetaObject *self, void *closure)
signature_cls = PyObject_GetAttrString(inspect, "Signature");
if (signature_cls == NULL) goto cleanup;

annotations = CALL_ONE_ARG(st->get_type_hints, (PyObject *)self);
annotations = PyObject_CallOneArg(st->get_type_hints, (PyObject *)self);
if (annotations == NULL) goto cleanup;

parameters = PyList_New(nfields);
Expand Down Expand Up @@ -6929,7 +6914,7 @@ StructMeta_signature(StructMetaObject *self, void *closure)
if (parameter == NULL) goto cleanup;
PyList_SET_ITEM(parameters, i, parameter);
}
res = CALL_ONE_ARG(signature_cls, parameters);
res = PyObject_CallOneArg(signature_cls, parameters);
cleanup:
Py_XDECREF(inspect);
Py_XDECREF(parameter_cls);
Expand Down Expand Up @@ -7234,7 +7219,7 @@ Struct_get_index(PyObject *obj, Py_ssize_t index) {
static MS_INLINE int
Struct_post_init(StructMetaObject *st_type, PyObject *obj) {
if (st_type->post_init != NULL) {
PyObject *res = CALL_ONE_ARG(st_type->post_init, obj);
PyObject *res = PyObject_CallOneArg(st_type->post_init, obj);
if (res == NULL) return -1;
Py_DECREF(res);
}
Expand Down Expand Up @@ -8251,7 +8236,7 @@ TypedDictInfo_Convert(PyObject *obj) {
}

/* Not cached, extract fields from TypedDict object */
PyObject *temp = CALL_ONE_ARG(mod->get_typeddict_info, obj);
PyObject *temp = PyObject_CallOneArg(mod->get_typeddict_info, obj);
if (temp == NULL) return NULL;
annotations = PyTuple_GET_ITEM(temp, 0);
Py_INCREF(annotations);
Expand Down Expand Up @@ -8416,7 +8401,7 @@ DataclassInfo_Convert(PyObject *obj) {
}

/* Not cached, extract fields from Dataclass object */
PyObject *temp = CALL_ONE_ARG(mod->get_dataclass_info, obj);
PyObject *temp = PyObject_CallOneArg(mod->get_dataclass_info, obj);
if (temp == NULL) return NULL;
cls = PyTuple_GET_ITEM(temp, 0);
Py_INCREF(cls);
Expand Down Expand Up @@ -8549,7 +8534,7 @@ DataclassInfo_post_decode(DataclassInfo *self, PyObject *obj, PathNode *path) {
);
bool is_factory = self->fields[i].type->types & MS_EXTRA_FLAG;
if (is_factory) {
default_value = CALL_NO_ARGS(default_value);
default_value = PyObject_CallNoArgs(default_value);
if (default_value == NULL) return -1;
}
int status = PyObject_GenericSetAttr(obj, name, default_value);
Expand All @@ -8561,7 +8546,7 @@ DataclassInfo_post_decode(DataclassInfo *self, PyObject *obj, PathNode *path) {
}
}
if (self->post_init != NULL) {
PyObject *res = CALL_ONE_ARG(self->post_init, obj);
PyObject *res = PyObject_CallOneArg(self->post_init, obj);
if (res == NULL) {
ms_maybe_wrap_validation_error(path);
return -1;
Expand Down Expand Up @@ -8636,7 +8621,7 @@ NamedTupleInfo_Convert(PyObject *obj) {
}

/* Not cached, extract fields from NamedTuple object */
annotations = CALL_ONE_ARG(mod->get_class_annotations, obj);
annotations = PyObject_CallOneArg(mod->get_class_annotations, obj);
if (annotations == NULL) goto cleanup;

if (PyType_Check(obj)) {
Expand Down Expand Up @@ -10497,7 +10482,7 @@ ms_encode_time_parts(
int32_t offset_days = 0, offset_secs = 0;

if (tzinfo != PyDateTime_TimeZone_UTC) {
PyObject *offset = CALL_METHOD_ONE_ARG(
PyObject *offset = PyObject_CallMethodOneArg(
tzinfo, mod->str_utcoffset, datetime_or_none
);
if (offset == NULL) {
Expand Down Expand Up @@ -11415,7 +11400,7 @@ ms_decode_decimal_from_pyobj(PyObject *str, PathNode *path, MsgspecState *mod) {
if (mod == NULL) {
mod = msgspec_get_global_state();
}
return CALL_ONE_ARG(mod->DecimalType, str);
return PyObject_CallOneArg(mod->DecimalType, str);
}

static PyObject *
Expand Down Expand Up @@ -11812,7 +11797,7 @@ json_float_hook(
PyObject *str = PyUnicode_New(size, 127);
if (str == NULL) return NULL;
memcpy(ascii_get_buffer(str), buf, size);
PyObject *out = CALL_ONE_ARG(float_hook, str);
PyObject *out = PyObject_CallOneArg(float_hook, str);
Py_DECREF(str);
if (out == NULL) {
ms_maybe_wrap_validation_error(path);
Expand Down Expand Up @@ -13146,7 +13131,7 @@ mpack_encode_uncommon(EncoderState *self, PyTypeObject *type, PyObject *obj)
if (self->enc_hook != NULL) {
int status = -1;
PyObject *temp;
temp = CALL_ONE_ARG(self->enc_hook, obj);
temp = PyObject_CallOneArg(self->enc_hook, obj);
if (temp == NULL) return -1;
if (!Py_EnterRecursiveCall(" while serializing an object")) {
status = mpack_encode(self, temp);
Expand Down Expand Up @@ -13816,7 +13801,7 @@ json_encode_dict_key_noinline(EncoderState *self, PyObject *obj) {
else if (self->enc_hook != NULL) {
int status = -1;
PyObject *temp;
temp = CALL_ONE_ARG(self->enc_hook, obj);
temp = PyObject_CallOneArg(self->enc_hook, obj);
if (temp == NULL) return -1;
if (!Py_EnterRecursiveCall(" while serializing an object")) {
status = json_encode_dict_key(self, temp);
Expand Down Expand Up @@ -14223,7 +14208,7 @@ json_encode_uncommon(EncoderState *self, PyTypeObject *type, PyObject *obj) {
if (self->enc_hook != NULL) {
int status = -1;
PyObject *temp;
temp = CALL_ONE_ARG(self->enc_hook, obj);
temp = PyObject_CallOneArg(self->enc_hook, obj);
if (temp == NULL) return -1;
if (!Py_EnterRecursiveCall(" while serializing an object")) {
status = json_encode(self, temp);
Expand Down Expand Up @@ -15096,7 +15081,7 @@ mpack_decode_list(
*/
res = PyList_New(Py_MIN(16, size));
if (res == NULL) return NULL;
SET_SIZE(res, 0);
Py_SET_SIZE(res, 0);
if (size == 0) return res;

if (Py_EnterRecursiveCall(" while deserializing an object")) {
Expand All @@ -15114,7 +15099,7 @@ mpack_decode_list(
/* Append item to list */
if (MS_LIKELY((LIST_CAPACITY(res) > Py_SIZE(res)))) {
PyList_SET_ITEM(res, Py_SIZE(res), item);
SET_SIZE(res, Py_SIZE(res) + 1);
Py_SET_SIZE(res, Py_SIZE(res) + 1);
}
else {
int status = PyList_Append(res, item);
Expand Down Expand Up @@ -15700,7 +15685,7 @@ mpack_decode_dataclass(
PyObject *out = dataclass_type->tp_alloc(dataclass_type, 0);
if (out == NULL) goto error;
if (info->pre_init != NULL) {
PyObject *res = CALL_ONE_ARG(info->pre_init, out);
PyObject *res = PyObject_CallOneArg(info->pre_init, out);
if (res == NULL) goto error;
Py_DECREF(res);
}
Expand Down Expand Up @@ -16148,9 +16133,7 @@ static struct PyMethodDef Decoder_methods[] = {
"decode", (PyCFunction) Decoder_decode, METH_FASTCALL,
Decoder_decode__doc__,
},
#if PY39_PLUS
{"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS},
#endif
{NULL, NULL} /* sentinel */
};

Expand Down Expand Up @@ -17347,7 +17330,7 @@ json_decode_list(JSONDecoderState *self, TypeNode *type, TypeNode *el_type, Path
/* Append item to list */
if (MS_LIKELY((LIST_CAPACITY(out) > Py_SIZE(out)))) {
PyList_SET_ITEM(out, Py_SIZE(out), item);
SET_SIZE(out, Py_SIZE(out) + 1);
Py_SET_SIZE(out, Py_SIZE(out) + 1);
}
else {
int status = PyList_Append(out, item);
Expand Down Expand Up @@ -18216,7 +18199,7 @@ json_decode_dataclass(
out = dataclass_type->tp_alloc(dataclass_type, 0);
if (out == NULL) goto error;
if (info->pre_init != NULL) {
PyObject *res = CALL_ONE_ARG(info->pre_init, out);
PyObject *res = PyObject_CallOneArg(info->pre_init, out);
if (res == NULL) goto error;
Py_DECREF(res);
}
Expand Down Expand Up @@ -19200,9 +19183,7 @@ static struct PyMethodDef JSONDecoder_methods[] = {
"decode_lines", (PyCFunction) JSONDecoder_decode_lines, METH_FASTCALL,
JSONDecoder_decode_lines__doc__,
},
#if PY39_PLUS
{"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS},
#endif
{NULL, NULL} /* sentinel */
};

Expand Down Expand Up @@ -19914,7 +19895,7 @@ to_builtins(ToBuiltinsState *self, PyObject *obj, bool is_key) {
if (self->enc_hook != NULL) {
PyObject *out = NULL;
PyObject *temp;
temp = CALL_ONE_ARG(self->enc_hook, obj);
temp = PyObject_CallOneArg(self->enc_hook, obj);
if (temp == NULL) return NULL;
if (!Py_EnterRecursiveCall(" while serializing an object")) {
out = to_builtins(self, temp, is_key);
Expand Down Expand Up @@ -21184,7 +21165,7 @@ convert_dict_to_dataclass(
PyObject *out = dataclass_type->tp_alloc(dataclass_type, 0);
if (out == NULL) goto error;
if (info->pre_init != NULL) {
PyObject *res = CALL_ONE_ARG(info->pre_init, out);
PyObject *res = PyObject_CallOneArg(info->pre_init, out);
if (res == NULL) goto error;
Py_DECREF(res);
}
Expand Down Expand Up @@ -21394,7 +21375,7 @@ convert_object_to_dataclass(
PyObject *out = dataclass_type->tp_alloc(dataclass_type, 0);
if (out == NULL) goto error;
if (info->pre_init != NULL) {
PyObject *res = CALL_ONE_ARG(info->pre_init, out);
PyObject *res = PyObject_CallOneArg(info->pre_init, out);
if (res == NULL) goto error;
Py_DECREF(res);
}
Expand All @@ -21411,7 +21392,7 @@ convert_object_to_dataclass(
);
bool is_factory = info->fields[i].type->types & MS_EXTRA_FLAG;
if (is_factory) {
val = CALL_NO_ARGS(default_val);
val = PyObject_CallNoArgs(default_val);
}
else {
Py_INCREF(default_val);
Expand All @@ -21434,7 +21415,7 @@ convert_object_to_dataclass(
if (status < 0) goto error;
}
if (info->post_init != NULL) {
PyObject *res = CALL_ONE_ARG(info->post_init, out);
PyObject *res = PyObject_CallOneArg(info->post_init, out);
if (res == NULL) {
ms_maybe_wrap_validation_error(path);
goto error;
Expand Down
Loading