uml.png

Maybe I should explain this :)

The central part is having ItemCollection, Item and Revision. ItemCollection is the thing that holds it together and creates new items that in turn create new revisions.

ACL checking is implemented as a decorator/proxy pattern as you can see from the diagram (ACLCheckingCollection is an ItemCollection but also uses one) and raises the appropriate exceptions if ACL checks fail or proxies requests through to the actual item. It's possible that there needs to be an ACLRevision as well although I think ACL checks can deny new_revision() already.

As another example I included a BackendCollection along with appropriate classes to show how this design can fully incorporate the StorageBackend idea too.

Item instances probably need a save() method as well to save metadata... the collection doesn't because all you do at that level is add or remove items which is done with the item itself.

   1 """
   2 Here's what I'd do with storage refactoring instead of having all the Backend stuff.
   3 
   4 All classes defined here are abstract and need to be implemented by a storage
   5 manager ("backend"). In order to do underlay etc., you have StackedItemCollection...
   6 
   7 Configuration is done with
   8 
   9   cfg.storage = FileItemCollection("/some/path")
  10 
  11 or
  12 
  13   cfg.storage = StackedItemCollection(FileItemCollection(), FileItemCollection(underlay=True))
  14 
  15 or similar with arguments for paths or whatever
  16 """
  17 
  18 class ItemCollection(DictMixin):
  19     def __init__(self):
  20         """Initialise the item collection."""
  21         raise NotImplementedError()
  22 
  23     # all the dict stuff like __contains__, __getitem__, __setitem__,
  24     # __delitem__
  25 
  26     # __delitem__ could be implemented by the generic code as
  27     def __delitem__(self, name):
  28         item = self[name]
  29         item.delete()
  30 
  31     # __setitem__ should probably not be implemented at all,
  32     # one needs to do __getitem__/new_item and then .save
  33 
  34     def keys(self, filter=None):
  35         """return all items this collection contains"""
  36         raise NotImplementedError()
  37 
  38     def new_item(self, name):
  39         """create a new item, returns an instance of a class derived from Item"""
  40         raise NotImplementedError()
  41 
  42 
  43 class Item:
  44     # similar to the one on StorageRefactoring/SOC2007
  45     ...
  46 
  47 
  48 class StackedItemCollection(ItemCollection):
  49     def __init__(self, *args):
  50         ItemCollection.__init__(self)
  51         self._stack = args
  52     def new_item(self, name):
  53         # new items are always in the first collection
  54         return self._stack[0].new_item(name)
  55     def __getitem__(self, name):
  56         item = None
  57         for s in self._stack:
  58             if name in s:
  59                 item = s[name]
  60                 break
  61         if not item:
  62             raise KeyError()
  63         # stacked item handles the load/save from/to different collections
  64         return StackedItem(item, self._stack[0])
  65 
  66 class StackedItem(Item):
  67     """This item needs to load data from wherever it came from,
  68        but store to the real store, for underlay-type stuff"""

MoinMoin: JohannesBerg/StorageRefactoringIdeas (last edited 2007-10-29 19:17:26 by localhost)