blob: dcb5aefc3bae17868830ece63e18902b7444e403 [file] [log] [blame]
Skip Montanaro3bf99e32002-12-08 18:36:24 +00001import unittest
Serhiy Storchaka6b867022021-10-29 12:40:22 +03002import dbm
3import os
Skip Montanaro3bf99e32002-12-08 18:36:24 +00004import shelve
5import glob
Zackery Spytzdf592732020-10-29 03:44:35 -06006import pickle
7
Benjamin Petersonee8712c2008-05-20 21:35:26 +00008from test import support
Hai Shia089d212020-07-06 17:15:08 +08009from test.support import os_helper
Raymond Hettinger57d1a882011-02-23 00:46:28 +000010from collections.abc import MutableMapping
Georg Brandl24420152008-05-26 16:32:26 +000011from test.test_dbm import dbm_iterator
Martin v. Löwis79c32082007-08-11 06:57:14 +000012
13def L1(s):
14 return s.decode("latin-1")
15
Raymond Hettingeredf3b732008-02-04 22:07:15 +000016class byteskeydict(MutableMapping):
Martin v. Löwis79c32082007-08-11 06:57:14 +000017 "Mapping that supports bytes keys"
18
19 def __init__(self):
20 self.d = {}
21
22 def __getitem__(self, key):
23 return self.d[L1(key)]
24
25 def __setitem__(self, key, value):
26 self.d[L1(key)] = value
27
28 def __delitem__(self, key):
29 del self.d[L1(key)]
30
Raymond Hettingeredf3b732008-02-04 22:07:15 +000031 def __len__(self):
32 return len(self.d)
33
Martin v. Löwis79c32082007-08-11 06:57:14 +000034 def iterkeys(self):
35 for k in self.d.keys():
Guido van Rossum83800a62007-08-29 02:57:31 +000036 yield k.encode("latin-1")
Martin v. Löwis79c32082007-08-11 06:57:14 +000037
Raymond Hettingeredf3b732008-02-04 22:07:15 +000038 __iter__ = iterkeys
39
Martin v. Löwis79c32082007-08-11 06:57:14 +000040 def keys(self):
41 return list(self.iterkeys())
42
43 def copy(self):
44 return byteskeydict(self.d)
45
Skip Montanaro3bf99e32002-12-08 18:36:24 +000046
47class TestCase(unittest.TestCase):
Serhiy Storchaka6b867022021-10-29 12:40:22 +030048 dirname = os_helper.TESTFN
49 fn = os.path.join(os_helper.TESTFN, "shelftemp.db")
Guido van Rossum8d9db042007-05-18 21:57:09 +000050
Benjamin Petersond6313712008-07-31 16:23:04 +000051 def test_close(self):
52 d1 = {}
53 s = shelve.Shelf(d1, protocol=2, writeback=False)
54 s['key1'] = [1,2,3,4]
55 self.assertEqual(s['key1'], [1,2,3,4])
56 self.assertEqual(len(s), 1)
57 s.close()
58 self.assertRaises(ValueError, len, s)
59 try:
60 s['key1']
61 except ValueError:
62 pass
63 else:
64 self.fail('Closed shelf should not find a key')
65
Serhiy Storchaka6b867022021-10-29 12:40:22 +030066 def test_open_template(self, protocol=None):
67 os.mkdir(self.dirname)
68 self.addCleanup(os_helper.rmtree, self.dirname)
69 s = shelve.open(self.fn, protocol=protocol)
Skip Montanaro3bf99e32002-12-08 18:36:24 +000070 try:
Skip Montanaro3bf99e32002-12-08 18:36:24 +000071 s['key1'] = (1,2,3,4)
72 self.assertEqual(s['key1'], (1,2,3,4))
Skip Montanaro3bf99e32002-12-08 18:36:24 +000073 finally:
Guido van Rossum8d9db042007-05-18 21:57:09 +000074 s.close()
Skip Montanaro3bf99e32002-12-08 18:36:24 +000075
Serhiy Storchaka6b867022021-10-29 12:40:22 +030076 def test_ascii_file_shelf(self):
77 self.test_open_template(protocol=0)
78
Skip Montanaro3bf99e32002-12-08 18:36:24 +000079 def test_binary_file_shelf(self):
Serhiy Storchaka6b867022021-10-29 12:40:22 +030080 self.test_open_template(protocol=1)
Skip Montanaro3bf99e32002-12-08 18:36:24 +000081
Martin v. Löwis153c9e42003-04-19 20:59:03 +000082 def test_proto2_file_shelf(self):
Serhiy Storchaka6b867022021-10-29 12:40:22 +030083 self.test_open_template(protocol=2)
Martin v. Löwis153c9e42003-04-19 20:59:03 +000084
Skip Montanaro3bf99e32002-12-08 18:36:24 +000085 def test_in_memory_shelf(self):
Martin v. Löwis79c32082007-08-11 06:57:14 +000086 d1 = byteskeydict()
Serhiy Storchaka5b10b982019-03-05 10:06:26 +020087 with shelve.Shelf(d1, protocol=0) as s:
88 s['key1'] = (1,2,3,4)
89 self.assertEqual(s['key1'], (1,2,3,4))
Martin v. Löwis79c32082007-08-11 06:57:14 +000090 d2 = byteskeydict()
Serhiy Storchaka5b10b982019-03-05 10:06:26 +020091 with shelve.Shelf(d2, protocol=1) as s:
92 s['key1'] = (1,2,3,4)
93 self.assertEqual(s['key1'], (1,2,3,4))
Skip Montanaro3bf99e32002-12-08 18:36:24 +000094
95 self.assertEqual(len(d1), 1)
Guido van Rossum83800a62007-08-29 02:57:31 +000096 self.assertEqual(len(d2), 1)
97 self.assertNotEqual(d1.items(), d2.items())
Skip Montanaro3bf99e32002-12-08 18:36:24 +000098
Martin v. Löwis153c9e42003-04-19 20:59:03 +000099 def test_mutable_entry(self):
Martin v. Löwis79c32082007-08-11 06:57:14 +0000100 d1 = byteskeydict()
Serhiy Storchaka5b10b982019-03-05 10:06:26 +0200101 with shelve.Shelf(d1, protocol=2, writeback=False) as s:
102 s['key1'] = [1,2,3,4]
103 self.assertEqual(s['key1'], [1,2,3,4])
104 s['key1'].append(5)
105 self.assertEqual(s['key1'], [1,2,3,4])
Martin v. Löwis153c9e42003-04-19 20:59:03 +0000106
Martin v. Löwis79c32082007-08-11 06:57:14 +0000107 d2 = byteskeydict()
Serhiy Storchaka5b10b982019-03-05 10:06:26 +0200108 with shelve.Shelf(d2, protocol=2, writeback=True) as s:
109 s['key1'] = [1,2,3,4]
110 self.assertEqual(s['key1'], [1,2,3,4])
111 s['key1'].append(5)
112 self.assertEqual(s['key1'], [1,2,3,4,5])
Martin v. Löwis153c9e42003-04-19 20:59:03 +0000113
114 self.assertEqual(len(d1), 1)
115 self.assertEqual(len(d2), 1)
116
Georg Brandl732324a2010-12-04 11:12:43 +0000117 def test_keyencoding(self):
118 d = {}
119 key = 'Pöp'
120 # the default keyencoding is utf-8
121 shelve.Shelf(d)[key] = [1]
122 self.assertIn(key.encode('utf-8'), d)
123 # but a different one can be given
Marc-André Lemburg8f36af72011-02-25 15:42:01 +0000124 shelve.Shelf(d, keyencoding='latin-1')[key] = [1]
125 self.assertIn(key.encode('latin-1'), d)
Georg Brandl732324a2010-12-04 11:12:43 +0000126 # with all consequences
127 s = shelve.Shelf(d, keyencoding='ascii')
128 self.assertRaises(UnicodeEncodeError, s.__setitem__, key, [1])
129
R. David Murrayddb3ed02010-02-11 02:42:19 +0000130 def test_writeback_also_writes_immediately(self):
131 # Issue 5754
132 d = {}
133 key = 'key'
134 encodedkey = key.encode('utf-8')
Serhiy Storchaka5b10b982019-03-05 10:06:26 +0200135 with shelve.Shelf(d, writeback=True) as s:
136 s[key] = [1]
137 p1 = d[encodedkey] # Will give a KeyError if backing store not updated
138 s['key'].append(2)
R. David Murrayddb3ed02010-02-11 02:42:19 +0000139 p2 = d[encodedkey]
140 self.assertNotEqual(p1, p2) # Write creates new object in store
141
Andrew Svetlovef08fb12012-10-06 13:52:19 +0300142 def test_with(self):
143 d1 = {}
144 with shelve.Shelf(d1, protocol=2, writeback=False) as s:
145 s['key1'] = [1,2,3,4]
146 self.assertEqual(s['key1'], [1,2,3,4])
147 self.assertEqual(len(s), 1)
148 self.assertRaises(ValueError, len, s)
149 try:
150 s['key1']
151 except ValueError:
152 pass
153 else:
154 self.fail('Closed shelf should not find a key')
Martin v. Löwis153c9e42003-04-19 20:59:03 +0000155
Berker Peksag8faca612016-07-01 12:33:00 +0300156 def test_default_protocol(self):
157 with shelve.Shelf({}) as s:
Zackery Spytzdf592732020-10-29 03:44:35 -0600158 self.assertEqual(s._protocol, pickle.DEFAULT_PROTOCOL)
Berker Peksag8faca612016-07-01 12:33:00 +0300159
Skip Montanaro3bf99e32002-12-08 18:36:24 +0000160
Serhiy Storchaka6b867022021-10-29 12:40:22 +0300161class TestShelveBase:
Walter Dörwald118f9312004-06-02 18:42:25 +0000162 type2test = shelve.Shelf
Serhiy Storchaka6b867022021-10-29 12:40:22 +0300163
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000164 def _reference(self):
165 return {"key1":"value1", "key2":2, "key3":(1,2,3)}
Serhiy Storchaka6b867022021-10-29 12:40:22 +0300166
167
168class TestShelveInMemBase(TestShelveBase):
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000169 def _empty_mapping(self):
Serhiy Storchaka6b867022021-10-29 12:40:22 +0300170 return shelve.Shelf(byteskeydict(), **self._args)
171
172
173class TestShelveFileBase(TestShelveBase):
174 counter = 0
175
176 def _empty_mapping(self):
177 self.counter += 1
178 x = shelve.open(self.base_path + str(self.counter), **self._args)
179 self.addCleanup(x.close)
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000180 return x
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000181
Serhiy Storchaka6b867022021-10-29 12:40:22 +0300182 def setUp(self):
183 dirname = os_helper.TESTFN
184 os.mkdir(dirname)
185 self.addCleanup(os_helper.rmtree, dirname)
186 self.base_path = os.path.join(dirname, "shelftemp.db")
187 self.addCleanup(setattr, dbm, '_defaultmod', dbm._defaultmod)
188 dbm._defaultmod = self.dbm_mod
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000189
Serhiy Storchaka6b867022021-10-29 12:40:22 +0300190
191from test import mapping_tests
192
193for proto in range(pickle.HIGHEST_PROTOCOL + 1):
194 bases = (TestShelveInMemBase, mapping_tests.BasicTestMappingProtocol)
195 name = f'TestProto{proto}MemShelve'
196 globals()[name] = type(name, bases,
197 {'_args': {'protocol': proto}})
198 bases = (TestShelveFileBase, mapping_tests.BasicTestMappingProtocol)
199 for dbm_mod in dbm_iterator():
200 assert dbm_mod.__name__.startswith('dbm.')
201 suffix = dbm_mod.__name__[4:]
202 name = f'TestProto{proto}File_{suffix}Shelve'
203 globals()[name] = type(name, bases,
204 {'dbm_mod': dbm_mod, '_args': {'protocol': proto}})
205
Skip Montanaro3bf99e32002-12-08 18:36:24 +0000206
207if __name__ == "__main__":
Serhiy Storchaka6b867022021-10-29 12:40:22 +0300208 unittest.main()