• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import unittest
2import shelve
3import glob
4from test import support
5from collections.abc import MutableMapping
6from test.test_dbm import dbm_iterator
7
8def L1(s):
9    return s.decode("latin-1")
10
11class byteskeydict(MutableMapping):
12    "Mapping that supports bytes keys"
13
14    def __init__(self):
15        self.d = {}
16
17    def __getitem__(self, key):
18        return self.d[L1(key)]
19
20    def __setitem__(self, key, value):
21        self.d[L1(key)] = value
22
23    def __delitem__(self, key):
24        del self.d[L1(key)]
25
26    def __len__(self):
27        return len(self.d)
28
29    def iterkeys(self):
30        for k in self.d.keys():
31            yield k.encode("latin-1")
32
33    __iter__ = iterkeys
34
35    def keys(self):
36        return list(self.iterkeys())
37
38    def copy(self):
39        return byteskeydict(self.d)
40
41
42class TestCase(unittest.TestCase):
43
44    fn = "shelftemp.db"
45
46    def tearDown(self):
47        for f in glob.glob(self.fn+"*"):
48            support.unlink(f)
49
50    def test_close(self):
51        d1 = {}
52        s = shelve.Shelf(d1, protocol=2, writeback=False)
53        s['key1'] = [1,2,3,4]
54        self.assertEqual(s['key1'], [1,2,3,4])
55        self.assertEqual(len(s), 1)
56        s.close()
57        self.assertRaises(ValueError, len, s)
58        try:
59            s['key1']
60        except ValueError:
61            pass
62        else:
63            self.fail('Closed shelf should not find a key')
64
65    def test_ascii_file_shelf(self):
66        s = shelve.open(self.fn, protocol=0)
67        try:
68            s['key1'] = (1,2,3,4)
69            self.assertEqual(s['key1'], (1,2,3,4))
70        finally:
71            s.close()
72
73    def test_binary_file_shelf(self):
74        s = shelve.open(self.fn, protocol=1)
75        try:
76            s['key1'] = (1,2,3,4)
77            self.assertEqual(s['key1'], (1,2,3,4))
78        finally:
79            s.close()
80
81    def test_proto2_file_shelf(self):
82        s = shelve.open(self.fn, protocol=2)
83        try:
84            s['key1'] = (1,2,3,4)
85            self.assertEqual(s['key1'], (1,2,3,4))
86        finally:
87            s.close()
88
89    def test_in_memory_shelf(self):
90        d1 = byteskeydict()
91        s = shelve.Shelf(d1, protocol=0)
92        s['key1'] = (1,2,3,4)
93        self.assertEqual(s['key1'], (1,2,3,4))
94        s.close()
95        d2 = byteskeydict()
96        s = shelve.Shelf(d2, protocol=1)
97        s['key1'] = (1,2,3,4)
98        self.assertEqual(s['key1'], (1,2,3,4))
99        s.close()
100
101        self.assertEqual(len(d1), 1)
102        self.assertEqual(len(d2), 1)
103        self.assertNotEqual(d1.items(), d2.items())
104
105    def test_mutable_entry(self):
106        d1 = byteskeydict()
107        s = shelve.Shelf(d1, protocol=2, writeback=False)
108        s['key1'] = [1,2,3,4]
109        self.assertEqual(s['key1'], [1,2,3,4])
110        s['key1'].append(5)
111        self.assertEqual(s['key1'], [1,2,3,4])
112        s.close()
113
114        d2 = byteskeydict()
115        s = shelve.Shelf(d2, protocol=2, writeback=True)
116        s['key1'] = [1,2,3,4]
117        self.assertEqual(s['key1'], [1,2,3,4])
118        s['key1'].append(5)
119        self.assertEqual(s['key1'], [1,2,3,4,5])
120        s.close()
121
122        self.assertEqual(len(d1), 1)
123        self.assertEqual(len(d2), 1)
124
125    def test_keyencoding(self):
126        d = {}
127        key = 'Pöp'
128        # the default keyencoding is utf-8
129        shelve.Shelf(d)[key] = [1]
130        self.assertIn(key.encode('utf-8'), d)
131        # but a different one can be given
132        shelve.Shelf(d, keyencoding='latin-1')[key] = [1]
133        self.assertIn(key.encode('latin-1'), d)
134        # with all consequences
135        s = shelve.Shelf(d, keyencoding='ascii')
136        self.assertRaises(UnicodeEncodeError, s.__setitem__, key, [1])
137
138    def test_writeback_also_writes_immediately(self):
139        # Issue 5754
140        d = {}
141        key = 'key'
142        encodedkey = key.encode('utf-8')
143        s = shelve.Shelf(d, writeback=True)
144        s[key] = [1]
145        p1 = d[encodedkey]  # Will give a KeyError if backing store not updated
146        s['key'].append(2)
147        s.close()
148        p2 = d[encodedkey]
149        self.assertNotEqual(p1, p2)  # Write creates new object in store
150
151    def test_with(self):
152        d1 = {}
153        with shelve.Shelf(d1, protocol=2, writeback=False) as s:
154            s['key1'] = [1,2,3,4]
155            self.assertEqual(s['key1'], [1,2,3,4])
156            self.assertEqual(len(s), 1)
157        self.assertRaises(ValueError, len, s)
158        try:
159            s['key1']
160        except ValueError:
161            pass
162        else:
163            self.fail('Closed shelf should not find a key')
164
165    def test_default_protocol(self):
166        with shelve.Shelf({}) as s:
167            self.assertEqual(s._protocol, 3)
168
169from test import mapping_tests
170
171class TestShelveBase(mapping_tests.BasicTestMappingProtocol):
172    fn = "shelftemp.db"
173    counter = 0
174    def __init__(self, *args, **kw):
175        self._db = []
176        mapping_tests.BasicTestMappingProtocol.__init__(self, *args, **kw)
177    type2test = shelve.Shelf
178    def _reference(self):
179        return {"key1":"value1", "key2":2, "key3":(1,2,3)}
180    def _empty_mapping(self):
181        if self._in_mem:
182            x= shelve.Shelf(byteskeydict(), **self._args)
183        else:
184            self.counter+=1
185            x= shelve.open(self.fn+str(self.counter), **self._args)
186        self._db.append(x)
187        return x
188    def tearDown(self):
189        for db in self._db:
190            db.close()
191        self._db = []
192        if not self._in_mem:
193            for f in glob.glob(self.fn+"*"):
194                support.unlink(f)
195
196class TestAsciiFileShelve(TestShelveBase):
197    _args={'protocol':0}
198    _in_mem = False
199class TestBinaryFileShelve(TestShelveBase):
200    _args={'protocol':1}
201    _in_mem = False
202class TestProto2FileShelve(TestShelveBase):
203    _args={'protocol':2}
204    _in_mem = False
205class TestAsciiMemShelve(TestShelveBase):
206    _args={'protocol':0}
207    _in_mem = True
208class TestBinaryMemShelve(TestShelveBase):
209    _args={'protocol':1}
210    _in_mem = True
211class TestProto2MemShelve(TestShelveBase):
212    _args={'protocol':2}
213    _in_mem = True
214
215def test_main():
216    for module in dbm_iterator():
217        support.run_unittest(
218            TestAsciiFileShelve,
219            TestBinaryFileShelve,
220            TestProto2FileShelve,
221            TestAsciiMemShelve,
222            TestBinaryMemShelve,
223            TestProto2MemShelve,
224            TestCase
225        )
226
227if __name__ == "__main__":
228    test_main()
229