Commits

pfw committed 2a0a469

Cleaned up indexing and use of naive UTC date times

  • Participants
  • Parent commits c328538

Comments (0)

Files changed (3)

flaskext/durus.py

 from flask import _request_ctx_stack, redirect, url_for
 
 from datetime import datetime
-import pytz
-epoch = datetime(1970,1,1, tzinfo=pytz.utc)
 
 def with_getters_and_setters(klass):
     """
         if ctx is not None:
             # walk list of changed items
             db = self._get_db(ctx) 
-            for changed in db.changed.itervalues():
+            changed = db.changed.values()
+            for changed in changed:
+                # call commit if definied on item
                 print "changed:", changed
+                on_commit = getattr(changed, 'on_commit', None)
+                if on_commit:
+                    print "changed:", changed, "calling on_commit"
+                    on_commit()
+
             return db.commit()
 
     @property
         return """<html><head><title>%s</title></head><body><div>%s</div><div>%s</div></body></html>""" % (repr(value).replace('<', '&lt;').replace('>','&gt;'), repr(value).replace('<', '&lt;').replace('>','&gt;'), format(persistent_vars(value)))
 
 
+class IndexedKeyed(Keyed):
+    """
+    A keyed item that maintains indexes
+    """
+    KEY_PREFIX = 'key_for_'
+    KEY_PREFIX_LEN = len(KEY_PREFIX)
+    
+    _keep_is = spec(either(None, "IndexedKeep"), "Pointer to the keep this item is in")
+    _indexes_is = spec(PersistentDict, "Pointers to the indexes this item exists in")
+
+    def __init__(self):
+        print "in init"
+        Keyed.__init__(self)
+        self._indexes = PersistentDict()
+        self._keep = None
+    
+    def _index(self):
+        """()
+        Return index keys for this item based on key functions
+        """
+        for name in dir(self):
+            attr = getattr(self, name)
+            if name.startswith(self.KEY_PREFIX) and callable(attr):
+                for key in attr():
+                    if key:
+                        # only return a index and key if the key isn't None, ie. no valid value for that key
+                        yield name[self.KEY_PREFIX_LEN:], key
+
+    def save(self):
+        """()
+        Get all index keys and update in the keep
+        """
+        print "update indexes"
+        if self._keep:
+            # remove existing index keys
+            for name, existing_key in self._indexes.items():
+                try:
+                    del(self._keep._indexes[name][existing_key])
+                    # remove index if empty
+                    if not self._keep._indexes[name]:
+                        del(self._keep._indexes[name])
+                except KeyError:
+                    """ no index """
+                    # TODO - clean up, should check for index
+            
+            # add current values
+            for name, key in self._index():
+                if type(key) == tuple:
+                    key = list(key)
+                if type(key) != list:
+                    key = [key]
+                # add item to end of key to ensure uniqueness
+                key.append(self)
+
+                key=tuple(key)
+                print "key [%s]" % str(key)
+                self._keep._indexes.setdefault(name, BTree())[key] = None
+
+                # store pointer back into index
+                self._indexes[name] = key
+
 class IndexedKeep(Keep):
     """
     A Keep that maintains indexes for quick access to the values.
     def __init__(self, value_spec=Keyed, mapping_class=BTree, counter_class=Counter):
         Keep.__init__(self, value_spec, mapping_class, counter_class)
         self._indexes = PersistentDict()
-        self.create_indexes()
 
     def add(self, value):
         Keep.add(self, value)
-        # update indexes if defined.
-        value._indexes = PeristentDict()
+        value._keep = self
 
-    def create_indexes(self):
-        """()
-        Create all indexes bases on callables on the value_spec class that start with 'key_for'
+
+    def by(self, name):
+        """(name:str) -> BTree
+        Get an index into the keep
         """
-        for attr in self.value_spec.__dict__.keys():
-            if attr.startswith('key_for_') and callable(getattr(self.value_spec, attr)):
-                # index key
-                print attr
-                self._indexes.setdefault(attr.split('key_for_')[1], BTree())
+        return self._indexes.get(name, None)
 
-    def update_indexes(self):
-        """()
-        Rebuild all indexes defined on this Keep.
-        """
-        for name, index in self._indexes.items():
-            print "update index:", name
-            index.clear()
-            for item in self.mapping.itervalues():
-                key = getattr(item, "key_for_%s" % name)()
-                index[(key, item.key)] = item
-                if not hasattr(item, '_indexes'):
-                    item._indexes = PersistentDict()
-                item._indexes[name] = (key, item.key)
 
+    # def on_commit(self):
+    #     """
+    #     When commiting this keep, run through all changed items in it and update the indexes.
+    #     """
+    #     for item in self.mapping.itervalues():
+    #         if item._p_is_unsaved():
+    #             item.update_indexes(value)
 
+    # def create_indexes(self):
+    #     """()
+    #     Create all indexes bases on callables on the value_spec class that start with 'key_for'
+    #     """
+    #     for attr in self.value_spec.__dict__.keys():
+    #         if attr.startswith('key_for_') and callable(getattr(self.value_spec, attr)):
+    #             # index key
+    #             print attr
+    #             self._indexes.setdefault(attr.split('key_for_')[1], BTree())
 
+    # def update_indexes(self, value=None):
+    #     """(value:Persistent|None)
+    #     Update the indexes for this keep, if value is specified, only update indexes for it.
+    #     """
+    #     items = [value] if value else self.mapping.itervalues()
+    #     for name, index in self._indexes.items():
+    #         for item in items:
+    #             if not item._p_oid or item._p_is_unsaved():
+    #                 print "update index:", name, item
+                    
+    #                 # remove existing entries in index
+    #                 existing_key = item._indexes.get(name, None)
+    #                 if existing_key:
+    #                     del(index[existing_key])
+    #                     del(item._indexes[name])
 
+    #                 # add new entries to index
+    #                 key = getattr(item, "key_for_%s" % name)()
+    #                 index[(key, item.key)] = item
+    #                 item._indexes[name] = (key, item.key)
 
+
+
+
+
 from durus.persistent import PersistentObject
 from durus.persistent_dict import PersistentDict
 
-from .spec import either, datetime_with_tz, mapping, spec, integer
+from .spec import either, datetime_without_tz, mapping, spec, integer
 from .spec import require, get_spec_problems, anything, specify
 
-import pytz
 from datetime import datetime
 
 def rand_int(bits):
     Provides a timestamp.
     This is a mixin for PersistentObject classes.  
     """
-    stamp_is = datetime_with_tz
+    stamp_is = datetime_without_tz
 
     __slots__ = []
 
         return self.stamp
 
     def set_stamp(self):
-        self.stamp = datetime.now(pytz.utc)
+        self.stamp = datetime.utcnow()
 
 
 def stamp_sorted(stamped_sequence):
 from types import FunctionType, MethodType
 import sys
 
+epoch = datetime(1970,1,1)
+
 if sys.version < "3":
     from __builtin__ import unicode, long
     unicode_string = unicode