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