Back to index

plone3  3.1.7
Public Member Functions | Static Public Attributes | Private Member Functions | Static Private Attributes
Archetypes.athistoryaware.ATHistoryAwareMixin Class Reference

List of all members.

Public Member Functions

def getHistories

Static Public Attributes

tuple security = ClassSecurityInfo()

Private Member Functions

def _constructAnnotatedHistory

Static Private Attributes

tuple __implements__ = (IATHistoryAware,)

Detailed Description

Archetypes history aware mixin class

Provide ZODB revisions, constructed from older transactions. Note that 
these transactions are available only up to the last pack.

Definition at line 110 of file athistoryaware.py.


Member Function Documentation

Reconstruct historical revisions of archetypes objects

Merges revisions to self with revisions to archetypes-related items
in __annotations__. Yields at most max recent revisions.

Definition at line 124 of file athistoryaware.py.

00124 
00125     def _constructAnnotatedHistory(self, max=10):
00126         """Reconstruct historical revisions of archetypes objects
00127         
00128         Merges revisions to self with revisions to archetypes-related items
00129         in __annotations__. Yields at most max recent revisions.
00130         
00131         """
00132         # All relevant historical states by transaction id
00133         # For every tid, keep a dict with object revisions, keyed on annotation
00134         # id, or None for self and '__annotations__' for the ann OOBTree
00135         # Initialize with self revisions
00136         history = dict([(tid, {None: rev})
00137                         for (tid, rev) in _objectRevisions(self, max)])
00138             
00139         if not getattr(self, '__annotations__', None):
00140             # No annotations, just return the history we have for self
00141             # Note that if this object had __annotations__ in a past 
00142             # transaction they will be ignored! Working around this is a
00143             # YAGNI I think though.
00144             for tid in sorted(history.keys()):
00145                 yield history[tid][None]
00146             return
00147             
00148         # Now find all __annotation__ revisions, and the annotation keys
00149         # used in those.
00150         annotation_key_objects = {}
00151         isatkey = lambda k, aak=AT_ANN_KEYS: filter(k.startswith, aak)
00152         # Loop over max revisions of the __annotations__ object to retrieve
00153         # all keys (and more importantly, their objects so we can get revisions)
00154         for tid, rev in _objectRevisions(self.__annotations__, max):
00155             history.setdefault(tid, {})['__annotations__'] = rev
00156             revision = rev['object']
00157             for key in itertools.ifilter(isatkey, revision.iterkeys()):
00158                 if not hasattr(revision[key], '_p_jar'):
00159                     continue # Not persistent
00160                 if key not in annotation_key_objects:
00161                     annotation_key_objects[key] = revision[key]
00162                     
00163         # For all annotation keys, get their revisions
00164         for key, obj in annotation_key_objects.iteritems():
00165             for tid, rev in _objectRevisions(obj, max):
00166                 history.setdefault(tid, {})[key] = rev
00167         del annotation_key_objects
00168                 
00169         # Now we merge the annotation and object revisions into one for each
00170         # transaction id, and yield the results
00171         tids = sorted(history.iterkeys(), reverse=True)
00172         def find_revision(tids, key):
00173             """First revision of key in a series of tids"""
00174             has_revision = lambda t, h=history, k=key: k in h[t]
00175             next_tid = itertools.ifilter(has_revision, tids).next()
00176             return history[next_tid][key]
00177         
00178         for i, tid in enumerate(tids[:max]):
00179             revision = find_revision(tids[i:], None)
00180             obj = revision['object']
00181             # Track size to maintain correct metadata
00182             size = revision['size']
00183             
00184             anns_rev = find_revision(tids[i:], '__annotations__')
00185             size += anns_rev['size']
00186             anns = anns_rev['object']
00187             
00188             # We use a temporary OOBTree to avoid _p_jar complaints from the
00189             # transaction machinery
00190             tempbtree = OOBTree()
00191             tempbtree.__setstate__(anns.__getstate__())
00192             
00193             # Find annotation revisions and insert
00194             for key in itertools.ifilter(isatkey, tempbtree.iterkeys()):
00195                 if not hasattr(tempbtree[key], '_p_jar'):
00196                     continue # Not persistent
00197                 value_rev = find_revision(tids[i:], key)
00198                 size += value_rev['size']
00199                 tempbtree[key] = value_rev['object']
00200                 
00201             # Now transfer the tembtree state over to anns, effectively 
00202             # bypassing the transaction registry while maintaining BTree 
00203             # integrity
00204             anns.__setstate__(tempbtree.__getstate__())
00205             anns._p_changed = 0
00206             del tempbtree
00207             
00208             # Do a similar hack to set anns on the main object
00209             state = obj.__getstate__()
00210             state['__annotations__'] = anns
00211             obj.__setstate__(state)
00212             obj._p_changed = 0
00213             
00214             # Update revision metadata if needed
00215             if revision['tid'] != tid:
00216                 # any other revision will do; only size and object are unique
00217                 revision = history[tid].values()[0].copy()
00218                 revision['object'] = obj
00219                 
00220             # Correct size based on merged records
00221             revision['size'] = size
00222             
00223             # clean up as we go
00224             del history[tid]
00225             
00226             yield revision

Here is the call graph for this function:

Here is the caller graph for this function:

Iterate over historic revisions.

Yields (object, time, transaction_note, user) tuples, where object
is an object revision approximating what was committed at that time,
with the current acquisition context.

Object revisions include correct archetype-related annotation revisions 
(in __annotations__); other persistent sub-objects are in their current 
revision, not historical!

Definition at line 228 of file athistoryaware.py.

00228 
00229     def getHistories(self, max=10):
00230         """Iterate over historic revisions.
00231         
00232         Yields (object, time, transaction_note, user) tuples, where object
00233         is an object revision approximating what was committed at that time,
00234         with the current acquisition context.
00235 
00236         Object revisions include correct archetype-related annotation revisions 
00237         (in __annotations__); other persistent sub-objects are in their current 
00238         revision, not historical!
00239         
00240         """
00241         
00242         parent = aq_parent(self)
00243         for revision in self._constructAnnotatedHistory(max):
00244             obj = revision['object'].__of__(parent)
00245             yield (obj, DateTime(revision['time']), revision['description'], 
00246                    revision['user_name'])
00247 
00248 InitializeClass(ATHistoryAwareMixin)

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

tuple Archetypes.athistoryaware.ATHistoryAwareMixin.__implements__ = (IATHistoryAware,) [static, private]

Definition at line 118 of file athistoryaware.py.

tuple Archetypes.athistoryaware.ATHistoryAwareMixin.security = ClassSecurityInfo() [static]

Definition at line 120 of file athistoryaware.py.


The documentation for this class was generated from the following file: