| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent eb8ea26 commit c610aba
8 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -73,33 +73,39 @@ Key and values are always stored as bytes. This means that when | |||
| 73 | 73 | strings are used they are implicitly converted to the default encoding before | |
| 74 | 74 | being stored. | |
| 75 | 75 | ||
| 76 | + These objects also support being used in a :keyword:`with` statement, which | ||
| 77 | + will automatically close them when done. | ||
| 78 | + | ||
| 79 | + .. versionchanged:: 3.4 | ||
| 80 | + Added native support for the context management protocol to the objects | ||
| 81 | + returned by :func:`.open`. | ||
| 82 | + | ||
| 76 | 83 | The following example records some hostnames and a corresponding title, and | |
| 77 | 84 | then prints out the contents of the database:: | |
| 78 | 85 | ||
| 79 | 86 | import dbm | |
| 80 | 87 | ||
| 81 | 88 | # Open database, creating it if necessary. | |
| 82 | - db = dbm.open('cache', 'c') | ||
| 89 | + with dbm.open('cache', 'c') as db: | ||
| 83 | 90 | ||
| 84 | - # Record some values | ||
| 85 | - db[b'hello'] = b'there' | ||
| 86 | - db['www.python.org'] = 'Python Website' | ||
| 87 | - db['www.cnn.com'] = 'Cable News Network' | ||
| 91 | + # Record some values | ||
| 92 | + db[b'hello'] = b'there' | ||
| 93 | + db['www.python.org'] = 'Python Website' | ||
| 94 | + db['www.cnn.com'] = 'Cable News Network' | ||
| 88 | 95 | ||
| 89 | - # Note that the keys are considered bytes now. | ||
| 90 | - assert db[b'www.python.org'] == b'Python Website' | ||
| 91 | - # Notice how the value is now in bytes. | ||
| 92 | - assert db['www.cnn.com'] == b'Cable News Network' | ||
| 96 | + # Note that the keys are considered bytes now. | ||
| 97 | + assert db[b'www.python.org'] == b'Python Website' | ||
| 98 | + # Notice how the value is now in bytes. | ||
| 99 | + assert db['www.cnn.com'] == b'Cable News Network' | ||
| 93 | 100 | ||
| 94 | - # Often-used methods of the dict interface work too. | ||
| 95 | - print(db.get('python.org', b'not present')) | ||
| 101 | + # Often-used methods of the dict interface work too. | ||
| 102 | + print(db.get('python.org', b'not present')) | ||
| 96 | 103 | ||
| 97 | - # Storing a non-string key or value will raise an exception (most | ||
| 98 | - # likely a TypeError). | ||
| 99 | - db['www.yahoo.com'] = 4 | ||
| 104 | + # Storing a non-string key or value will raise an exception (most | ||
| 105 | + # likely a TypeError). | ||
| 106 | + db['www.yahoo.com'] = 4 | ||
| 100 | 107 | ||
| 101 | - # Close when done. | ||
| 102 | - db.close() | ||
| 108 | + # db is automatically closed when leaving the with statement. | ||
| 103 | 109 | ||
| 104 | 110 | ||
| 105 | 111 | .. seealso:: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -236,6 +236,12 @@ def _chmod(self, file): | |||
| 236 | 236 | if hasattr(self._os, 'chmod'): | |
| 237 | 237 | self._os.chmod(file, self._mode) | |
| 238 | 238 | ||
| 239 | + def __enter__(self): | ||
| 240 | + return self | ||
| 241 | + | ||
| 242 | + def __exit__(self, *args): | ||
| 243 | + self.close() | ||
| 244 | + | ||
| 239 | 245 | ||
| 240 | 246 | def open(file, flag=None, mode=0o666): | |
| 241 | 247 | """Open the database file, filename, and return corresponding object. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -184,6 +184,19 @@ def test_random(self): | |||
| 184 | 184 | self.assertEqual(expected, got) | |
| 185 | 185 | f.close() | |
| 186 | 186 | ||
| 187 | + def test_context_manager(self): | ||
| 188 | + with dumbdbm.open(_fname, 'c') as db: | ||
| 189 | + db["dumbdbm context manager"] = "context manager" | ||
| 190 | + | ||
| 191 | + with dumbdbm.open(_fname, 'r') as db: | ||
| 192 | + self.assertEqual(list(db.keys()), [b"dumbdbm context manager"]) | ||
| 193 | + | ||
| 194 | + # This currently just raises AttributeError rather than a specific | ||
| 195 | + # exception like the GNU or NDBM based implementations. See | ||
| 196 | + # http://bugs.python.org/issue19385 for details. | ||
| 197 | + with self.assertRaises(Exception): | ||
| 198 | + db.keys() | ||
| 199 | + | ||
| 187 | 200 | def tearDown(self): | |
| 188 | 201 | _delete_files() | |
| 189 | 202 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -81,6 +81,17 @@ def test_reorganize(self): | |||
| 81 | 81 | size2 = os.path.getsize(filename) | |
| 82 | 82 | self.assertTrue(size1 > size2 >= size0) | |
| 83 | 83 | ||
| 84 | + def test_context_manager(self): | ||
| 85 | + with gdbm.open(filename, 'c') as db: | ||
| 86 | + db["gdbm context manager"] = "context manager" | ||
| 87 | + | ||
| 88 | + with gdbm.open(filename, 'r') as db: | ||
| 89 | + self.assertEqual(list(db.keys()), [b"gdbm context manager"]) | ||
| 90 | + | ||
| 91 | + with self.assertRaises(gdbm.error) as cm: | ||
| 92 | + db.keys() | ||
| 93 | + self.assertEqual(str(cm.exception), | ||
| 94 | + "GDBM object has already been closed") | ||
| 84 | 95 | ||
| 85 | 96 | if __name__ == '__main__': | |
| 86 | 97 | unittest.main() | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -37,5 +37,18 @@ def test_modes(self): | |||
| 37 | 37 | except error: | |
| 38 | 38 | self.fail() | |
| 39 | 39 | ||
| 40 | + def test_context_manager(self): | ||
| 41 | + with dbm.ndbm.open(self.filename, 'c') as db: | ||
| 42 | + db["ndbm context manager"] = "context manager" | ||
| 43 | + | ||
| 44 | + with dbm.ndbm.open(self.filename, 'r') as db: | ||
| 45 | + self.assertEqual(list(db.keys()), [b"ndbm context manager"]) | ||
| 46 | + | ||
| 47 | + with self.assertRaises(dbm.ndbm.error) as cm: | ||
| 48 | + db.keys() | ||
| 49 | + self.assertEqual(str(cm.exception), | ||
| 50 | + "DBM object has already been closed") | ||
| 51 | + | ||
| 52 | + | ||
| 40 | 53 | if __name__ == '__main__': | |
| 41 | 54 | unittest.main() | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -50,6 +50,9 @@ Core and Builtins | |||
| 50 | 50 | Library | |
| 51 | 51 | ------- | |
| 52 | 52 | ||
| 53 | + - Issue #19282: dbm.open now supports the context manager protocol. (Inital | ||
| 54 | + patch by Claudiu Popa) | ||
| 55 | + | ||
| 53 | 56 | - Issue #8311: Added support for writing any bytes-like objects in the aifc, | |
| 54 | 57 | sunau, and wave modules. | |
| 55 | 58 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -313,6 +313,21 @@ dbm_setdefault(dbmobject *dp, PyObject *args) | |||
| 313 | 313 | return defvalue; | |
| 314 | 314 | } | |
| 315 | 315 | ||
| 316 | + static PyObject * | ||
| 317 | + dbm__enter__(PyObject *self, PyObject *args) | ||
| 318 | + { | ||
| 319 | + Py_INCREF(self); | ||
| 320 | + return self; | ||
| 321 | + } | ||
| 322 | + | ||
| 323 | + static PyObject * | ||
| 324 | + dbm__exit__(PyObject *self, PyObject *args) | ||
| 325 | + { | ||
| 326 | + _Py_IDENTIFIER(close); | ||
| 327 | + return _PyObject_CallMethodId(self, &PyId_close, NULL); | ||
| 328 | + } | ||
| 329 | + | ||
| 330 | + | ||
| 316 | 331 | static PyMethodDef dbm_methods[] = { | |
| 317 | 332 | {"close", (PyCFunction)dbm__close, METH_NOARGS, | |
| 318 | 333 | "close()\nClose the database."}, | |
@@ -325,6 +340,8 @@ static PyMethodDef dbm_methods[] = { | |||
| 325 | 340 | "setdefault(key[, default]) -> value\n" | |
| 326 | 341 | "Return the value for key if present, otherwise default. If key\n" | |
| 327 | 342 | "is not in the database, it is inserted with default as the value."}, | |
| 343 | + {"__enter__", dbm__enter__, METH_NOARGS, NULL}, | ||
| 344 | + {"__exit__", dbm__exit__, METH_VARARGS, NULL}, | ||
| 328 | 345 | {NULL, NULL} /* sentinel */ | |
| 329 | 346 | }; | |
| 330 | 347 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -425,6 +425,20 @@ dbm_sync(dbmobject *dp, PyObject *unused) | |||
| 425 | 425 | return Py_None; | |
| 426 | 426 | } | |
| 427 | 427 | ||
| 428 | + static PyObject * | ||
| 429 | + dbm__enter__(PyObject *self, PyObject *args) | ||
| 430 | + { | ||
| 431 | + Py_INCREF(self); | ||
| 432 | + return self; | ||
| 433 | + } | ||
| 434 | + | ||
| 435 | + static PyObject * | ||
| 436 | + dbm__exit__(PyObject *self, PyObject *args) | ||
| 437 | + { | ||
| 438 | + _Py_IDENTIFIER(close); | ||
| 439 | + return _PyObject_CallMethodId(self, &PyId_close, NULL); | ||
| 440 | + } | ||
| 441 | + | ||
| 428 | 442 | static PyMethodDef dbm_methods[] = { | |
| 429 | 443 | {"close", (PyCFunction)dbm_close, METH_NOARGS, dbm_close__doc__}, | |
| 430 | 444 | {"keys", (PyCFunction)dbm_keys, METH_NOARGS, dbm_keys__doc__}, | |
@@ -434,6 +448,8 @@ static PyMethodDef dbm_methods[] = { | |||
| 434 | 448 | {"sync", (PyCFunction)dbm_sync, METH_NOARGS, dbm_sync__doc__}, | |
| 435 | 449 | {"get", (PyCFunction)dbm_get, METH_VARARGS, dbm_get__doc__}, | |
| 436 | 450 | {"setdefault",(PyCFunction)dbm_setdefault,METH_VARARGS, dbm_setdefault__doc__}, | |
| 451 | + {"__enter__", dbm__enter__, METH_NOARGS, NULL}, | ||
| 452 | + {"__exit__", dbm__exit__, METH_VARARGS, NULL}, | ||
| 437 | 453 | {NULL, NULL} /* sentinel */ | |
| 438 | 454 | }; | |
| 439 | 455 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments