• 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        with shelve.Shelf(d1, protocol=0) as s:
92            s['key1'] = (1,2,3,4)
93            self.assertEqual(s['key1'], (1,2,3,4))
94        d2 = byteskeydict()
95        with shelve.Shelf(d2, protocol=1) as s:
96            s['key1'] = (1,2,3,4)
97            self.assertEqual(s['key1'], (1,2,3,4))
98
99        self.assertEqual(len(d1), 1)
100        self.assertEqual(len(d2), 1)
101        self.assertNotEqual(d1.items(), d2.items())
102
103    def test_mutable_entry(self):
104        d1 = byteskeydict()
105        with shelve.Shelf(d1, protocol=2, writeback=False) as s:
106            s['key1'] = [1,2,3,4]
107            self.assertEqual(s['key1'], [1,2,3,4])
108            s['key1'].append(5)
109            self.assertEqual(s['key1'], [1,2,3,4])
110
111        d2 = byteskeydict()
112        with shelve.Shelf(d2, protocol=2, writeback=True) as s:
113            s['key1'] = [1,2,3,4]
114            self.assertEqual(s['key1'], [1,2,3,4])
115            s['key1'].append(5)
116            self.assertEqual(s['key1'], [1,2,3,4,5])
117
118        self.assertEqual(len(d1), 1)
119        self.assertEqual(len(d2), 1)
120
121    def test_keyencoding(self):
122        d = {}
123        key = 'Pöp'
124        # the default keyencoding is utf-8
125        shelve.Shelf(d)[key] = [1]
126        self.assertIn(key.encode('utf-8'), d)
127        # but a different one can be given
128        shelve.Shelf(d, keyencoding='latin-1')[key] = [1]
129        self.assertIn(key.encode('latin-1'), d)
130        # with all consequences
131        s = shelve.Shelf(d, keyencoding='ascii')
132        self.assertRaises(UnicodeEncodeError, s.__setitem__, key, [1])
133
134    def test_writeback_also_writes_immediately(self):
135        # Issue 5754
136        d = {}
137        key = 'key'
138        encodedkey = key.encode('utf-8')
139        with shelve.Shelf(d, writeback=True) as s:
140            s[key] = [1]
141            p1 = d[encodedkey]  # Will give a KeyError if backing store not updated
142            s['key'].append(2)
143        p2 = d[encodedkey]
144        self.assertNotEqual(p1, p2)  # Write creates new object in store
145
146    def test_with(self):
147        d1 = {}
148        with shelve.Shelf(d1, protocol=2, writeback=False) as s:
149            s['key1'] = [1,2,3,4]
150            self.assertEqual(s['key1'], [1,2,3,4])
151            self.assertEqual(len(s), 1)
152        self.assertRaises(ValueError, len, s)
153        try:
154            s['key1']
155        except ValueError:
156            pass
157        else:
158            self.fail('Closed shelf should not find a key')
159
160    def test_default_protocol(self):
161        with shelve.Shelf({}) as s:
162            self.assertEqual(s._protocol, 3)
163
164from test import mapping_tests
165
166class TestShelveBase(mapping_tests.BasicTestMappingProtocol):
167    fn = "shelftemp.db"
168    counter = 0
169    def __init__(self, *args, **kw):
170        self._db = []
171        mapping_tests.BasicTestMappingProtocol.__init__(self, *args, **kw)
172    type2test = shelve.Shelf
173    def _reference(self):
174        return {"key1":"value1", "key2":2, "key3":(1,2,3)}
175    def _empty_mapping(self):
176        if self._in_mem:
177            x= shelve.Shelf(byteskeydict(), **self._args)
178        else:
179            self.counter+=1
180            x= shelve.open(self.fn+str(self.counter), **self._args)
181        self._db.append(x)
182        return x
183    def tearDown(self):
184        for db in self._db:
185            db.close()
186        self._db = []
187        if not self._in_mem:
188            for f in glob.glob(self.fn+"*"):
189                support.unlink(f)
190
191class TestAsciiFileShelve(TestShelveBase):
192    _args={'protocol':0}
193    _in_mem = False
194class TestBinaryFileShelve(TestShelveBase):
195    _args={'protocol':1}
196    _in_mem = False
197class TestProto2FileShelve(TestShelveBase):
198    _args={'protocol':2}
199    _in_mem = False
200class TestAsciiMemShelve(TestShelveBase):
201    _args={'protocol':0}
202    _in_mem = True
203class TestBinaryMemShelve(TestShelveBase):
204    _args={'protocol':1}
205    _in_mem = True
206class TestProto2MemShelve(TestShelveBase):
207    _args={'protocol':2}
208    _in_mem = True
209
210def test_main():
211    for module in dbm_iterator():
212        support.run_unittest(
213            TestAsciiFileShelve,
214            TestBinaryFileShelve,
215            TestProto2FileShelve,
216            TestAsciiMemShelve,
217            TestBinaryMemShelve,
218            TestProto2MemShelve,
219            TestCase
220        )
221
222if __name__ == "__main__":
223    test_main()
224