Skip to content

Commit 4631991

Browse files
committed
gh-113093: add parameter 'mode' in shelve.open, letting users control file's type and access permissions
1 parent 71fa314 commit 4631991

5 files changed

Lines changed: 34 additions & 8 deletions

File tree

Doc/library/shelve.rst

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ lots of shared sub-objects. The keys are ordinary strings.
1818

1919

2020
.. function:: open(filename, flag='c', protocol=None, writeback=False, *, \
21-
serializer=None, deserializer=None)
21+
mode=0o666, serializer=None, deserializer=None)
2222

2323
Open a persistent dictionary. The filename specified is the base filename for
2424
the underlying database. As a side-effect, an extension may be added to the
@@ -42,6 +42,9 @@ lots of shared sub-objects. The keys are ordinary strings.
4242
determine which accessed entries are mutable, nor which ones were actually
4343
mutated).
4444

45+
The optional *mode* parameter controls the file mode (permissions) when creating
46+
a new shelf. It has the same interpretation as the *mode* parameter of :func:`dbm.open`.
47+
4548
By default, :mod:`!shelve` uses :func:`pickle.dumps` and :func:`pickle.loads`
4649
for serializing and deserializing. This can be changed by supplying
4750
*serializer* and *deserializer*, respectively.
@@ -68,6 +71,9 @@ lots of shared sub-objects. The keys are ordinary strings.
6871
Accepts custom *serializer* and *deserializer* functions in place of
6972
:func:`pickle.dumps` and :func:`pickle.loads`.
7073

74+
.. versionchanged:: next
75+
Accepts *mode* to control file mode, behavior is the same as in :func:`dbm.open`.
76+
7177
.. note::
7278

7379
Do not rely on the shelf being closed automatically; always call
@@ -209,20 +215,23 @@ Restrictions
209215

210216

211217
.. class:: DbfilenameShelf(filename, flag='c', protocol=None, \
212-
writeback=False, *, serializer=None, \
218+
writeback=False, *, mode=0o666, serializer=None \
213219
deserializer=None)
214220
215221
A subclass of :class:`Shelf` which accepts a *filename* instead of a dict-like
216222
object. The underlying file will be opened using :func:`dbm.open`. By
217223
default, the file will be created and opened for both read and write. The
218224
optional *flag* parameter has the same interpretation as for the
219-
:func:`.open` function. The optional *protocol*, *writeback*, *serializer*
225+
:func:`.open` function. The optional *mode*, *protocol*, *writeback*, *serializer*
220226
and *deserializer* parameters have the same interpretation as in
221227
:func:`~shelve.open`.
222228

223229
.. versionchanged:: 3.15
224230
Added the *serializer* and *deserializer* parameters.
225231

232+
.. versionchanged:: next
233+
Added the *mode* parameter.
234+
226235

227236
.. _shelve-example:
228237

Doc/whatsnew/3.16.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,12 @@ mimetypes
151151
:meth:`mimetypes.MimeTypes.add_type`.
152152
Undotted extensions now raise a :exc:`ValueError`.
153153

154+
shelve
155+
------
156+
157+
* Add suport for custom mode in :func:`shelve.open`.
158+
(Contributed by Guilherme Crocetti in :gh:`113093`.)
159+
154160
shutil
155161
------
156162

Lib/shelve.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -236,9 +236,9 @@ class DbfilenameShelf(Shelf):
236236
"""
237237

238238
def __init__(self, filename, flag='c', protocol=None, writeback=False, *,
239-
serializer=None, deserializer=None):
239+
mode=0o666, serializer=None, deserializer=None):
240240
import dbm
241-
Shelf.__init__(self, dbm.open(filename, flag), protocol, writeback,
241+
Shelf.__init__(self, dbm.open(filename, flag, mode), protocol, writeback,
242242
serializer=serializer, deserializer=deserializer)
243243

244244
def clear(self):
@@ -249,18 +249,20 @@ def clear(self):
249249
self.dict.clear()
250250

251251
def open(filename, flag='c', protocol=None, writeback=False, *,
252-
serializer=None, deserializer=None):
252+
mode=0o666, serializer=None, deserializer=None):
253253
"""Open a persistent dictionary for reading and writing.
254254
255255
The filename parameter is the base filename for the underlying
256256
database. As a side-effect, an extension may be added to the
257257
filename and more than one file may be created. The optional flag
258258
parameter has the same interpretation as the flag parameter of
259259
dbm.open(). The optional protocol parameter specifies the
260-
version of the pickle protocol.
260+
version of the pickle protocol. The optional mode parameter is
261+
passed to dbm.open() and controls the file mode when creating a
262+
new shelf, set to 0666 by default.
261263
262264
See the module's __doc__ string for an overview of the interface.
263265
"""
264266

265-
return DbfilenameShelf(filename, flag, protocol, writeback,
267+
return DbfilenameShelf(filename, flag, protocol, writeback, mode=mode,
266268
serializer=serializer, deserializer=deserializer)

Lib/test/test_shelve.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import pickle
66
import os
77

8+
from unittest import mock
89
from test.support import import_helper, os_helper, subTests
910
from collections.abc import MutableMapping
1011
from test.test_dbm import dbm_iterator
@@ -47,6 +48,12 @@ class TestCase(unittest.TestCase):
4748
dirname = os_helper.TESTFN
4849
fn = os.path.join(os_helper.TESTFN, "shelftemp.db")
4950

51+
@mock.patch("dbm.open", autospec=True)
52+
def test_open_calls_dbm_as_expected(self, dbm_open):
53+
shelf_open_mode = 0o433
54+
shelve.open(filename=self.fn, mode=shelf_open_mode)
55+
dbm_open.assert_called_once_with(self.fn, 'c', shelf_open_mode)
56+
5057
def test_close(self):
5158
d1 = {}
5259
s = shelve.Shelf(d1, protocol=2, writeback=False)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add parameter *mode* in :func:`shelve.open`.
2+
Patch by Guilherme Crocetti.

0 commit comments

Comments
 (0)