(root)/
Python-3.12.0/
Lib/
test/
test_shelve.py
       1  import unittest
       2  import dbm
       3  import shelve
       4  import pickle
       5  import os
       6  
       7  from test.support import os_helper
       8  from collections.abc import MutableMapping
       9  from test.test_dbm import dbm_iterator
      10  
      11  def L1(s):
      12      return s.decode("latin-1")
      13  
      14  class ESC[4;38;5;81mbyteskeydict(ESC[4;38;5;149mMutableMapping):
      15      "Mapping that supports bytes keys"
      16  
      17      def __init__(self):
      18          self.d = {}
      19  
      20      def __getitem__(self, key):
      21          return self.d[L1(key)]
      22  
      23      def __setitem__(self, key, value):
      24          self.d[L1(key)] = value
      25  
      26      def __delitem__(self, key):
      27          del self.d[L1(key)]
      28  
      29      def __len__(self):
      30          return len(self.d)
      31  
      32      def iterkeys(self):
      33          for k in self.d.keys():
      34              yield k.encode("latin-1")
      35  
      36      __iter__ = iterkeys
      37  
      38      def keys(self):
      39          return list(self.iterkeys())
      40  
      41      def copy(self):
      42          return byteskeydict(self.d)
      43  
      44  
      45  class ESC[4;38;5;81mTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      46      dirname = os_helper.TESTFN
      47      fn = os.path.join(os_helper.TESTFN, "shelftemp.db")
      48  
      49      def test_close(self):
      50          d1 = {}
      51          s = shelve.Shelf(d1, protocol=2, writeback=False)
      52          s['key1'] = [1,2,3,4]
      53          self.assertEqual(s['key1'], [1,2,3,4])
      54          self.assertEqual(len(s), 1)
      55          s.close()
      56          self.assertRaises(ValueError, len, s)
      57          try:
      58              s['key1']
      59          except ValueError:
      60              pass
      61          else:
      62              self.fail('Closed shelf should not find a key')
      63  
      64      def test_open_template(self, filename=None, protocol=None):
      65          os.mkdir(self.dirname)
      66          self.addCleanup(os_helper.rmtree, self.dirname)
      67          s = shelve.open(filename=filename if filename is not None else self.fn,
      68                          protocol=protocol)
      69          try:
      70              s['key1'] = (1,2,3,4)
      71              self.assertEqual(s['key1'], (1,2,3,4))
      72          finally:
      73              s.close()
      74  
      75      def test_ascii_file_shelf(self):
      76          self.test_open_template(protocol=0)
      77  
      78      def test_binary_file_shelf(self):
      79          self.test_open_template(protocol=1)
      80  
      81      def test_proto2_file_shelf(self):
      82          self.test_open_template(protocol=2)
      83  
      84      def test_pathlib_path_file_shelf(self):
      85          self.test_open_template(filename=os_helper.FakePath(self.fn))
      86  
      87      def test_bytes_path_file_shelf(self):
      88          self.test_open_template(filename=os.fsencode(self.fn))
      89  
      90      def test_pathlib_bytes_path_file_shelf(self):
      91          self.test_open_template(filename=os_helper.FakePath(os.fsencode(self.fn)))
      92  
      93      def test_in_memory_shelf(self):
      94          d1 = byteskeydict()
      95          with shelve.Shelf(d1, protocol=0) as s:
      96              s['key1'] = (1,2,3,4)
      97              self.assertEqual(s['key1'], (1,2,3,4))
      98          d2 = byteskeydict()
      99          with shelve.Shelf(d2, protocol=1) as s:
     100              s['key1'] = (1,2,3,4)
     101              self.assertEqual(s['key1'], (1,2,3,4))
     102  
     103          self.assertEqual(len(d1), 1)
     104          self.assertEqual(len(d2), 1)
     105          self.assertNotEqual(d1.items(), d2.items())
     106  
     107      def test_mutable_entry(self):
     108          d1 = byteskeydict()
     109          with shelve.Shelf(d1, protocol=2, writeback=False) as s:
     110              s['key1'] = [1,2,3,4]
     111              self.assertEqual(s['key1'], [1,2,3,4])
     112              s['key1'].append(5)
     113              self.assertEqual(s['key1'], [1,2,3,4])
     114  
     115          d2 = byteskeydict()
     116          with shelve.Shelf(d2, protocol=2, writeback=True) as s:
     117              s['key1'] = [1,2,3,4]
     118              self.assertEqual(s['key1'], [1,2,3,4])
     119              s['key1'].append(5)
     120              self.assertEqual(s['key1'], [1,2,3,4,5])
     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          with shelve.Shelf(d, writeback=True) as s:
     144              s[key] = [1]
     145              p1 = d[encodedkey]  # Will give a KeyError if backing store not updated
     146              s['key'].append(2)
     147          p2 = d[encodedkey]
     148          self.assertNotEqual(p1, p2)  # Write creates new object in store
     149  
     150      def test_with(self):
     151          d1 = {}
     152          with shelve.Shelf(d1, protocol=2, writeback=False) as s:
     153              s['key1'] = [1,2,3,4]
     154              self.assertEqual(s['key1'], [1,2,3,4])
     155              self.assertEqual(len(s), 1)
     156          self.assertRaises(ValueError, len, s)
     157          try:
     158              s['key1']
     159          except ValueError:
     160              pass
     161          else:
     162              self.fail('Closed shelf should not find a key')
     163  
     164      def test_default_protocol(self):
     165          with shelve.Shelf({}) as s:
     166              self.assertEqual(s._protocol, pickle.DEFAULT_PROTOCOL)
     167  
     168  
     169  class ESC[4;38;5;81mTestShelveBase:
     170      type2test = shelve.Shelf
     171  
     172      def _reference(self):
     173          return {"key1":"value1", "key2":2, "key3":(1,2,3)}
     174  
     175  
     176  class ESC[4;38;5;81mTestShelveInMemBase(ESC[4;38;5;149mTestShelveBase):
     177      def _empty_mapping(self):
     178          return shelve.Shelf(byteskeydict(), **self._args)
     179  
     180  
     181  class ESC[4;38;5;81mTestShelveFileBase(ESC[4;38;5;149mTestShelveBase):
     182      counter = 0
     183  
     184      def _empty_mapping(self):
     185          self.counter += 1
     186          x = shelve.open(self.base_path + str(self.counter), **self._args)
     187          self.addCleanup(x.close)
     188          return x
     189  
     190      def setUp(self):
     191          dirname = os_helper.TESTFN
     192          os.mkdir(dirname)
     193          self.addCleanup(os_helper.rmtree, dirname)
     194          self.base_path = os.path.join(dirname, "shelftemp.db")
     195          self.addCleanup(setattr, dbm, '_defaultmod', dbm._defaultmod)
     196          dbm._defaultmod = self.dbm_mod
     197  
     198  
     199  from test import mapping_tests
     200  
     201  for proto in range(pickle.HIGHEST_PROTOCOL + 1):
     202      bases = (TestShelveInMemBase, mapping_tests.BasicTestMappingProtocol)
     203      name = f'TestProto{proto}MemShelve'
     204      globals()[name] = type(name, bases,
     205                             {'_args': {'protocol': proto}})
     206      bases = (TestShelveFileBase, mapping_tests.BasicTestMappingProtocol)
     207      for dbm_mod in dbm_iterator():
     208          assert dbm_mod.__name__.startswith('dbm.')
     209          suffix = dbm_mod.__name__[4:]
     210          name = f'TestProto{proto}File_{suffix}Shelve'
     211          globals()[name] = type(name, bases,
     212                                 {'dbm_mod': dbm_mod, '_args': {'protocol': proto}})
     213  
     214  
     215  if __name__ == "__main__":
     216      unittest.main()