Repository: zarr-developers/zarr-python

Issue:
Renaming DictStore
Some discussion in PR ( https://github.com/zarr-developers/zarr/pull/350 ) raised the point that the name `DictStore` may not itself be clear. As such it may be better to rename it to something that makes its intent clear (with some backcompat support like aliasing to the old name with a deprecation warning). Namely something that expresses it is an in-memory storage like `MemStore` or `MemoryStore`.

Discussion:
jrbourbeau: I wasn't sure what the version number will be for the next release (e.g. `2.3.3` vs. `2.4.0`), so I added an "Upcoming Release" section to `release.rst`

Patch:
diff --git a/docs/api/storage.rst b/docs/api/storage.rst
index 85d85f40..a2aff3b6 100644
--- a/docs/api/storage.rst
+++ b/docs/api/storage.rst
@@ -2,7 +2,7 @@ Storage (``zarr.storage``)
 ==========================
 .. automodule:: zarr.storage
 
-.. autoclass:: DictStore
+.. autoclass:: MemoryStore
 .. autoclass:: DirectoryStore
 .. autoclass:: TempStore
 .. autoclass:: NestedDirectoryStore
diff --git a/docs/release.rst b/docs/release.rst
index e7db6edb..0e7028ec 100644
--- a/docs/release.rst
+++ b/docs/release.rst
@@ -1,6 +1,13 @@
 Release notes
 =============
 
+Upcoming Release
+----------------
+
+* Rename ``DictStore`` to ``MemoryStore``.
+  By :user:`James Bourbeau <jrbourbeau>`; :issue:`455`
+
+
 .. _release_2.3.2:
 
 2.3.2
diff --git a/docs/tutorial.rst b/docs/tutorial.rst
index e73dcb89..d2985646 100644
--- a/docs/tutorial.rst
+++ b/docs/tutorial.rst
@@ -367,7 +367,7 @@ property. E.g.::
     Name        : /
     Type        : zarr.hierarchy.Group
     Read-only   : False
-    Store type  : zarr.storage.DictStore
+    Store type  : zarr.storage.MemoryStore
     No. members : 1
     No. arrays  : 0
     No. groups  : 1
@@ -377,7 +377,7 @@ property. E.g.::
     Name        : /foo
     Type        : zarr.hierarchy.Group
     Read-only   : False
-    Store type  : zarr.storage.DictStore
+    Store type  : zarr.storage.MemoryStore
     No. members : 2
     No. arrays  : 2
     No. groups  : 0
@@ -392,7 +392,7 @@ property. E.g.::
     Order              : C
     Read-only          : False
     Compressor         : Blosc(cname='lz4', clevel=5, shuffle=SHUFFLE, blocksize=0)
-    Store type         : zarr.storage.DictStore
+    Store type         : zarr.storage.MemoryStore
     No. bytes          : 8000000 (7.6M)
     No. bytes stored   : 33240 (32.5K)
     Storage ratio      : 240.7
@@ -407,7 +407,7 @@ property. E.g.::
     Order              : C
     Read-only          : False
     Compressor         : Blosc(cname='lz4', clevel=5, shuffle=SHUFFLE, blocksize=0)
-    Store type         : zarr.storage.DictStore
+    Store type         : zarr.storage.MemoryStore
     No. bytes          : 4000000 (3.8M)
     No. bytes stored   : 23943 (23.4K)
     Storage ratio      : 167.1
@@ -1333,7 +1333,7 @@ module can be pickled, as can the built-in ``dict`` class which can also be used
 storage.
 
 Note that if an array or group is backed by an in-memory store like a ``dict`` or
-:class:`zarr.storage.DictStore`, then when it is pickled all of the store data will be
+:class:`zarr.storage.MemoryStore`, then when it is pickled all of the store data will be
 included in the pickled data. However, if an array or group is backed by a persistent
 store like a :class:`zarr.storage.DirectoryStore`, :class:`zarr.storage.ZipStore` or
 :class:`zarr.storage.DBMStore` then the store data **are not** pickled. The only thing
diff --git a/zarr/__init__.py b/zarr/__init__.py
index 16f71a73..55b5016b 100644
--- a/zarr/__init__.py
+++ b/zarr/__init__.py
@@ -6,7 +6,7 @@ from __future__ import absolute_import, print_function, division
 from zarr.core import Array
 from zarr.creation import (empty, zeros, ones, full, array, empty_like, zeros_like,
                            ones_like, full_like, open_array, open_like, create)
-from zarr.storage import (DictStore, DirectoryStore, ZipStore, TempStore,
+from zarr.storage import (DictStore, MemoryStore, DirectoryStore, ZipStore, TempStore,
                           NestedDirectoryStore, DBMStore, LMDBStore, SQLiteStore,
                           LRUStoreCache, ABSStore, RedisStore, MongoDBStore)
 from zarr.hierarchy import group, open_group, Group
diff --git a/zarr/hierarchy.py b/zarr/hierarchy.py
index bf9a7383..d0ea6000 100644
--- a/zarr/hierarchy.py
+++ b/zarr/hierarchy.py
@@ -9,7 +9,7 @@ from zarr.compat import PY2, MutableMapping
 from zarr.attrs import Attributes
 from zarr.core import Array
 from zarr.storage import (contains_array, contains_group, init_group,
-                          DictStore, group_meta_key, attrs_key, listdir, rename, rmdir)
+                          MemoryStore, group_meta_key, attrs_key, listdir, rename, rmdir)
 from zarr.creation import (array, create, empty, zeros, ones, full,
                            empty_like, zeros_like, ones_like, full_like,
                            normalize_store_arg)
@@ -996,7 +996,7 @@ class Group(MutableMapping):
 
 
 def _normalize_store_arg(store, clobber=False):
-    return normalize_store_arg(store, clobber=clobber, default=DictStore)
+    return normalize_store_arg(store, clobber=clobber, default=MemoryStore)
 
 
 def group(store=None, overwrite=False, chunk_store=None,
diff --git a/zarr/storage.py b/zarr/storage.py
index 3499167c..9e608da0 100644
--- a/zarr/storage.py
+++ b/zarr/storage.py
@@ -463,7 +463,7 @@ def _dict_store_keys(d, prefix='', cls=dict):
             yield prefix + k
 
 
-class DictStore(MutableMapping):
+class MemoryStore(MutableMapping):
     """Store class that uses a hierarchy of :class:`dict` objects, thus all data
     will be held in main memory.
 
@@ -474,7 +474,7 @@ class DictStore(MutableMapping):
         >>> import zarr
         >>> g = zarr.group()
         >>> type(g.store)
-        <class 'zarr.storage.DictStore'>
+        <class 'zarr.storage.MemoryStore'>
 
     Note that the default class when creating an array is the built-in
     :class:`dict` class, i.e.::
@@ -568,7 +568,7 @@ class DictStore(MutableMapping):
 
     def __eq__(self, other):
         return (
-            isinstance(other, DictStore) and
+            isinstance(other, MemoryStore) and
             self.root == other.root and
             self.cls == other.cls
         )
@@ -656,6 +656,16 @@ class DictStore(MutableMapping):
             self.root.clear()
 
 
+class DictStore(MemoryStore):
+
+    def __init__(self, *args, **kwargs):
+        warnings.warn("DictStore has been renamed to MemoryStore and will be "
+                      "removed in the future. Please use MemoryStore.",
+                      DeprecationWarning,
+                      stacklevel=2)
+        super(DictStore, self).__init__(*args, **kwargs)
+
+
 class DirectoryStore(MutableMapping):
     """Storage class using directories and files on a standard file system.
 


Test patch:
diff --git a/zarr/tests/test_convenience.py b/zarr/tests/test_convenience.py
index f64d27ed..d33d23ec 100644
--- a/zarr/tests/test_convenience.py
+++ b/zarr/tests/test_convenience.py
@@ -15,7 +15,7 @@ import pytest
 
 from zarr.convenience import (open, save, save_group, load, copy_store, copy,
                               consolidate_metadata, open_consolidated)
-from zarr.storage import atexit_rmtree, DictStore, getsize, ConsolidatedMetadataStore
+from zarr.storage import atexit_rmtree, MemoryStore, getsize, ConsolidatedMetadataStore
 from zarr.core import Array
 from zarr.hierarchy import Group, group
 from zarr.errors import CopyError, PermissionError
@@ -96,7 +96,7 @@ def test_lazy_loader():
 def test_consolidate_metadata():
 
     # setup initial data
-    store = DictStore()
+    store = MemoryStore()
     z = group(store)
     z.create_group('g1')
     g2 = z.create_group('g2')
diff --git a/zarr/tests/test_hierarchy.py b/zarr/tests/test_hierarchy.py
index 3d498839..30bcd484 100644
--- a/zarr/tests/test_hierarchy.py
+++ b/zarr/tests/test_hierarchy.py
@@ -20,7 +20,7 @@ except ImportError:  # pragma: no cover
     asb = None
 
 
-from zarr.storage import (DictStore, DirectoryStore, ZipStore, init_group, init_array,
+from zarr.storage import (MemoryStore, DirectoryStore, ZipStore, init_group, init_array,
                           array_meta_key, group_meta_key, atexit_rmtree,
                           NestedDirectoryStore, DBMStore, LMDBStore, SQLiteStore,
                           ABSStore, atexit_rmglob, LRUStoreCache)
@@ -852,11 +852,11 @@ class TestGroup(unittest.TestCase):
         assert isinstance(g2['foo/bar'], Array)
 
 
-class TestGroupWithDictStore(TestGroup):
+class TestGroupWithMemoryStore(TestGroup):
 
     @staticmethod
     def create_store():
-        return DictStore(), None
+        return MemoryStore(), None
 
 
 class TestGroupWithDirectoryStore(TestGroup):
diff --git a/zarr/tests/test_storage.py b/zarr/tests/test_storage.py
index 90461b9d..b21341c4 100644
--- a/zarr/tests/test_storage.py
+++ b/zarr/tests/test_storage.py
@@ -22,7 +22,7 @@ except ImportError:  # pragma: no cover
     asb = None
 
 
-from zarr.storage import (init_array, array_meta_key, attrs_key, DictStore,
+from zarr.storage import (init_array, array_meta_key, attrs_key, DictStore, MemoryStore,
                           DirectoryStore, ZipStore, init_group, group_meta_key,
                           getsize, migrate_1to2, TempStore, atexit_rmtree,
                           NestedDirectoryStore, default_compressor, DBMStore,
@@ -652,7 +652,7 @@ class TestMappingStore(StoreTests, unittest.TestCase):
 def setdel_hierarchy_checks(store):
     # these tests are for stores that are aware of hierarchy levels; this
     # behaviour is not stricly required by Zarr but these tests are included
-    # to define behaviour of DictStore and DirectoryStore classes
+    # to define behaviour of MemoryStore and DirectoryStore classes
 
     # check __setitem__ and __delitem__ blocked by leaf
 
@@ -686,10 +686,10 @@ def setdel_hierarchy_checks(store):
     assert 'r/s' not in store
 
 
-class TestDictStore(StoreTests, unittest.TestCase):
+class TestMemoryStore(StoreTests, unittest.TestCase):
 
     def create_store(self):
-        return DictStore()
+        return MemoryStore()
 
     def test_store_contains_bytes(self):
         store = self.create_store()
@@ -701,6 +701,17 @@ class TestDictStore(StoreTests, unittest.TestCase):
         setdel_hierarchy_checks(store)
 
 
+class TestDictStore(StoreTests, unittest.TestCase):
+
+    def create_store(self):
+        return DictStore()
+
+    def test_deprecated(self):
+        with pytest.warns(DeprecationWarning):
+            store = self.create_store()
+        assert isinstance(store, MemoryStore)
+
+
 class TestDirectoryStore(StoreTests, unittest.TestCase):
 
     def create_store(self):