dumbdbm.py revision 1aa2c0f073bdbed4fa824591d53e20bbf3d01add
19f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossum"""A dumb and slow but simple dbm clone. 29f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossum 39f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van RossumFor database spam, spam.dir contains the index (a text file), 49f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossumspam.bak *may* contain a backup of the index (also a text file), 59f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossumwhile spam.dat contains the data (a binary file). 69f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossum 79f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van RossumXXX TO DO: 89f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossum 99f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossum- seems to contain a bug when updating... 109f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossum 119f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossum- reclaim free space (currently, space once occupied by deleted or expanded 129f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossumitems is never reused) 139f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossum 149f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossum- support concurrent access (currently, if two processes take turns making 159f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossumupdates, they can mess up the index) 169f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossum 179f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossum- support efficient access to large databases (currently, the whole index 189f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossumis read when the database is opened, and some updates rewrite the whole index) 199f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossum 209f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossum- support opening for read-only (flag = 'm') 219f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossum 229f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossum""" 239f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossum 24c769040100c3957446acea6efed5c9ad4a552cf2Serhiy Storchakaimport ast as _ast 25d0cd95ce7febd97683d6e113e1b486b93bcf88ebMartin v. Löwisimport os as _os 269f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossumimport __builtin__ 272dd1ed69b425d2f2ac8152548c7581aa1f01216dRaymond Hettingerimport UserDict 289f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossum 299f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossum_open = __builtin__.open 309f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossum 319f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossum_BLOCKSIZE = 512 329f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossum 3388869f9787cd4ceb2298e4b13980beb057687824Tim Peterserror = IOError # For anydbm 3422a18904e43c47902ae1e58922abeb87b530b0aeGuido van Rossum 352dd1ed69b425d2f2ac8152548c7581aa1f01216dRaymond Hettingerclass _Database(UserDict.DictMixin): 369f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossum 37d7472ec13a65c6c5ff00365b1477677d1fecbb3cTim Peters # The on-disk directory and data files can remain in mutually 38d7472ec13a65c6c5ff00365b1477677d1fecbb3cTim Peters # inconsistent states for an arbitrarily long time (see comments 39d7472ec13a65c6c5ff00365b1477677d1fecbb3cTim Peters # at the end of __setitem__). This is only repaired when _commit() 40d7472ec13a65c6c5ff00365b1477677d1fecbb3cTim Peters # gets called. One place _commit() gets called is from __del__(), 41d7472ec13a65c6c5ff00365b1477677d1fecbb3cTim Peters # and if that occurs at program shutdown time, module globals may 42d7472ec13a65c6c5ff00365b1477677d1fecbb3cTim Peters # already have gotten rebound to None. Since it's crucial that 430320464583957258031ebee1b8897343211e4339Tim Peters # _commit() finish successfully, we can't ignore shutdown races 44d7472ec13a65c6c5ff00365b1477677d1fecbb3cTim Peters # here, and _commit() must not reference any globals. 45d7472ec13a65c6c5ff00365b1477677d1fecbb3cTim Peters _os = _os # for _commit() 46d7472ec13a65c6c5ff00365b1477677d1fecbb3cTim Peters _open = _open # for _commit() 47d7472ec13a65c6c5ff00365b1477677d1fecbb3cTim Peters 487dfd5701b20c3566166e148f77591a2912164221Tim Peters def __init__(self, filebasename, mode): 492c8373bc234039fff699df9c28d2cb74efd6a37cFred Drake self._mode = mode 507dfd5701b20c3566166e148f77591a2912164221Tim Peters 517dfd5701b20c3566166e148f77591a2912164221Tim Peters # The directory file is a text file. Each line looks like 527dfd5701b20c3566166e148f77591a2912164221Tim Peters # "%r, (%d, %d)\n" % (key, pos, siz) 537dfd5701b20c3566166e148f77591a2912164221Tim Peters # where key is the string key, pos is the offset into the dat 547dfd5701b20c3566166e148f77591a2912164221Tim Peters # file of the associated value's first byte, and siz is the number 557dfd5701b20c3566166e148f77591a2912164221Tim Peters # of bytes in the associated value. 567dfd5701b20c3566166e148f77591a2912164221Tim Peters self._dirfile = filebasename + _os.extsep + 'dir' 577dfd5701b20c3566166e148f77591a2912164221Tim Peters 587dfd5701b20c3566166e148f77591a2912164221Tim Peters # The data file is a binary file pointed into by the directory 597dfd5701b20c3566166e148f77591a2912164221Tim Peters # file, and holds the values associated with keys. Each value 607dfd5701b20c3566166e148f77591a2912164221Tim Peters # begins at a _BLOCKSIZE-aligned byte offset, and is a raw 617dfd5701b20c3566166e148f77591a2912164221Tim Peters # binary 8-bit string value. 627dfd5701b20c3566166e148f77591a2912164221Tim Peters self._datfile = filebasename + _os.extsep + 'dat' 637dfd5701b20c3566166e148f77591a2912164221Tim Peters self._bakfile = filebasename + _os.extsep + 'bak' 647dfd5701b20c3566166e148f77591a2912164221Tim Peters 657dfd5701b20c3566166e148f77591a2912164221Tim Peters # The index is an in-memory dict, mirroring the directory file. 667dfd5701b20c3566166e148f77591a2912164221Tim Peters self._index = None # maps keys to (pos, siz) pairs 677dfd5701b20c3566166e148f77591a2912164221Tim Peters 6888869f9787cd4ceb2298e4b13980beb057687824Tim Peters # Mod by Jack: create data file if needed 6988869f9787cd4ceb2298e4b13980beb057687824Tim Peters try: 7088869f9787cd4ceb2298e4b13980beb057687824Tim Peters f = _open(self._datfile, 'r') 7188869f9787cd4ceb2298e4b13980beb057687824Tim Peters except IOError: 7233ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka with _open(self._datfile, 'w') as f: 7333ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka self._chmod(self._datfile) 7433ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka else: 7533ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka f.close() 7688869f9787cd4ceb2298e4b13980beb057687824Tim Peters self._update() 7788869f9787cd4ceb2298e4b13980beb057687824Tim Peters 787dfd5701b20c3566166e148f77591a2912164221Tim Peters # Read directory file into the in-memory index dict. 7988869f9787cd4ceb2298e4b13980beb057687824Tim Peters def _update(self): 8088869f9787cd4ceb2298e4b13980beb057687824Tim Peters self._index = {} 8188869f9787cd4ceb2298e4b13980beb057687824Tim Peters try: 8288869f9787cd4ceb2298e4b13980beb057687824Tim Peters f = _open(self._dirfile) 8388869f9787cd4ceb2298e4b13980beb057687824Tim Peters except IOError: 8488869f9787cd4ceb2298e4b13980beb057687824Tim Peters pass 8588869f9787cd4ceb2298e4b13980beb057687824Tim Peters else: 8633ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka with f: 8733ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka for line in f: 8833ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka line = line.rstrip() 89c769040100c3957446acea6efed5c9ad4a552cf2Serhiy Storchaka key, pos_and_siz_pair = _ast.literal_eval(line) 9033ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka self._index[key] = pos_and_siz_pair 9188869f9787cd4ceb2298e4b13980beb057687824Tim Peters 927dfd5701b20c3566166e148f77591a2912164221Tim Peters # Write the index dict to the directory file. The original directory 937dfd5701b20c3566166e148f77591a2912164221Tim Peters # file (if any) is renamed with a .bak extension first. If a .bak 947dfd5701b20c3566166e148f77591a2912164221Tim Peters # file currently exists, it's deleted. 9588869f9787cd4ceb2298e4b13980beb057687824Tim Peters def _commit(self): 96d7472ec13a65c6c5ff00365b1477677d1fecbb3cTim Peters # CAUTION: It's vital that _commit() succeed, and _commit() can 97d7472ec13a65c6c5ff00365b1477677d1fecbb3cTim Peters # be called from __del__(). Therefore we must never reference a 98d7472ec13a65c6c5ff00365b1477677d1fecbb3cTim Peters # global in this routine. 997a6c733c3b8ee131d7860ecb0877837e412c2959Tim Peters if self._index is None: 1007a6c733c3b8ee131d7860ecb0877837e412c2959Tim Peters return # nothing to do 1017a6c733c3b8ee131d7860ecb0877837e412c2959Tim Peters 1027dfd5701b20c3566166e148f77591a2912164221Tim Peters try: 103d7472ec13a65c6c5ff00365b1477677d1fecbb3cTim Peters self._os.unlink(self._bakfile) 104d7472ec13a65c6c5ff00365b1477677d1fecbb3cTim Peters except self._os.error: 1057dfd5701b20c3566166e148f77591a2912164221Tim Peters pass 1067dfd5701b20c3566166e148f77591a2912164221Tim Peters 1077dfd5701b20c3566166e148f77591a2912164221Tim Peters try: 108d7472ec13a65c6c5ff00365b1477677d1fecbb3cTim Peters self._os.rename(self._dirfile, self._bakfile) 109d7472ec13a65c6c5ff00365b1477677d1fecbb3cTim Peters except self._os.error: 1107dfd5701b20c3566166e148f77591a2912164221Tim Peters pass 1117dfd5701b20c3566166e148f77591a2912164221Tim Peters 11233ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka with self._open(self._dirfile, 'w') as f: 11333ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka self._chmod(self._dirfile) 11433ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka for key, pos_and_siz_pair in self._index.iteritems(): 11533ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka f.write("%r, %r\n" % (key, pos_and_siz_pair)) 11688869f9787cd4ceb2298e4b13980beb057687824Tim Peters 1176d06815b562e1540ee334d30953354210dfebd24Skip Montanaro sync = _commit 1186d06815b562e1540ee334d30953354210dfebd24Skip Montanaro 11988869f9787cd4ceb2298e4b13980beb057687824Tim Peters def __getitem__(self, key): 12088869f9787cd4ceb2298e4b13980beb057687824Tim Peters pos, siz = self._index[key] # may raise KeyError 12133ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka with _open(self._datfile, 'rb') as f: 12233ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka f.seek(pos) 12333ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka dat = f.read(siz) 12488869f9787cd4ceb2298e4b13980beb057687824Tim Peters return dat 12588869f9787cd4ceb2298e4b13980beb057687824Tim Peters 1267dfd5701b20c3566166e148f77591a2912164221Tim Peters # Append val to the data file, starting at a _BLOCKSIZE-aligned 1277dfd5701b20c3566166e148f77591a2912164221Tim Peters # offset. The data file is first padded with NUL bytes (if needed) 1287dfd5701b20c3566166e148f77591a2912164221Tim Peters # to get to an aligned offset. Return pair 1297dfd5701b20c3566166e148f77591a2912164221Tim Peters # (starting offset of val, len(val)) 13088869f9787cd4ceb2298e4b13980beb057687824Tim Peters def _addval(self, val): 13133ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka with _open(self._datfile, 'rb+') as f: 13233ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka f.seek(0, 2) 13333ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka pos = int(f.tell()) 13433ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka npos = ((pos + _BLOCKSIZE - 1) // _BLOCKSIZE) * _BLOCKSIZE 13533ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka f.write('\0'*(npos-pos)) 13633ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka pos = npos 13733ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka f.write(val) 13888869f9787cd4ceb2298e4b13980beb057687824Tim Peters return (pos, len(val)) 13988869f9787cd4ceb2298e4b13980beb057687824Tim Peters 1407dfd5701b20c3566166e148f77591a2912164221Tim Peters # Write val to the data file, starting at offset pos. The caller 1417dfd5701b20c3566166e148f77591a2912164221Tim Peters # is responsible for ensuring that there's enough room starting at 1427dfd5701b20c3566166e148f77591a2912164221Tim Peters # pos to hold val, without overwriting some other value. Return 1437dfd5701b20c3566166e148f77591a2912164221Tim Peters # pair (pos, len(val)). 14488869f9787cd4ceb2298e4b13980beb057687824Tim Peters def _setval(self, pos, val): 14533ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka with _open(self._datfile, 'rb+') as f: 14633ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka f.seek(pos) 14733ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka f.write(val) 14888869f9787cd4ceb2298e4b13980beb057687824Tim Peters return (pos, len(val)) 14988869f9787cd4ceb2298e4b13980beb057687824Tim Peters 1507dfd5701b20c3566166e148f77591a2912164221Tim Peters # key is a new key whose associated value starts in the data file 1511d8d729af80c7d45161f20a40428d26698c11af8Tim Peters # at offset pos and with length siz. Add an index record to 1521d8d729af80c7d45161f20a40428d26698c11af8Tim Peters # the in-memory index dict, and append one to the directory file. 1537dfd5701b20c3566166e148f77591a2912164221Tim Peters def _addkey(self, key, pos_and_siz_pair): 1547dfd5701b20c3566166e148f77591a2912164221Tim Peters self._index[key] = pos_and_siz_pair 15533ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka with _open(self._dirfile, 'a') as f: 15633ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka self._chmod(self._dirfile) 15733ad0968eb624d22075d567123c52f62e7184d8dSerhiy Storchaka f.write("%r, %r\n" % (key, pos_and_siz_pair)) 15888869f9787cd4ceb2298e4b13980beb057687824Tim Peters 15988869f9787cd4ceb2298e4b13980beb057687824Tim Peters def __setitem__(self, key, val): 16088869f9787cd4ceb2298e4b13980beb057687824Tim Peters if not type(key) == type('') == type(val): 16188869f9787cd4ceb2298e4b13980beb057687824Tim Peters raise TypeError, "keys and values must be strings" 1627dfd5701b20c3566166e148f77591a2912164221Tim Peters if key not in self._index: 1637dfd5701b20c3566166e148f77591a2912164221Tim Peters self._addkey(key, self._addval(val)) 16488869f9787cd4ceb2298e4b13980beb057687824Tim Peters else: 1657dfd5701b20c3566166e148f77591a2912164221Tim Peters # See whether the new value is small enough to fit in the 1667dfd5701b20c3566166e148f77591a2912164221Tim Peters # (padded) space currently occupied by the old value. 16788869f9787cd4ceb2298e4b13980beb057687824Tim Peters pos, siz = self._index[key] 168ef6573e52946c70778e29e3b33d61a8a0c6e4052Tim Peters oldblocks = (siz + _BLOCKSIZE - 1) // _BLOCKSIZE 169ef6573e52946c70778e29e3b33d61a8a0c6e4052Tim Peters newblocks = (len(val) + _BLOCKSIZE - 1) // _BLOCKSIZE 17088869f9787cd4ceb2298e4b13980beb057687824Tim Peters if newblocks <= oldblocks: 1717dfd5701b20c3566166e148f77591a2912164221Tim Peters self._index[key] = self._setval(pos, val) 17288869f9787cd4ceb2298e4b13980beb057687824Tim Peters else: 1737dfd5701b20c3566166e148f77591a2912164221Tim Peters # The new value doesn't fit in the (padded) space used 1747dfd5701b20c3566166e148f77591a2912164221Tim Peters # by the old value. The blocks used by the old value are 1757dfd5701b20c3566166e148f77591a2912164221Tim Peters # forever lost. 1767dfd5701b20c3566166e148f77591a2912164221Tim Peters self._index[key] = self._addval(val) 1777dfd5701b20c3566166e148f77591a2912164221Tim Peters 1787dfd5701b20c3566166e148f77591a2912164221Tim Peters # Note that _index may be out of synch with the directory 1797dfd5701b20c3566166e148f77591a2912164221Tim Peters # file now: _setval() and _addval() don't update the directory 1801d8d729af80c7d45161f20a40428d26698c11af8Tim Peters # file. This also means that the on-disk directory and data 1811d8d729af80c7d45161f20a40428d26698c11af8Tim Peters # files are in a mutually inconsistent state, and they'll 1821d8d729af80c7d45161f20a40428d26698c11af8Tim Peters # remain that way until _commit() is called. Note that this 1831d8d729af80c7d45161f20a40428d26698c11af8Tim Peters # is a disaster (for the database) if the program crashes 1841d8d729af80c7d45161f20a40428d26698c11af8Tim Peters # (so that _commit() never gets called). 18588869f9787cd4ceb2298e4b13980beb057687824Tim Peters 18688869f9787cd4ceb2298e4b13980beb057687824Tim Peters def __delitem__(self, key): 1877dfd5701b20c3566166e148f77591a2912164221Tim Peters # The blocks used by the associated value are lost. 18888869f9787cd4ceb2298e4b13980beb057687824Tim Peters del self._index[key] 1897dfd5701b20c3566166e148f77591a2912164221Tim Peters # XXX It's unclear why we do a _commit() here (the code always 1907dfd5701b20c3566166e148f77591a2912164221Tim Peters # XXX has, so I'm not changing it). _setitem__ doesn't try to 1917dfd5701b20c3566166e148f77591a2912164221Tim Peters # XXX keep the directory file in synch. Why should we? Or 1927dfd5701b20c3566166e148f77591a2912164221Tim Peters # XXX why shouldn't __setitem__? 19388869f9787cd4ceb2298e4b13980beb057687824Tim Peters self._commit() 19488869f9787cd4ceb2298e4b13980beb057687824Tim Peters 19588869f9787cd4ceb2298e4b13980beb057687824Tim Peters def keys(self): 19688869f9787cd4ceb2298e4b13980beb057687824Tim Peters return self._index.keys() 19788869f9787cd4ceb2298e4b13980beb057687824Tim Peters 19888869f9787cd4ceb2298e4b13980beb057687824Tim Peters def has_key(self, key): 199793d4b49361a010e4baa485ec77e3adc430f0236Raymond Hettinger return key in self._index 20088869f9787cd4ceb2298e4b13980beb057687824Tim Peters 201a7cc69e02ef9ec7014600911a66978898e545cf1Fred Drake def __contains__(self, key): 202793d4b49361a010e4baa485ec77e3adc430f0236Raymond Hettinger return key in self._index 203a7cc69e02ef9ec7014600911a66978898e545cf1Fred Drake 204a7cc69e02ef9ec7014600911a66978898e545cf1Fred Drake def iterkeys(self): 205a7cc69e02ef9ec7014600911a66978898e545cf1Fred Drake return self._index.iterkeys() 206a7cc69e02ef9ec7014600911a66978898e545cf1Fred Drake __iter__ = iterkeys 207a7cc69e02ef9ec7014600911a66978898e545cf1Fred Drake 20888869f9787cd4ceb2298e4b13980beb057687824Tim Peters def __len__(self): 20988869f9787cd4ceb2298e4b13980beb057687824Tim Peters return len(self._index) 21088869f9787cd4ceb2298e4b13980beb057687824Tim Peters 21188869f9787cd4ceb2298e4b13980beb057687824Tim Peters def close(self): 2121aa2c0f073bdbed4fa824591d53e20bbf3d01addSerhiy Storchaka try: 2131aa2c0f073bdbed4fa824591d53e20bbf3d01addSerhiy Storchaka self._commit() 2141aa2c0f073bdbed4fa824591d53e20bbf3d01addSerhiy Storchaka finally: 2151aa2c0f073bdbed4fa824591d53e20bbf3d01addSerhiy Storchaka self._index = self._datfile = self._dirfile = self._bakfile = None 2169f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossum 2177a6c733c3b8ee131d7860ecb0877837e412c2959Tim Peters __del__ = close 218e4418609f79b94b91bda2621b5e6f067fb6a31d5Tim Peters 219dc26758ffeb33f6d59cb30b0019da9252e0cea1cAndrew M. Kuchling def _chmod (self, file): 220dc26758ffeb33f6d59cb30b0019da9252e0cea1cAndrew M. Kuchling if hasattr(self._os, 'chmod'): 221dc26758ffeb33f6d59cb30b0019da9252e0cea1cAndrew M. Kuchling self._os.chmod(file, self._mode) 222ed9057083bcdcce37ddb66bc01e9b7fddb5ea206Anthony Baxter 2239f824a7984fcd98d00dfc795e6a1d95317fd4b93Guido van Rossum 2242c8373bc234039fff699df9c28d2cb74efd6a37cFred Drakedef open(file, flag=None, mode=0666): 225aef22fb9cdf31fb7f0afc28ad049f08a89e23761Raymond Hettinger """Open the database file, filename, and return corresponding object. 226aef22fb9cdf31fb7f0afc28ad049f08a89e23761Raymond Hettinger 227aef22fb9cdf31fb7f0afc28ad049f08a89e23761Raymond Hettinger The flag argument, used to control how the database is opened in the 228aef22fb9cdf31fb7f0afc28ad049f08a89e23761Raymond Hettinger other DBM implementations, is ignored in the dumbdbm module; the 229aef22fb9cdf31fb7f0afc28ad049f08a89e23761Raymond Hettinger database is always opened for update, and will be created if it does 230aef22fb9cdf31fb7f0afc28ad049f08a89e23761Raymond Hettinger not exist. 231aef22fb9cdf31fb7f0afc28ad049f08a89e23761Raymond Hettinger 232aef22fb9cdf31fb7f0afc28ad049f08a89e23761Raymond Hettinger The optional mode argument is the UNIX mode of the file, used only when 233aef22fb9cdf31fb7f0afc28ad049f08a89e23761Raymond Hettinger the database has to be created. It defaults to octal code 0666 (and 234aef22fb9cdf31fb7f0afc28ad049f08a89e23761Raymond Hettinger will be modified by the prevailing umask). 235aef22fb9cdf31fb7f0afc28ad049f08a89e23761Raymond Hettinger 236aef22fb9cdf31fb7f0afc28ad049f08a89e23761Raymond Hettinger """ 237f421e81e4112809380542af378575756247eba00Neal Norwitz # flag argument is currently ignored 2389ef0ef5b729b88491be1d28ab46248b645645c44Andrew M. Kuchling 2399ef0ef5b729b88491be1d28ab46248b645645c44Andrew M. Kuchling # Modify mode depending on the umask 2409ef0ef5b729b88491be1d28ab46248b645645c44Andrew M. Kuchling try: 2419ef0ef5b729b88491be1d28ab46248b645645c44Andrew M. Kuchling um = _os.umask(0) 2429ef0ef5b729b88491be1d28ab46248b645645c44Andrew M. Kuchling _os.umask(um) 2439ef0ef5b729b88491be1d28ab46248b645645c44Andrew M. Kuchling except AttributeError: 2449ef0ef5b729b88491be1d28ab46248b645645c44Andrew M. Kuchling pass 2459ef0ef5b729b88491be1d28ab46248b645645c44Andrew M. Kuchling else: 2469ef0ef5b729b88491be1d28ab46248b645645c44Andrew M. Kuchling # Turn off any bits that are set in the umask 2479ef0ef5b729b88491be1d28ab46248b645645c44Andrew M. Kuchling mode = mode & (~um) 248f733abb7831d6566cb0fccd0550d58ec3b7f05a4Tim Peters 2492c8373bc234039fff699df9c28d2cb74efd6a37cFred Drake return _Database(file, mode) 250