| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -47,6 +47,7 @@ class _Database(collections.MutableMapping): | |||
| 47 | 47 | ||
| 48 | 48 | def __init__(self, filebasename, mode, flag='c'): | |
| 49 | 49 | self._mode = mode | |
| 50 | + self._readonly = (flag == 'r') | ||
| 50 | 51 | ||
| 51 | 52 | # The directory file is a text file. Each line looks like | |
| 52 | 53 | # "%r, (%d, %d)\n" % (key, pos, siz) | |
@@ -91,8 +92,9 @@ def _update(self): | |||
| 91 | 92 | try: | |
| 92 | 93 | f = _io.open(self._dirfile, 'r', encoding="Latin-1") | |
| 93 | 94 | except OSError: | |
| 94 | - pass | ||
| 95 | + self._modified = not self._readonly | ||
| 95 | 96 | else: | |
| 97 | + self._modified = False | ||
| 96 | 98 | with f: | |
| 97 | 99 | for line in f: | |
| 98 | 100 | line = line.rstrip() | |
@@ -107,7 +109,7 @@ def _commit(self): | |||
| 107 | 109 | # CAUTION: It's vital that _commit() succeed, and _commit() can | |
| 108 | 110 | # be called from __del__(). Therefore we must never reference a | |
| 109 | 111 | # global in this routine. | |
| 110 | - if self._index is None: | ||
| 112 | + if self._index is None or not self._modified: | ||
| 111 | 113 | return # nothing to do | |
| 112 | 114 | ||
| 113 | 115 | try: | |
@@ -187,6 +189,7 @@ def __setitem__(self, key, val): | |||
| 187 | 189 | elif not isinstance(val, (bytes, bytearray)): | |
| 188 | 190 | raise TypeError("values must be bytes or strings") | |
| 189 | 191 | self._verify_open() | |
| 192 | + self._modified = True | ||
| 190 | 193 | if key not in self._index: | |
| 191 | 194 | self._addkey(key, self._addval(val)) | |
| 192 | 195 | else: | |
@@ -215,6 +218,7 @@ def __delitem__(self, key): | |||
| 215 | 218 | if isinstance(key, str): | |
| 216 | 219 | key = key.encode('utf-8') | |
| 217 | 220 | self._verify_open() | |
| 221 | + self._modified = True | ||
| 218 | 222 | # The blocks used by the associated value are lost. | |
| 219 | 223 | del self._index[key] | |
| 220 | 224 | # XXX It's unclear why we do a _commit() here (the code always | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -359,9 +359,9 @@ def _rmtree_inner(path): | |||
| 359 | 359 | mode = 0 | |
| 360 | 360 | if stat.S_ISDIR(mode): | |
| 361 | 361 | _waitfor(_rmtree_inner, fullname, waitall=True) | |
| 362 | - _force_run(path, os.rmdir, fullname) | ||
| 362 | + _force_run(fullname, os.rmdir, fullname) | ||
| 363 | 363 | else: | |
| 364 | - _force_run(path, os.unlink, fullname) | ||
| 364 | + _force_run(fullname, os.unlink, fullname) | ||
| 365 | 365 | _waitfor(_rmtree_inner, path, waitall=True) | |
| 366 | 366 | _waitfor(lambda p: _force_run(p, os.rmdir, p), path) | |
| 367 | 367 | else: | |
@@ -933,7 +933,7 @@ def temp_dir(path=None, quiet=False): | |||
| 933 | 933 | yield path | |
| 934 | 934 | finally: | |
| 935 | 935 | if dir_created: | |
| 936 | - shutil.rmtree(path) | ||
| 936 | + rmtree(path) | ||
| 937 | 937 | ||
| 938 | 938 | @contextlib.contextmanager | |
| 939 | 939 | def change_cwd(path, quiet=False): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5,6 +5,7 @@ | |||
| 5 | 5 | import io | |
| 6 | 6 | import operator | |
| 7 | 7 | import os | |
| 8 | + import stat | ||
| 8 | 9 | import unittest | |
| 9 | 10 | import dbm.dumb as dumbdbm | |
| 10 | 11 | from test import support | |
@@ -234,6 +235,21 @@ def test_eval(self): | |||
| 234 | 235 | pass | |
| 235 | 236 | self.assertEqual(stdout.getvalue(), '') | |
| 236 | 237 | ||
| 238 | + @unittest.skipUnless(hasattr(os, 'chmod'), 'test needs os.chmod()') | ||
| 239 | + def test_readonly_files(self): | ||
| 240 | + with support.temp_dir() as dir: | ||
| 241 | + fname = os.path.join(dir, 'db') | ||
| 242 | + with dumbdbm.open(fname, 'n') as f: | ||
| 243 | + self.assertEqual(list(f.keys()), []) | ||
| 244 | + for key in self._dict: | ||
| 245 | + f[key] = self._dict[key] | ||
| 246 | + os.chmod(fname + ".dir", stat.S_IRUSR) | ||
| 247 | + os.chmod(fname + ".dat", stat.S_IRUSR) | ||
| 248 | + os.chmod(dir, stat.S_IRUSR|stat.S_IXUSR) | ||
| 249 | + with dumbdbm.open(fname, 'r') as f: | ||
| 250 | + self.assertEqual(sorted(f.keys()), sorted(self._dict)) | ||
| 251 | + f.close() # don't write | ||
| 252 | + | ||
| 237 | 253 | def tearDown(self): | |
| 238 | 254 | _delete_files() | |
| 239 | 255 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -121,6 +121,9 @@ Core and Builtins | |||
| 121 | 121 | Library | |
| 122 | 122 | ------- | |
| 123 | 123 | ||
| 124 | + - Issue #28847: dbm.dumb now supports reading read-only files and no longer | ||
| 125 | + writes the index file when it is not changed. | ||
| 126 | + | ||
| 124 | 127 | - Issue #25659: In ctypes, prevent a crash calling the from_buffer() and | |
| 125 | 128 | from_buffer_copy() methods on abstract classes like Array. | |
| 126 | 129 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments