Sometimes common functionality can be compartmentalized into logic that can be plugged in or not. For example, serializing and deserializing data as it is stored or extracted is a very common operation. Likewise, applications may need to perform routine operations as data makes its way from the top-level logic to the underlying storage.
To address this use case in an elegant way, datastore uses the notion of a shim datastore, which implements all four main datastore operations in terms of an underlying child datastore. For example, a json serializer datastore could implement get and put as:
def get(self, key):
value = self.child_datastore.get(key)
return json.loads(value)
def put(self, key, value):
value = json.dumps(value)
self.child_datastore.put(key, value)
To implement a shim datastore, derive from datastore.ShimDatastore and override any of the operations.