Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
allendowney
GitHub Repository: allendowney/cpython
Path: blob/main/Modules/_gdbmmodule.c
12 views
1
2
/* GDBM module using dictionary interface */
3
/* Author: Anthony Baxter, after dbmmodule.c */
4
/* Doc strings: Mitch Chapman */
5
6
#include "Python.h"
7
#include "gdbm.h"
8
9
#include <fcntl.h>
10
#include <stdlib.h> // free()
11
#include <sys/stat.h>
12
#include <sys/types.h>
13
14
#if defined(WIN32) && !defined(__CYGWIN__)
15
#include "gdbmerrno.h"
16
extern const char * gdbm_strerror(gdbm_error);
17
#endif
18
19
typedef struct {
20
PyTypeObject *gdbm_type;
21
PyObject *gdbm_error;
22
} _gdbm_state;
23
24
static inline _gdbm_state*
25
get_gdbm_state(PyObject *module)
26
{
27
void *state = PyModule_GetState(module);
28
assert(state != NULL);
29
return (_gdbm_state *)state;
30
}
31
32
/*[clinic input]
33
module _gdbm
34
class _gdbm.gdbm "gdbmobject *" "&Gdbmtype"
35
[clinic start generated code]*/
36
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=38ae71cedfc7172b]*/
37
38
PyDoc_STRVAR(gdbmmodule__doc__,
39
"This module provides an interface to the GNU DBM (GDBM) library.\n\
40
\n\
41
This module is quite similar to the dbm module, but uses GDBM instead to\n\
42
provide some additional functionality. Please note that the file formats\n\
43
created by GDBM and dbm are incompatible.\n\
44
\n\
45
GDBM objects behave like mappings (dictionaries), except that keys and\n\
46
values are always immutable bytes-like objects or strings. Printing\n\
47
a GDBM object doesn't print the keys and values, and the items() and\n\
48
values() methods are not supported.");
49
50
typedef struct {
51
PyObject_HEAD
52
Py_ssize_t di_size; /* -1 means recompute */
53
GDBM_FILE di_dbm;
54
} gdbmobject;
55
56
#include "clinic/_gdbmmodule.c.h"
57
58
#define check_gdbmobject_open(v, err) \
59
if ((v)->di_dbm == NULL) { \
60
PyErr_SetString(err, "GDBM object has already been closed"); \
61
return NULL; \
62
}
63
64
PyDoc_STRVAR(gdbm_object__doc__,
65
"This object represents a GDBM database.\n\
66
GDBM objects behave like mappings (dictionaries), except that keys and\n\
67
values are always immutable bytes-like objects or strings. Printing\n\
68
a GDBM object doesn't print the keys and values, and the items() and\n\
69
values() methods are not supported.\n\
70
\n\
71
GDBM objects also support additional operations such as firstkey,\n\
72
nextkey, reorganize, and sync.");
73
74
static PyObject *
75
newgdbmobject(_gdbm_state *state, const char *file, int flags, int mode)
76
{
77
gdbmobject *dp = PyObject_GC_New(gdbmobject, state->gdbm_type);
78
if (dp == NULL) {
79
return NULL;
80
}
81
dp->di_size = -1;
82
errno = 0;
83
PyObject_GC_Track(dp);
84
85
if ((dp->di_dbm = gdbm_open((char *)file, 0, flags, mode, NULL)) == 0) {
86
if (errno != 0) {
87
PyErr_SetFromErrnoWithFilename(state->gdbm_error, file);
88
}
89
else {
90
PyErr_SetString(state->gdbm_error, gdbm_strerror(gdbm_errno));
91
}
92
Py_DECREF(dp);
93
return NULL;
94
}
95
return (PyObject *)dp;
96
}
97
98
/* Methods */
99
static int
100
gdbm_traverse(gdbmobject *dp, visitproc visit, void *arg)
101
{
102
Py_VISIT(Py_TYPE(dp));
103
return 0;
104
}
105
106
static void
107
gdbm_dealloc(gdbmobject *dp)
108
{
109
PyObject_GC_UnTrack(dp);
110
if (dp->di_dbm) {
111
gdbm_close(dp->di_dbm);
112
}
113
PyTypeObject *tp = Py_TYPE(dp);
114
tp->tp_free(dp);
115
Py_DECREF(tp);
116
}
117
118
static Py_ssize_t
119
gdbm_length(gdbmobject *dp)
120
{
121
_gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
122
if (dp->di_dbm == NULL) {
123
PyErr_SetString(state->gdbm_error, "GDBM object has already been closed");
124
return -1;
125
}
126
if (dp->di_size < 0) {
127
#if GDBM_VERSION_MAJOR >= 1 && GDBM_VERSION_MINOR >= 11
128
errno = 0;
129
gdbm_count_t count;
130
if (gdbm_count(dp->di_dbm, &count) == -1) {
131
if (errno != 0) {
132
PyErr_SetFromErrno(state->gdbm_error);
133
}
134
else {
135
PyErr_SetString(state->gdbm_error, gdbm_strerror(gdbm_errno));
136
}
137
return -1;
138
}
139
if (count > PY_SSIZE_T_MAX) {
140
PyErr_SetString(PyExc_OverflowError, "count exceeds PY_SSIZE_T_MAX");
141
return -1;
142
}
143
dp->di_size = count;
144
#else
145
datum key,okey;
146
okey.dsize=0;
147
okey.dptr=NULL;
148
149
Py_ssize_t size = 0;
150
for (key = gdbm_firstkey(dp->di_dbm); key.dptr;
151
key = gdbm_nextkey(dp->di_dbm,okey)) {
152
size++;
153
if (okey.dsize) {
154
free(okey.dptr);
155
}
156
okey=key;
157
}
158
dp->di_size = size;
159
#endif
160
}
161
return dp->di_size;
162
}
163
164
static int
165
gdbm_bool(gdbmobject *dp)
166
{
167
_gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
168
if (dp->di_dbm == NULL) {
169
PyErr_SetString(state->gdbm_error, "GDBM object has already been closed");
170
return -1;
171
}
172
if (dp->di_size > 0) {
173
/* Known non-zero size. */
174
return 1;
175
}
176
if (dp->di_size == 0) {
177
/* Known zero size. */
178
return 0;
179
}
180
/* Unknown size. Ensure DBM object has an entry. */
181
datum key = gdbm_firstkey(dp->di_dbm);
182
if (key.dptr == NULL) {
183
/* Empty. Cache this fact. */
184
dp->di_size = 0;
185
return 0;
186
}
187
188
/* Non-empty. Don't cache the length since we don't know. */
189
free(key.dptr);
190
return 1;
191
}
192
193
// Wrapper function for PyArg_Parse(o, "s#", &d.dptr, &d.size).
194
// This function is needed to support PY_SSIZE_T_CLEAN.
195
// Return 1 on success, same to PyArg_Parse().
196
static int
197
parse_datum(PyObject *o, datum *d, const char *failmsg)
198
{
199
Py_ssize_t size;
200
if (!PyArg_Parse(o, "s#", &d->dptr, &size)) {
201
if (failmsg != NULL) {
202
PyErr_SetString(PyExc_TypeError, failmsg);
203
}
204
return 0;
205
}
206
if (INT_MAX < size) {
207
PyErr_SetString(PyExc_OverflowError, "size does not fit in an int");
208
return 0;
209
}
210
d->dsize = size;
211
return 1;
212
}
213
214
static PyObject *
215
gdbm_subscript(gdbmobject *dp, PyObject *key)
216
{
217
PyObject *v;
218
datum drec, krec;
219
_gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
220
221
if (!parse_datum(key, &krec, NULL)) {
222
return NULL;
223
}
224
if (dp->di_dbm == NULL) {
225
PyErr_SetString(state->gdbm_error,
226
"GDBM object has already been closed");
227
return NULL;
228
}
229
drec = gdbm_fetch(dp->di_dbm, krec);
230
if (drec.dptr == 0) {
231
PyErr_SetObject(PyExc_KeyError, key);
232
return NULL;
233
}
234
v = PyBytes_FromStringAndSize(drec.dptr, drec.dsize);
235
free(drec.dptr);
236
return v;
237
}
238
239
/*[clinic input]
240
_gdbm.gdbm.get
241
242
key: object
243
default: object = None
244
/
245
246
Get the value for key, or default if not present.
247
[clinic start generated code]*/
248
249
static PyObject *
250
_gdbm_gdbm_get_impl(gdbmobject *self, PyObject *key, PyObject *default_value)
251
/*[clinic end generated code: output=92421838f3a852f4 input=a9c20423f34c17b6]*/
252
{
253
PyObject *res;
254
255
res = gdbm_subscript(self, key);
256
if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) {
257
PyErr_Clear();
258
return Py_NewRef(default_value);
259
}
260
return res;
261
}
262
263
static int
264
gdbm_ass_sub(gdbmobject *dp, PyObject *v, PyObject *w)
265
{
266
datum krec, drec;
267
const char *failmsg = "gdbm mappings have bytes or string indices only";
268
_gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
269
270
if (!parse_datum(v, &krec, failmsg)) {
271
return -1;
272
}
273
if (dp->di_dbm == NULL) {
274
PyErr_SetString(state->gdbm_error,
275
"GDBM object has already been closed");
276
return -1;
277
}
278
dp->di_size = -1;
279
if (w == NULL) {
280
if (gdbm_delete(dp->di_dbm, krec) < 0) {
281
if (gdbm_errno == GDBM_ITEM_NOT_FOUND) {
282
PyErr_SetObject(PyExc_KeyError, v);
283
}
284
else {
285
PyErr_SetString(state->gdbm_error, gdbm_strerror(gdbm_errno));
286
}
287
return -1;
288
}
289
}
290
else {
291
if (!parse_datum(w, &drec, failmsg)) {
292
return -1;
293
}
294
errno = 0;
295
if (gdbm_store(dp->di_dbm, krec, drec, GDBM_REPLACE) < 0) {
296
if (errno != 0)
297
PyErr_SetFromErrno(state->gdbm_error);
298
else
299
PyErr_SetString(state->gdbm_error,
300
gdbm_strerror(gdbm_errno));
301
return -1;
302
}
303
}
304
return 0;
305
}
306
307
/*[clinic input]
308
_gdbm.gdbm.setdefault
309
310
key: object
311
default: object = None
312
/
313
314
Get value for key, or set it to default and return default if not present.
315
[clinic start generated code]*/
316
317
static PyObject *
318
_gdbm_gdbm_setdefault_impl(gdbmobject *self, PyObject *key,
319
PyObject *default_value)
320
/*[clinic end generated code: output=f3246e880509f142 input=0db46b69e9680171]*/
321
{
322
PyObject *res;
323
324
res = gdbm_subscript(self, key);
325
if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) {
326
PyErr_Clear();
327
if (gdbm_ass_sub(self, key, default_value) < 0)
328
return NULL;
329
return gdbm_subscript(self, key);
330
}
331
return res;
332
}
333
334
/*[clinic input]
335
_gdbm.gdbm.close
336
337
Close the database.
338
[clinic start generated code]*/
339
340
static PyObject *
341
_gdbm_gdbm_close_impl(gdbmobject *self)
342
/*[clinic end generated code: output=f5abb4d6bb9e52d5 input=0a203447379b45fd]*/
343
{
344
if (self->di_dbm) {
345
gdbm_close(self->di_dbm);
346
}
347
self->di_dbm = NULL;
348
Py_RETURN_NONE;
349
}
350
351
/* XXX Should return a set or a set view */
352
/*[clinic input]
353
_gdbm.gdbm.keys
354
355
cls: defining_class
356
357
Get a list of all keys in the database.
358
[clinic start generated code]*/
359
360
static PyObject *
361
_gdbm_gdbm_keys_impl(gdbmobject *self, PyTypeObject *cls)
362
/*[clinic end generated code: output=c24b824e81404755 input=1428b7c79703d7d5]*/
363
{
364
PyObject *v, *item;
365
datum key, nextkey;
366
int err;
367
368
_gdbm_state *state = PyType_GetModuleState(cls);
369
assert(state != NULL);
370
371
if (self == NULL || !Py_IS_TYPE(self, state->gdbm_type)) {
372
PyErr_BadInternalCall();
373
return NULL;
374
}
375
check_gdbmobject_open(self, state->gdbm_error);
376
377
v = PyList_New(0);
378
if (v == NULL)
379
return NULL;
380
381
key = gdbm_firstkey(self->di_dbm);
382
while (key.dptr) {
383
item = PyBytes_FromStringAndSize(key.dptr, key.dsize);
384
if (item == NULL) {
385
free(key.dptr);
386
Py_DECREF(v);
387
return NULL;
388
}
389
err = PyList_Append(v, item);
390
Py_DECREF(item);
391
if (err != 0) {
392
free(key.dptr);
393
Py_DECREF(v);
394
return NULL;
395
}
396
nextkey = gdbm_nextkey(self->di_dbm, key);
397
free(key.dptr);
398
key = nextkey;
399
}
400
return v;
401
}
402
403
static int
404
gdbm_contains(PyObject *self, PyObject *arg)
405
{
406
gdbmobject *dp = (gdbmobject *)self;
407
datum key;
408
Py_ssize_t size;
409
_gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
410
411
if ((dp)->di_dbm == NULL) {
412
PyErr_SetString(state->gdbm_error,
413
"GDBM object has already been closed");
414
return -1;
415
}
416
if (PyUnicode_Check(arg)) {
417
key.dptr = (char *)PyUnicode_AsUTF8AndSize(arg, &size);
418
key.dsize = size;
419
if (key.dptr == NULL)
420
return -1;
421
}
422
else if (!PyBytes_Check(arg)) {
423
PyErr_Format(PyExc_TypeError,
424
"gdbm key must be bytes or string, not %.100s",
425
Py_TYPE(arg)->tp_name);
426
return -1;
427
}
428
else {
429
key.dptr = PyBytes_AS_STRING(arg);
430
key.dsize = PyBytes_GET_SIZE(arg);
431
}
432
return gdbm_exists(dp->di_dbm, key);
433
}
434
435
/*[clinic input]
436
_gdbm.gdbm.firstkey
437
438
cls: defining_class
439
440
Return the starting key for the traversal.
441
442
It's possible to loop over every key in the database using this method
443
and the nextkey() method. The traversal is ordered by GDBM's internal
444
hash values, and won't be sorted by the key values.
445
[clinic start generated code]*/
446
447
static PyObject *
448
_gdbm_gdbm_firstkey_impl(gdbmobject *self, PyTypeObject *cls)
449
/*[clinic end generated code: output=139275e9c8b60827 input=ed8782a029a5d299]*/
450
{
451
PyObject *v;
452
datum key;
453
_gdbm_state *state = PyType_GetModuleState(cls);
454
assert(state != NULL);
455
456
check_gdbmobject_open(self, state->gdbm_error);
457
key = gdbm_firstkey(self->di_dbm);
458
if (key.dptr) {
459
v = PyBytes_FromStringAndSize(key.dptr, key.dsize);
460
free(key.dptr);
461
return v;
462
}
463
else {
464
Py_RETURN_NONE;
465
}
466
}
467
468
/*[clinic input]
469
_gdbm.gdbm.nextkey
470
471
cls: defining_class
472
key: str(accept={str, robuffer}, zeroes=True)
473
/
474
475
Returns the key that follows key in the traversal.
476
477
The following code prints every key in the database db, without having
478
to create a list in memory that contains them all:
479
480
k = db.firstkey()
481
while k is not None:
482
print(k)
483
k = db.nextkey(k)
484
[clinic start generated code]*/
485
486
static PyObject *
487
_gdbm_gdbm_nextkey_impl(gdbmobject *self, PyTypeObject *cls, const char *key,
488
Py_ssize_t key_length)
489
/*[clinic end generated code: output=c81a69300ef41766 input=365e297bc0b3db48]*/
490
{
491
PyObject *v;
492
datum dbm_key, nextkey;
493
_gdbm_state *state = PyType_GetModuleState(cls);
494
assert(state != NULL);
495
496
dbm_key.dptr = (char *)key;
497
dbm_key.dsize = key_length;
498
check_gdbmobject_open(self, state->gdbm_error);
499
nextkey = gdbm_nextkey(self->di_dbm, dbm_key);
500
if (nextkey.dptr) {
501
v = PyBytes_FromStringAndSize(nextkey.dptr, nextkey.dsize);
502
free(nextkey.dptr);
503
return v;
504
}
505
else {
506
Py_RETURN_NONE;
507
}
508
}
509
510
/*[clinic input]
511
_gdbm.gdbm.reorganize
512
513
cls: defining_class
514
515
Reorganize the database.
516
517
If you have carried out a lot of deletions and would like to shrink
518
the space used by the GDBM file, this routine will reorganize the
519
database. GDBM will not shorten the length of a database file except
520
by using this reorganization; otherwise, deleted file space will be
521
kept and reused as new (key,value) pairs are added.
522
[clinic start generated code]*/
523
524
static PyObject *
525
_gdbm_gdbm_reorganize_impl(gdbmobject *self, PyTypeObject *cls)
526
/*[clinic end generated code: output=d77c69e8e3dd644a input=e1359faeef844e46]*/
527
{
528
_gdbm_state *state = PyType_GetModuleState(cls);
529
assert(state != NULL);
530
check_gdbmobject_open(self, state->gdbm_error);
531
errno = 0;
532
if (gdbm_reorganize(self->di_dbm) < 0) {
533
if (errno != 0)
534
PyErr_SetFromErrno(state->gdbm_error);
535
else
536
PyErr_SetString(state->gdbm_error, gdbm_strerror(gdbm_errno));
537
return NULL;
538
}
539
Py_RETURN_NONE;
540
}
541
542
/*[clinic input]
543
_gdbm.gdbm.sync
544
545
cls: defining_class
546
547
Flush the database to the disk file.
548
549
When the database has been opened in fast mode, this method forces
550
any unwritten data to be written to the disk.
551
[clinic start generated code]*/
552
553
static PyObject *
554
_gdbm_gdbm_sync_impl(gdbmobject *self, PyTypeObject *cls)
555
/*[clinic end generated code: output=bb680a2035c3f592 input=3d749235f79b6f2a]*/
556
{
557
_gdbm_state *state = PyType_GetModuleState(cls);
558
assert(state != NULL);
559
check_gdbmobject_open(self, state->gdbm_error);
560
gdbm_sync(self->di_dbm);
561
Py_RETURN_NONE;
562
}
563
564
static PyObject *
565
gdbm__enter__(PyObject *self, PyObject *args)
566
{
567
return Py_NewRef(self);
568
}
569
570
static PyObject *
571
gdbm__exit__(PyObject *self, PyObject *args)
572
{
573
return _gdbm_gdbm_close_impl((gdbmobject *)self);
574
}
575
576
static PyMethodDef gdbm_methods[] = {
577
_GDBM_GDBM_CLOSE_METHODDEF
578
_GDBM_GDBM_KEYS_METHODDEF
579
_GDBM_GDBM_FIRSTKEY_METHODDEF
580
_GDBM_GDBM_NEXTKEY_METHODDEF
581
_GDBM_GDBM_REORGANIZE_METHODDEF
582
_GDBM_GDBM_SYNC_METHODDEF
583
_GDBM_GDBM_GET_METHODDEF
584
_GDBM_GDBM_SETDEFAULT_METHODDEF
585
{"__enter__", gdbm__enter__, METH_NOARGS, NULL},
586
{"__exit__", gdbm__exit__, METH_VARARGS, NULL},
587
{NULL, NULL} /* sentinel */
588
};
589
590
static PyType_Slot gdbmtype_spec_slots[] = {
591
{Py_tp_dealloc, gdbm_dealloc},
592
{Py_tp_traverse, gdbm_traverse},
593
{Py_tp_methods, gdbm_methods},
594
{Py_sq_contains, gdbm_contains},
595
{Py_mp_length, gdbm_length},
596
{Py_mp_subscript, gdbm_subscript},
597
{Py_mp_ass_subscript, gdbm_ass_sub},
598
{Py_nb_bool, gdbm_bool},
599
{Py_tp_doc, (char*)gdbm_object__doc__},
600
{0, 0}
601
};
602
603
static PyType_Spec gdbmtype_spec = {
604
.name = "_gdbm.gdbm",
605
.basicsize = sizeof(gdbmobject),
606
// Calling PyType_GetModuleState() on a subclass is not safe.
607
// dbmtype_spec does not have Py_TPFLAGS_BASETYPE flag
608
// which prevents to create a subclass.
609
// So calling PyType_GetModuleState() in this file is always safe.
610
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION |
611
Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE),
612
.slots = gdbmtype_spec_slots,
613
};
614
615
/* ----------------------------------------------------------------- */
616
617
/*[clinic input]
618
_gdbm.open as dbmopen
619
620
filename: object
621
flags: str="r"
622
mode: int(py_default="0o666") = 0o666
623
/
624
625
Open a dbm database and return a dbm object.
626
627
The filename argument is the name of the database file.
628
629
The optional flags argument can be 'r' (to open an existing database
630
for reading only -- default), 'w' (to open an existing database for
631
reading and writing), 'c' (which creates the database if it doesn't
632
exist), or 'n' (which always creates a new empty database).
633
634
Some versions of gdbm support additional flags which must be
635
appended to one of the flags described above. The module constant
636
'open_flags' is a string of valid additional flags. The 'f' flag
637
opens the database in fast mode; altered data will not automatically
638
be written to the disk after every change. This results in faster
639
writes to the database, but may result in an inconsistent database
640
if the program crashes while the database is still open. Use the
641
sync() method to force any unwritten data to be written to the disk.
642
The 's' flag causes all database operations to be synchronized to
643
disk. The 'u' flag disables locking of the database file.
644
645
The optional mode argument is the Unix mode of the file, used only
646
when the database has to be created. It defaults to octal 0o666.
647
[clinic start generated code]*/
648
649
static PyObject *
650
dbmopen_impl(PyObject *module, PyObject *filename, const char *flags,
651
int mode)
652
/*[clinic end generated code: output=9527750f5df90764 input=bca6ec81dc49292c]*/
653
{
654
int iflags;
655
_gdbm_state *state = get_gdbm_state(module);
656
assert(state != NULL);
657
658
switch (flags[0]) {
659
case 'r':
660
iflags = GDBM_READER;
661
break;
662
case 'w':
663
iflags = GDBM_WRITER;
664
break;
665
case 'c':
666
iflags = GDBM_WRCREAT;
667
break;
668
case 'n':
669
iflags = GDBM_NEWDB;
670
break;
671
default:
672
PyErr_SetString(state->gdbm_error,
673
"First flag must be one of 'r', 'w', 'c' or 'n'");
674
return NULL;
675
}
676
for (flags++; *flags != '\0'; flags++) {
677
switch (*flags) {
678
#ifdef GDBM_FAST
679
case 'f':
680
iflags |= GDBM_FAST;
681
break;
682
#endif
683
#ifdef GDBM_SYNC
684
case 's':
685
iflags |= GDBM_SYNC;
686
break;
687
#endif
688
#ifdef GDBM_NOLOCK
689
case 'u':
690
iflags |= GDBM_NOLOCK;
691
break;
692
#endif
693
default:
694
PyErr_Format(state->gdbm_error,
695
"Flag '%c' is not supported.", (unsigned char)*flags);
696
return NULL;
697
}
698
}
699
700
PyObject *filenamebytes;
701
if (!PyUnicode_FSConverter(filename, &filenamebytes)) {
702
return NULL;
703
}
704
705
const char *name = PyBytes_AS_STRING(filenamebytes);
706
if (strlen(name) != (size_t)PyBytes_GET_SIZE(filenamebytes)) {
707
Py_DECREF(filenamebytes);
708
PyErr_SetString(PyExc_ValueError, "embedded null character");
709
return NULL;
710
}
711
PyObject *self = newgdbmobject(state, name, iflags, mode);
712
Py_DECREF(filenamebytes);
713
return self;
714
}
715
716
static const char gdbmmodule_open_flags[] = "rwcn"
717
#ifdef GDBM_FAST
718
"f"
719
#endif
720
#ifdef GDBM_SYNC
721
"s"
722
#endif
723
#ifdef GDBM_NOLOCK
724
"u"
725
#endif
726
;
727
728
static PyMethodDef _gdbm_module_methods[] = {
729
DBMOPEN_METHODDEF
730
{ 0, 0 },
731
};
732
733
static int
734
_gdbm_exec(PyObject *module)
735
{
736
_gdbm_state *state = get_gdbm_state(module);
737
state->gdbm_type = (PyTypeObject *)PyType_FromModuleAndSpec(module,
738
&gdbmtype_spec, NULL);
739
if (state->gdbm_type == NULL) {
740
return -1;
741
}
742
state->gdbm_error = PyErr_NewException("_gdbm.error", PyExc_OSError, NULL);
743
if (state->gdbm_error == NULL) {
744
return -1;
745
}
746
if (PyModule_AddType(module, (PyTypeObject *)state->gdbm_error) < 0) {
747
return -1;
748
}
749
if (PyModule_AddStringConstant(module, "open_flags",
750
gdbmmodule_open_flags) < 0) {
751
return -1;
752
}
753
754
#if defined(GDBM_VERSION_MAJOR) && defined(GDBM_VERSION_MINOR) && \
755
defined(GDBM_VERSION_PATCH)
756
PyObject *obj = Py_BuildValue("iii", GDBM_VERSION_MAJOR,
757
GDBM_VERSION_MINOR, GDBM_VERSION_PATCH);
758
if (obj == NULL) {
759
return -1;
760
}
761
if (PyModule_AddObject(module, "_GDBM_VERSION", obj) < 0) {
762
Py_DECREF(obj);
763
return -1;
764
}
765
#endif
766
return 0;
767
}
768
769
static int
770
_gdbm_module_traverse(PyObject *module, visitproc visit, void *arg)
771
{
772
_gdbm_state *state = get_gdbm_state(module);
773
Py_VISIT(state->gdbm_error);
774
Py_VISIT(state->gdbm_type);
775
return 0;
776
}
777
778
static int
779
_gdbm_module_clear(PyObject *module)
780
{
781
_gdbm_state *state = get_gdbm_state(module);
782
Py_CLEAR(state->gdbm_error);
783
Py_CLEAR(state->gdbm_type);
784
return 0;
785
}
786
787
static void
788
_gdbm_module_free(void *module)
789
{
790
_gdbm_module_clear((PyObject *)module);
791
}
792
793
static PyModuleDef_Slot _gdbm_module_slots[] = {
794
{Py_mod_exec, _gdbm_exec},
795
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
796
{0, NULL}
797
};
798
799
static struct PyModuleDef _gdbmmodule = {
800
PyModuleDef_HEAD_INIT,
801
.m_name = "_gdbm",
802
.m_doc = gdbmmodule__doc__,
803
.m_size = sizeof(_gdbm_state),
804
.m_methods = _gdbm_module_methods,
805
.m_slots = _gdbm_module_slots,
806
.m_traverse = _gdbm_module_traverse,
807
.m_clear = _gdbm_module_clear,
808
.m_free = _gdbm_module_free,
809
};
810
811
PyMODINIT_FUNC
812
PyInit__gdbm(void)
813
{
814
return PyModuleDef_Init(&_gdbmmodule);
815
}
816
817