Index: Doc/library/shelve.rst =================================================================== --- Doc/library/shelve.rst (revision 78145) +++ Doc/library/shelve.rst (working copy) @@ -92,7 +92,7 @@ implementation used. -.. class:: Shelf(dict, protocol=None, writeback=False) +.. class:: Shelf(dict, protocol=None, writeback=False, keyencoding='utf-8') A subclass of :class:`collections.MutableMapping` which stores pickled values in the *dict* object. @@ -106,9 +106,12 @@ This allows natural operations on mutable entries, but can consume much more memory and make sync and close take a long time. + The *keyencoding* parameter is the encoding used to encode key values + before they are used with the underlying dict. -.. class:: BsdDbShelf(dict, protocol=None, writeback=False) +.. class:: BsdDbShelf(dict, protocol=None, writeback=False, keyencoding='utf-8') + A subclass of :class:`Shelf` which exposes :meth:`first`, :meth:`!next`, :meth:`previous`, :meth:`last` and :meth:`set_location` which are available in the third-party :mod:`bsddb` module from `pybsddb @@ -116,8 +119,8 @@ modules. The *dict* object passed to the constructor must support those methods. This is generally accomplished by calling one of :func:`bsddb.hashopen`, :func:`bsddb.btopen` or :func:`bsddb.rnopen`. The - optional *protocol* and *writeback* parameters have the same interpretation - as for the :class:`Shelf` class. + optional *protocol*, *writeback*, and *keyencoding* parameters have the same + interpretation as for the :class:`Shelf` class. .. class:: DbfilenameShelf(filename, flag='c', protocol=None, writeback=False) Index: Lib/shelve.py =================================================================== --- Lib/shelve.py (revision 78145) +++ Lib/shelve.py (working copy) @@ -88,7 +88,7 @@ self._protocol = protocol self.writeback = writeback self.cache = {} - self.keyencoding = "utf-8" + self.keyencoding = keyencoding def __iter__(self): for k in self.dict.keys(): Index: Lib/test/test_shelve.py =================================================================== --- Lib/test/test_shelve.py (revision 78145) +++ Lib/test/test_shelve.py (working copy) @@ -122,6 +122,19 @@ self.assertEqual(len(d1), 1) self.assertEqual(len(d2), 1) + def test_default_keyencoding_is_not_ascii(self): + d = {} + key = 'Pöp' + s = shelve.Shelf(d) + s[key] = [1] + self.assertIn(key.encode('utf-8'), d) + + def test_nondefault_keyencoding(self): + d = {} + key = 'Pöp' + s = shelve.Shelf(d, keyencoding='ascii') + self.assertRaises(UnicodeEncodeError, s.__setitem__, key, [1]) + def test_writeback_also_writes_immediately(self): # Issue 5754 d = {}