bpo-1635741: Port _gdbm module to multiphase initialization (GH-20920)

This commit is contained in:
Dong-hee Na 2020-06-17 01:41:23 +09:00 committed by GitHub
parent 51c5896b62
commit c4862e333a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 283 additions and 199 deletions

View File

@ -0,0 +1 @@
Port :mod:`_gdbm` to multiphase initialization.

View File

@ -1,5 +1,5 @@
/* DBM module using dictionary interface */
/* GDBM module using dictionary interface */
/* Author: Anthony Baxter, after dbmmodule.c */
/* Doc strings: Mitch Chapman */
@ -16,11 +16,24 @@
extern const char * gdbm_strerror(gdbm_error);
#endif
typedef struct {
PyTypeObject *gdbm_type;
PyObject *gdbm_error;
} _gdbm_state;
static inline _gdbm_state*
get_gdbm_state(PyObject *module)
{
void *state = PyModule_GetState(module);
assert(state != NULL);
return (_gdbm_state *)state;
}
/*[clinic input]
module _gdbm
class _gdbm.gdbm "dbmobject *" "&Dbmtype"
class _gdbm.gdbm "gdbmobject *" "&Gdbmtype"
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=113927c6170729b2]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=38ae71cedfc7172b]*/
PyDoc_STRVAR(gdbmmodule__doc__,
"This module provides an interface to the GNU DBM (GDBM) library.\n\
@ -38,20 +51,15 @@ typedef struct {
PyObject_HEAD
Py_ssize_t di_size; /* -1 means recompute */
GDBM_FILE di_dbm;
} dbmobject;
static PyTypeObject Dbmtype;
} gdbmobject;
#include "clinic/_gdbmmodule.c.h"
#define is_dbmobject(v) Py_IS_TYPE(v, &Dbmtype)
#define check_dbmobject_open(v) if ((v)->di_dbm == NULL) \
{ PyErr_SetString(DbmError, "GDBM object has already been closed"); \
return NULL; }
static PyObject *DbmError;
#define check_gdbmobject_open(v, err) \
if ((v)->di_dbm == NULL) { \
PyErr_SetString(err, "GDBM object has already been closed"); \
return NULL; \
}
PyDoc_STRVAR(gdbm_object__doc__,
"This object represents a GDBM database.\n\
@ -64,20 +72,21 @@ GDBM objects also support additional operations such as firstkey,\n\
nextkey, reorganize, and sync.");
static PyObject *
newdbmobject(const char *file, int flags, int mode)
newgdbmobject(_gdbm_state *state, const char *file, int flags, int mode)
{
dbmobject *dp;
dp = PyObject_New(dbmobject, &Dbmtype);
if (dp == NULL)
gdbmobject *dp = PyObject_New(gdbmobject, state->gdbm_type);
if (dp == NULL) {
return NULL;
}
dp->di_size = -1;
errno = 0;
if ((dp->di_dbm = gdbm_open((char *)file, 0, flags, mode, NULL)) == 0) {
if (errno != 0)
PyErr_SetFromErrnoWithFilename(DbmError, file);
else
PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
if (errno != 0) {
PyErr_SetFromErrnoWithFilename(state->gdbm_error, file);
}
else {
PyErr_SetString(state->gdbm_error, gdbm_strerror(gdbm_errno));
}
Py_DECREF(dp);
return NULL;
}
@ -87,18 +96,22 @@ newdbmobject(const char *file, int flags, int mode)
/* Methods */
static void
dbm_dealloc(dbmobject *dp)
gdbm_dealloc(gdbmobject *dp)
{
if (dp->di_dbm)
if (dp->di_dbm) {
gdbm_close(dp->di_dbm);
PyObject_Del(dp);
}
PyTypeObject *tp = Py_TYPE(dp);
tp->tp_free(dp);
Py_DECREF(tp);
}
static Py_ssize_t
dbm_length(dbmobject *dp)
gdbm_length(gdbmobject *dp)
{
_gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
if (dp->di_dbm == NULL) {
PyErr_SetString(DbmError, "GDBM object has already been closed");
PyErr_SetString(state->gdbm_error, "GDBM object has already been closed");
return -1;
}
if (dp->di_size < 0) {
@ -107,10 +120,10 @@ dbm_length(dbmobject *dp)
gdbm_count_t count;
if (gdbm_count(dp->di_dbm, &count) == -1) {
if (errno != 0) {
PyErr_SetFromErrno(DbmError);
PyErr_SetFromErrno(state->gdbm_error);
}
else {
PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
PyErr_SetString(state->gdbm_error, gdbm_strerror(gdbm_errno));
}
return -1;
}
@ -161,16 +174,17 @@ parse_datum(PyObject *o, datum *d, const char *failmsg)
}
static PyObject *
dbm_subscript(dbmobject *dp, PyObject *key)
gdbm_subscript(gdbmobject *dp, PyObject *key)
{
PyObject *v;
datum drec, krec;
_gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
if (!parse_datum(key, &krec, NULL)) {
return NULL;
}
if (dp->di_dbm == NULL) {
PyErr_SetString(DbmError,
PyErr_SetString(state->gdbm_error,
"GDBM object has already been closed");
return NULL;
}
@ -195,12 +209,12 @@ Get the value for key, or default if not present.
[clinic start generated code]*/
static PyObject *
_gdbm_gdbm_get_impl(dbmobject *self, PyObject *key, PyObject *default_value)
/*[clinic end generated code: output=19b7c585ad4f554a input=a9c20423f34c17b6]*/
_gdbm_gdbm_get_impl(gdbmobject *self, PyObject *key, PyObject *default_value)
/*[clinic end generated code: output=92421838f3a852f4 input=a9c20423f34c17b6]*/
{
PyObject *res;
res = dbm_subscript(self, key);
res = gdbm_subscript(self, key);
if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) {
PyErr_Clear();
Py_INCREF(default_value);
@ -210,16 +224,17 @@ _gdbm_gdbm_get_impl(dbmobject *self, PyObject *key, PyObject *default_value)
}
static int
dbm_ass_sub(dbmobject *dp, PyObject *v, PyObject *w)
gdbm_ass_sub(gdbmobject *dp, PyObject *v, PyObject *w)
{
datum krec, drec;
const char *failmsg = "gdbm mappings have bytes or string indices only";
_gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
if (!parse_datum(v, &krec, failmsg)) {
return -1;
}
if (dp->di_dbm == NULL) {
PyErr_SetString(DbmError,
PyErr_SetString(state->gdbm_error,
"GDBM object has already been closed");
return -1;
}
@ -230,7 +245,7 @@ dbm_ass_sub(dbmobject *dp, PyObject *v, PyObject *w)
PyErr_SetObject(PyExc_KeyError, v);
}
else {
PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
PyErr_SetString(state->gdbm_error, gdbm_strerror(gdbm_errno));
}
return -1;
}
@ -242,9 +257,9 @@ dbm_ass_sub(dbmobject *dp, PyObject *v, PyObject *w)
errno = 0;
if (gdbm_store(dp->di_dbm, krec, drec, GDBM_REPLACE) < 0) {
if (errno != 0)
PyErr_SetFromErrno(DbmError);
PyErr_SetFromErrno(state->gdbm_error);
else
PyErr_SetString(DbmError,
PyErr_SetString(state->gdbm_error,
gdbm_strerror(gdbm_errno));
return -1;
}
@ -263,28 +278,22 @@ Get value for key, or set it to default and return default if not present.
[clinic start generated code]*/
static PyObject *
_gdbm_gdbm_setdefault_impl(dbmobject *self, PyObject *key,
_gdbm_gdbm_setdefault_impl(gdbmobject *self, PyObject *key,
PyObject *default_value)
/*[clinic end generated code: output=88760ee520329012 input=0db46b69e9680171]*/
/*[clinic end generated code: output=f3246e880509f142 input=0db46b69e9680171]*/
{
PyObject *res;
res = dbm_subscript(self, key);
res = gdbm_subscript(self, key);
if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) {
PyErr_Clear();
if (dbm_ass_sub(self, key, default_value) < 0)
if (gdbm_ass_sub(self, key, default_value) < 0)
return NULL;
return dbm_subscript(self, key);
return gdbm_subscript(self, key);
}
return res;
}
static PyMappingMethods dbm_as_mapping = {
(lenfunc)dbm_length, /*mp_length*/
(binaryfunc)dbm_subscript, /*mp_subscript*/
(objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
};
/*[clinic input]
_gdbm.gdbm.close
@ -292,11 +301,12 @@ Close the database.
[clinic start generated code]*/
static PyObject *
_gdbm_gdbm_close_impl(dbmobject *self)
/*[clinic end generated code: output=23512a594598b563 input=0a203447379b45fd]*/
_gdbm_gdbm_close_impl(gdbmobject *self)
/*[clinic end generated code: output=f5abb4d6bb9e52d5 input=0a203447379b45fd]*/
{
if (self->di_dbm)
if (self->di_dbm) {
gdbm_close(self->di_dbm);
}
self->di_dbm = NULL;
Py_RETURN_NONE;
}
@ -305,22 +315,27 @@ _gdbm_gdbm_close_impl(dbmobject *self)
/*[clinic input]
_gdbm.gdbm.keys
cls: defining_class
Get a list of all keys in the database.
[clinic start generated code]*/
static PyObject *
_gdbm_gdbm_keys_impl(dbmobject *self)
/*[clinic end generated code: output=cb4b1776c3645dcc input=1832ee0a3132cfaf]*/
_gdbm_gdbm_keys_impl(gdbmobject *self, PyTypeObject *cls)
/*[clinic end generated code: output=c24b824e81404755 input=1428b7c79703d7d5]*/
{
PyObject *v, *item;
datum key, nextkey;
int err;
if (self == NULL || !is_dbmobject(self)) {
_gdbm_state *state = PyType_GetModuleState(cls);
assert(state != NULL);
if (self == NULL || !Py_IS_TYPE(self, state->gdbm_type)) {
PyErr_BadInternalCall();
return NULL;
}
check_dbmobject_open(self);
check_gdbmobject_open(self, state->gdbm_error);
v = PyList_New(0);
if (v == NULL)
@ -349,14 +364,15 @@ _gdbm_gdbm_keys_impl(dbmobject *self)
}
static int
dbm_contains(PyObject *self, PyObject *arg)
gdbm_contains(PyObject *self, PyObject *arg)
{
dbmobject *dp = (dbmobject *)self;
gdbmobject *dp = (gdbmobject *)self;
datum key;
Py_ssize_t size;
_gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
if ((dp)->di_dbm == NULL) {
PyErr_SetString(DbmError,
PyErr_SetString(state->gdbm_error,
"GDBM object has already been closed");
return -1;
}
@ -379,22 +395,11 @@ dbm_contains(PyObject *self, PyObject *arg)
return gdbm_exists(dp->di_dbm, key);
}
static PySequenceMethods dbm_as_sequence = {
0, /* sq_length */
0, /* sq_concat */
0, /* sq_repeat */
0, /* sq_item */
0, /* sq_slice */
0, /* sq_ass_item */
0, /* sq_ass_slice */
dbm_contains, /* sq_contains */
0, /* sq_inplace_concat */
0, /* sq_inplace_repeat */
};
/*[clinic input]
_gdbm.gdbm.firstkey
cls: defining_class
Return the starting key for the traversal.
It's possible to loop over every key in the database using this method
@ -403,13 +408,15 @@ hash values, and won't be sorted by the key values.
[clinic start generated code]*/
static PyObject *
_gdbm_gdbm_firstkey_impl(dbmobject *self)
/*[clinic end generated code: output=9ff85628d84b65d2 input=0dbd6a335d69bba0]*/
_gdbm_gdbm_firstkey_impl(gdbmobject *self, PyTypeObject *cls)
/*[clinic end generated code: output=139275e9c8b60827 input=ed8782a029a5d299]*/
{
PyObject *v;
datum key;
_gdbm_state *state = PyType_GetModuleState(cls);
assert(state != NULL);
check_dbmobject_open(self);
check_gdbmobject_open(self, state->gdbm_error);
key = gdbm_firstkey(self->di_dbm);
if (key.dptr) {
v = PyBytes_FromStringAndSize(key.dptr, key.dsize);
@ -424,6 +431,7 @@ _gdbm_gdbm_firstkey_impl(dbmobject *self)
/*[clinic input]
_gdbm.gdbm.nextkey
cls: defining_class
key: str(accept={str, robuffer}, zeroes=True)
/
@ -439,16 +447,18 @@ to create a list in memory that contains them all:
[clinic start generated code]*/
static PyObject *
_gdbm_gdbm_nextkey_impl(dbmobject *self, const char *key,
_gdbm_gdbm_nextkey_impl(gdbmobject *self, PyTypeObject *cls, const char *key,
Py_ssize_clean_t key_length)
/*[clinic end generated code: output=192ab892de6eb2f6 input=1f1606943614e36f]*/
/*[clinic end generated code: output=204964441fdbaf02 input=fcf6a51a96ce0172]*/
{
PyObject *v;
datum dbm_key, nextkey;
_gdbm_state *state = PyType_GetModuleState(cls);
assert(state != NULL);
dbm_key.dptr = (char *)key;
dbm_key.dsize = key_length;
check_dbmobject_open(self);
check_gdbmobject_open(self, state->gdbm_error);
nextkey = gdbm_nextkey(self->di_dbm, dbm_key);
if (nextkey.dptr) {
v = PyBytes_FromStringAndSize(nextkey.dptr, nextkey.dsize);
@ -463,6 +473,8 @@ _gdbm_gdbm_nextkey_impl(dbmobject *self, const char *key,
/*[clinic input]
_gdbm.gdbm.reorganize
cls: defining_class
Reorganize the database.
If you have carried out a lot of deletions and would like to shrink
@ -473,16 +485,18 @@ kept and reused as new (key,value) pairs are added.
[clinic start generated code]*/
static PyObject *
_gdbm_gdbm_reorganize_impl(dbmobject *self)
/*[clinic end generated code: output=38d9624df92e961d input=f6bea85bcfd40dd2]*/
_gdbm_gdbm_reorganize_impl(gdbmobject *self, PyTypeObject *cls)
/*[clinic end generated code: output=d77c69e8e3dd644a input=e1359faeef844e46]*/
{
check_dbmobject_open(self);
_gdbm_state *state = PyType_GetModuleState(cls);
assert(state != NULL);
check_gdbmobject_open(self, state->gdbm_error);
errno = 0;
if (gdbm_reorganize(self->di_dbm) < 0) {
if (errno != 0)
PyErr_SetFromErrno(DbmError);
PyErr_SetFromErrno(state->gdbm_error);
else
PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
PyErr_SetString(state->gdbm_error, gdbm_strerror(gdbm_errno));
return NULL;
}
Py_RETURN_NONE;
@ -491,6 +505,8 @@ _gdbm_gdbm_reorganize_impl(dbmobject *self)
/*[clinic input]
_gdbm.gdbm.sync
cls: defining_class
Flush the database to the disk file.
When the database has been opened in fast mode, this method forces
@ -498,29 +514,31 @@ any unwritten data to be written to the disk.
[clinic start generated code]*/
static PyObject *
_gdbm_gdbm_sync_impl(dbmobject *self)
/*[clinic end generated code: output=488b15f47028f125 input=2a47d2c9e153ab8a]*/
_gdbm_gdbm_sync_impl(gdbmobject *self, PyTypeObject *cls)
/*[clinic end generated code: output=bb680a2035c3f592 input=3d749235f79b6f2a]*/
{
check_dbmobject_open(self);
_gdbm_state *state = PyType_GetModuleState(cls);
assert(state != NULL);
check_gdbmobject_open(self, state->gdbm_error);
gdbm_sync(self->di_dbm);
Py_RETURN_NONE;
}
static PyObject *
dbm__enter__(PyObject *self, PyObject *args)
gdbm__enter__(PyObject *self, PyObject *args)
{
Py_INCREF(self);
return self;
}
static PyObject *
dbm__exit__(PyObject *self, PyObject *args)
gdbm__exit__(PyObject *self, PyObject *args)
{
_Py_IDENTIFIER(close);
return _PyObject_CallMethodIdNoArgs(self, &PyId_close);
}
static PyMethodDef dbm_methods[] = {
static PyMethodDef gdbm_methods[] = {
_GDBM_GDBM_CLOSE_METHODDEF
_GDBM_GDBM_KEYS_METHODDEF
_GDBM_GDBM_FIRSTKEY_METHODDEF
@ -529,46 +547,38 @@ static PyMethodDef dbm_methods[] = {
_GDBM_GDBM_SYNC_METHODDEF
_GDBM_GDBM_GET_METHODDEF
_GDBM_GDBM_SETDEFAULT_METHODDEF
{"__enter__", dbm__enter__, METH_NOARGS, NULL},
{"__exit__", dbm__exit__, METH_VARARGS, NULL},
{"__enter__", gdbm__enter__, METH_NOARGS, NULL},
{"__exit__", gdbm__exit__, METH_VARARGS, NULL},
{NULL, NULL} /* sentinel */
};
static PyTypeObject Dbmtype = {
PyVarObject_HEAD_INIT(0, 0)
"_gdbm.gdbm",
sizeof(dbmobject),
0,
(destructor)dbm_dealloc, /*tp_dealloc*/
0, /*tp_vectorcall_offset*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_as_async*/
0, /*tp_repr*/
0, /*tp_as_number*/
&dbm_as_sequence, /*tp_as_sequence*/
&dbm_as_mapping, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_xxx4*/
gdbm_object__doc__, /*tp_doc*/
0, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
0, /*tp_weaklistoffset*/
0, /*tp_iter*/
0, /*tp_iternext*/
dbm_methods, /*tp_methods*/
static PyType_Slot gdbmtype_spec_slots[] = {
{Py_tp_dealloc, gdbm_dealloc},
{Py_tp_methods, gdbm_methods},
{Py_sq_contains, gdbm_contains},
{Py_mp_length, gdbm_length},
{Py_mp_subscript, gdbm_subscript},
{Py_mp_ass_subscript, gdbm_ass_sub},
{Py_tp_doc, (char*)gdbm_object__doc__},
{0, 0}
};
static PyType_Spec gdbmtype_spec = {
.name = "_gdbm.gdbm",
.basicsize = sizeof(gdbmobject),
// Calling PyType_GetModuleState() on a subclass is not safe.
// dbmtype_spec does not have Py_TPFLAGS_BASETYPE flag
// which prevents to create a subclass.
// So calling PyType_GetModuleState() in this file is always safe.
.flags = Py_TPFLAGS_DEFAULT,
.slots = gdbmtype_spec_slots,
};
/* ----------------------------------------------------------------- */
/*[clinic input]
_gdbm.open as dbmopen
filename: unicode
flags: str="r"
mode: int(py_default="0o666") = 0o666
@ -601,9 +611,11 @@ when the database has to be created. It defaults to octal 0o666.
static PyObject *
dbmopen_impl(PyObject *module, PyObject *filename, const char *flags,
int mode)
/*[clinic end generated code: output=9527750f5df90764 input=3be0b0875974b928]*/
/*[clinic end generated code: output=9527750f5df90764 input=812b7d74399ceb0e]*/
{
int iflags;
_gdbm_state *state = get_gdbm_state(module);
assert(state != NULL);
switch (flags[0]) {
case 'r':
@ -619,7 +631,7 @@ dbmopen_impl(PyObject *module, PyObject *filename, const char *flags,
iflags = GDBM_NEWDB;
break;
default:
PyErr_SetString(DbmError,
PyErr_SetString(state->gdbm_error,
"First flag must be one of 'r', 'w', 'c' or 'n'");
return NULL;
}
@ -644,7 +656,7 @@ dbmopen_impl(PyObject *module, PyObject *filename, const char *flags,
default:
PyOS_snprintf(buf, sizeof(buf), "Flag '%c' is not supported.",
*flags);
PyErr_SetString(DbmError, buf);
PyErr_SetString(state->gdbm_error, buf);
return NULL;
}
}
@ -659,12 +671,12 @@ dbmopen_impl(PyObject *module, PyObject *filename, const char *flags,
PyErr_SetString(PyExc_ValueError, "embedded null character");
return NULL;
}
PyObject *self = newdbmobject(name, iflags, mode);
PyObject *self = newgdbmobject(state, name, iflags, mode);
Py_DECREF(filenamebytes);
return self;
}
static const char dbmmodule_open_flags[] = "rwcn"
static const char gdbmmodule_open_flags[] = "rwcn"
#ifdef GDBM_FAST
"f"
#endif
@ -676,48 +688,30 @@ static const char dbmmodule_open_flags[] = "rwcn"
#endif
;
static PyMethodDef dbmmodule_methods[] = {
static PyMethodDef _gdbm_module_methods[] = {
DBMOPEN_METHODDEF
{ 0, 0 },
};
static struct PyModuleDef _gdbmmodule = {
PyModuleDef_HEAD_INIT,
"_gdbm",
gdbmmodule__doc__,
-1,
dbmmodule_methods,
NULL,
NULL,
NULL,
NULL
};
PyMODINIT_FUNC
PyInit__gdbm(void) {
PyObject *m;
if (PyType_Ready(&Dbmtype) < 0)
return NULL;
m = PyModule_Create(&_gdbmmodule);
if (m == NULL) {
return NULL;
static int
_gdbm_exec(PyObject *module)
{
_gdbm_state *state = get_gdbm_state(module);
state->gdbm_type = (PyTypeObject *)PyType_FromModuleAndSpec(module,
&gdbmtype_spec, NULL);
if (state->gdbm_type == NULL) {
return -1;
}
DbmError = PyErr_NewException("_gdbm.error", PyExc_OSError, NULL);
if (DbmError == NULL) {
goto error;
state->gdbm_error = PyErr_NewException("_gdbm.error", PyExc_OSError, NULL);
if (state->gdbm_error == NULL) {
return -1;
}
Py_INCREF(DbmError);
if (PyModule_AddObject(m, "error", DbmError) < 0) {
Py_DECREF(DbmError);
goto error;
if (PyModule_AddType(module, (PyTypeObject *)state->gdbm_error) < 0) {
return -1;
}
if (PyModule_AddStringConstant(m, "open_flags",
dbmmodule_open_flags) < 0) {
goto error;
if (PyModule_AddStringConstant(module, "open_flags",
gdbmmodule_open_flags) < 0) {
return -1;
}
#if defined(GDBM_VERSION_MAJOR) && defined(GDBM_VERSION_MINOR) && \
@ -725,17 +719,59 @@ PyInit__gdbm(void) {
PyObject *obj = Py_BuildValue("iii", GDBM_VERSION_MAJOR,
GDBM_VERSION_MINOR, GDBM_VERSION_PATCH);
if (obj == NULL) {
goto error;
return -1;
}
if (PyModule_AddObject(m, "_GDBM_VERSION", obj) < 0) {
if (PyModule_AddObject(module, "_GDBM_VERSION", obj) < 0) {
Py_DECREF(obj);
goto error;
return -1;
}
#endif
return m;
error:
Py_DECREF(m);
return NULL;
return 0;
}
static int
_gdbm_module_traverse(PyObject *module, visitproc visit, void *arg)
{
_gdbm_state *state = get_gdbm_state(module);
Py_VISIT(state->gdbm_error);
Py_VISIT(state->gdbm_type);
return 0;
}
static int
_gdbm_module_clear(PyObject *module)
{
_gdbm_state *state = get_gdbm_state(module);
Py_CLEAR(state->gdbm_error);
Py_CLEAR(state->gdbm_type);
return 0;
}
static void
_gdbm_module_free(void *module)
{
_gdbm_module_clear((PyObject *)module);
}
static PyModuleDef_Slot _gdbm_module_slots[] = {
{Py_mod_exec, _gdbm_exec},
{0, NULL}
};
static struct PyModuleDef _gdbmmodule = {
PyModuleDef_HEAD_INIT,
.m_name = "_gdbm",
.m_doc = gdbmmodule__doc__,
.m_size = sizeof(_gdbm_state),
.m_methods = _gdbm_module_methods,
.m_slots = _gdbm_module_slots,
.m_traverse = _gdbm_module_traverse,
.m_clear = _gdbm_module_clear,
.m_free = _gdbm_module_free,
};
PyMODINIT_FUNC
PyInit__gdbm(void)
{
return PyModuleDef_Init(&_gdbmmodule);
}

View File

@ -12,10 +12,10 @@ PyDoc_STRVAR(_gdbm_gdbm_get__doc__,
{"get", (PyCFunction)(void(*)(void))_gdbm_gdbm_get, METH_FASTCALL, _gdbm_gdbm_get__doc__},
static PyObject *
_gdbm_gdbm_get_impl(dbmobject *self, PyObject *key, PyObject *default_value);
_gdbm_gdbm_get_impl(gdbmobject *self, PyObject *key, PyObject *default_value);
static PyObject *
_gdbm_gdbm_get(dbmobject *self, PyObject *const *args, Py_ssize_t nargs)
_gdbm_gdbm_get(gdbmobject *self, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *key;
@ -46,11 +46,11 @@ PyDoc_STRVAR(_gdbm_gdbm_setdefault__doc__,
{"setdefault", (PyCFunction)(void(*)(void))_gdbm_gdbm_setdefault, METH_FASTCALL, _gdbm_gdbm_setdefault__doc__},
static PyObject *
_gdbm_gdbm_setdefault_impl(dbmobject *self, PyObject *key,
_gdbm_gdbm_setdefault_impl(gdbmobject *self, PyObject *key,
PyObject *default_value);
static PyObject *
_gdbm_gdbm_setdefault(dbmobject *self, PyObject *const *args, Py_ssize_t nargs)
_gdbm_gdbm_setdefault(gdbmobject *self, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *key;
@ -81,10 +81,10 @@ PyDoc_STRVAR(_gdbm_gdbm_close__doc__,
{"close", (PyCFunction)_gdbm_gdbm_close, METH_NOARGS, _gdbm_gdbm_close__doc__},
static PyObject *
_gdbm_gdbm_close_impl(dbmobject *self);
_gdbm_gdbm_close_impl(gdbmobject *self);
static PyObject *
_gdbm_gdbm_close(dbmobject *self, PyObject *Py_UNUSED(ignored))
_gdbm_gdbm_close(gdbmobject *self, PyObject *Py_UNUSED(ignored))
{
return _gdbm_gdbm_close_impl(self);
}
@ -96,15 +96,26 @@ PyDoc_STRVAR(_gdbm_gdbm_keys__doc__,
"Get a list of all keys in the database.");
#define _GDBM_GDBM_KEYS_METHODDEF \
{"keys", (PyCFunction)_gdbm_gdbm_keys, METH_NOARGS, _gdbm_gdbm_keys__doc__},
{"keys", (PyCFunction)(void(*)(void))_gdbm_gdbm_keys, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _gdbm_gdbm_keys__doc__},
static PyObject *
_gdbm_gdbm_keys_impl(dbmobject *self);
_gdbm_gdbm_keys_impl(gdbmobject *self, PyTypeObject *cls);
static PyObject *
_gdbm_gdbm_keys(dbmobject *self, PyObject *Py_UNUSED(ignored))
_gdbm_gdbm_keys(gdbmobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
return _gdbm_gdbm_keys_impl(self);
PyObject *return_value = NULL;
static const char * const _keywords[] = { NULL};
static _PyArg_Parser _parser = {":keys", _keywords, 0};
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
)) {
goto exit;
}
return_value = _gdbm_gdbm_keys_impl(self, cls);
exit:
return return_value;
}
PyDoc_STRVAR(_gdbm_gdbm_firstkey__doc__,
@ -118,15 +129,26 @@ PyDoc_STRVAR(_gdbm_gdbm_firstkey__doc__,
"hash values, and won\'t be sorted by the key values.");
#define _GDBM_GDBM_FIRSTKEY_METHODDEF \
{"firstkey", (PyCFunction)_gdbm_gdbm_firstkey, METH_NOARGS, _gdbm_gdbm_firstkey__doc__},
{"firstkey", (PyCFunction)(void(*)(void))_gdbm_gdbm_firstkey, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _gdbm_gdbm_firstkey__doc__},
static PyObject *
_gdbm_gdbm_firstkey_impl(dbmobject *self);
_gdbm_gdbm_firstkey_impl(gdbmobject *self, PyTypeObject *cls);
static PyObject *
_gdbm_gdbm_firstkey(dbmobject *self, PyObject *Py_UNUSED(ignored))
_gdbm_gdbm_firstkey(gdbmobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
return _gdbm_gdbm_firstkey_impl(self);
PyObject *return_value = NULL;
static const char * const _keywords[] = { NULL};
static _PyArg_Parser _parser = {":firstkey", _keywords, 0};
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
)) {
goto exit;
}
return_value = _gdbm_gdbm_firstkey_impl(self, cls);
exit:
return return_value;
}
PyDoc_STRVAR(_gdbm_gdbm_nextkey__doc__,
@ -144,23 +166,26 @@ PyDoc_STRVAR(_gdbm_gdbm_nextkey__doc__,
" k = db.nextkey(k)");
#define _GDBM_GDBM_NEXTKEY_METHODDEF \
{"nextkey", (PyCFunction)_gdbm_gdbm_nextkey, METH_O, _gdbm_gdbm_nextkey__doc__},
{"nextkey", (PyCFunction)(void(*)(void))_gdbm_gdbm_nextkey, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _gdbm_gdbm_nextkey__doc__},
static PyObject *
_gdbm_gdbm_nextkey_impl(dbmobject *self, const char *key,
_gdbm_gdbm_nextkey_impl(gdbmobject *self, PyTypeObject *cls, const char *key,
Py_ssize_clean_t key_length);
static PyObject *
_gdbm_gdbm_nextkey(dbmobject *self, PyObject *arg)
_gdbm_gdbm_nextkey(gdbmobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", NULL};
static _PyArg_Parser _parser = {"s#:nextkey", _keywords, 0};
const char *key;
Py_ssize_clean_t key_length;
if (!PyArg_Parse(arg, "s#:nextkey", &key, &key_length)) {
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
&key, &key_length)) {
goto exit;
}
return_value = _gdbm_gdbm_nextkey_impl(self, key, key_length);
return_value = _gdbm_gdbm_nextkey_impl(self, cls, key, key_length);
exit:
return return_value;
@ -179,15 +204,26 @@ PyDoc_STRVAR(_gdbm_gdbm_reorganize__doc__,
"kept and reused as new (key,value) pairs are added.");
#define _GDBM_GDBM_REORGANIZE_METHODDEF \
{"reorganize", (PyCFunction)_gdbm_gdbm_reorganize, METH_NOARGS, _gdbm_gdbm_reorganize__doc__},
{"reorganize", (PyCFunction)(void(*)(void))_gdbm_gdbm_reorganize, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _gdbm_gdbm_reorganize__doc__},
static PyObject *
_gdbm_gdbm_reorganize_impl(dbmobject *self);
_gdbm_gdbm_reorganize_impl(gdbmobject *self, PyTypeObject *cls);
static PyObject *
_gdbm_gdbm_reorganize(dbmobject *self, PyObject *Py_UNUSED(ignored))
_gdbm_gdbm_reorganize(gdbmobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
return _gdbm_gdbm_reorganize_impl(self);
PyObject *return_value = NULL;
static const char * const _keywords[] = { NULL};
static _PyArg_Parser _parser = {":reorganize", _keywords, 0};
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
)) {
goto exit;
}
return_value = _gdbm_gdbm_reorganize_impl(self, cls);
exit:
return return_value;
}
PyDoc_STRVAR(_gdbm_gdbm_sync__doc__,
@ -200,15 +236,26 @@ PyDoc_STRVAR(_gdbm_gdbm_sync__doc__,
"any unwritten data to be written to the disk.");
#define _GDBM_GDBM_SYNC_METHODDEF \
{"sync", (PyCFunction)_gdbm_gdbm_sync, METH_NOARGS, _gdbm_gdbm_sync__doc__},
{"sync", (PyCFunction)(void(*)(void))_gdbm_gdbm_sync, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _gdbm_gdbm_sync__doc__},
static PyObject *
_gdbm_gdbm_sync_impl(dbmobject *self);
_gdbm_gdbm_sync_impl(gdbmobject *self, PyTypeObject *cls);
static PyObject *
_gdbm_gdbm_sync(dbmobject *self, PyObject *Py_UNUSED(ignored))
_gdbm_gdbm_sync(gdbmobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
return _gdbm_gdbm_sync_impl(self);
PyObject *return_value = NULL;
static const char * const _keywords[] = { NULL};
static _PyArg_Parser _parser = {":sync", _keywords, 0};
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
)) {
goto exit;
}
return_value = _gdbm_gdbm_sync_impl(self, cls);
exit:
return return_value;
}
PyDoc_STRVAR(dbmopen__doc__,
@ -293,4 +340,4 @@ skip_optional:
exit:
return return_value;
}
/*[clinic end generated code: output=c9d43f42677f4efb input=a9049054013a1b77]*/
/*[clinic end generated code: output=e84bc6ac82fcb6d4 input=a9049054013a1b77]*/