Metadata-Version: 1.0
Name: dm.historical
Version: 1.0
Summary: Historical state of objects stored in the ZODB
Home-page: UNKNOWN
Author: Dieter Maurer
Author-email: dieter@handshake.de
License: BSD (see "dm/historical/LICENSE.txt", for details)
Description: dm.historical
        =============
        
        Utilities to access the historical state of objects stored in
        a (history aware) ZODB (Zope Object DataBase).
        They can be useful to find out what happened to objects in the past
        and to restore accidentally deleted or modified objects.
        
        I have used them recently to analyse a case where colleagues reported
        about mysteriously lost objects. It turned out that the objects
        have not been lost at all but only became unindexed.
        
        This version is tested against ZODB 3.4. It will not work
        with ZODB 3.2. It may (or may not) work with more recent ZODB versions.
        Beside ZODB, this version requires Zope's ``DateTime`` package.
        
        
        API
        ---
        
        Currently, there are two utilities:
        ``getHistory(obj, first=0, last=20)`` and
        ``getObjectAt(obj, time)``.
        
        *time* can be a Zope ``DateTime`` instance, a float in seconds since epoch
        or a serial/transaction id.
        
        
        Usage example
        -------------
        
        In the example below, the ZODB contains a folder ``f``. Let's have a look
        at its history.
        
        >>> from dm.historical import getHistory, getObjectAt
        >>> from pprint import pprint as pp
        >>> h = getHistory(f)
        >>> pp(h)
        [{'description': '',
        'obj': <Folder at /f>,
        'size': 157L,
        'tid': '\x03r\xc8\x1b\xf3hhU',
        'time': DateTime('2008/01/01 09:59:57.049 GMT+1'),
        'user_name': '',
        'version': ''},
        {'description': '',
        'obj': <Folder at /f>,
        'size': 124L,
        'tid': '\x03r\xc8\x1bX\x0e\xfb\xcc',
        'time': DateTime('2008/01/01 09:59:20.639 GMT+1'),
        'user_name': '',
        'version': ''},
        {'description': '',
        'obj': <Folder at /f>,
        'size': 48L,
        'tid': '\x03r\xc8\x15\x1c\x9f\xb03',
        'time': DateTime('2008/01/01 09:53:06.709 GMT+1'),
        'user_name': '',
        'version': ''}]
        
        This tells us that the ZODB knows about 3 transactions affecting
        ``f``. We can access its state after the first transaction.
        
        >>> f1 = h[-1]['obj']
        >>> f1.objectIds()
        []
        
        ``f`` was empty at that time. Let's see how ``f`` was changed by the
        other transactions:
        
        >>> for hr in h:
        ...   print hr['time'].strftime('%H:%M:%S'), hr['obj'].objectIds()
        ...
        09:59:57 ['x', 'y']
        09:59:20 ['x']
        09:53:06 []
        
        This tells us that the second transaction added ``x`` and the third
        transaction ``y``.
        
        We can control which history records are retrieved with the
        optional parameters *first* and *last*.
        
        >>> pp(getHistory(f,last=1))
        [{'description': '',
        'obj': <Folder at /f>,
        'size': 157L,
        'tid': '\x03r\xc8\x1b\xf3hhU',
        'time': DateTime('2008/01/01 09:59:57.049 GMT+1'),
        'user_name': '',
        'version': ''}]
        >>> pp(getHistory(f,first=2))
        [{'description': '',
        'obj': <Folder at /f>,
        'size': 48L,
        'tid': '\x03r\xc8\x15\x1c\x9f\xb03',
        'time': DateTime('2008/01/01 09:53:06.709 GMT+1'),
        'user_name': '',
        'version': ''}]
        
        ``getObjectAt`` can be used to retrieve the historical state
        at a given time. Say, we want to learn how ``f`` was at 9:55.
        The most easy way to specify a time is via a ``DateTime``.
        
        >>> from DateTime import DateTime
        >>> dt=DateTime(2008,1,1,9,55)
        >>> dt
        DateTime('2008/01/01 09:55:00 GMT+1')
        >>> getObjectAt(f, dt).objectIds()
        []
        
        When we request the state beyond the ZODB's maintained history,
        we get a ``POSKeyError``.
        
        >>> getObjectAt(f, DateTime(2008,1,1,9,50))
        Traceback (most recent call last):
        ...
        ZODB.POSException.POSKeyError: ('\x00\x00\x00\x00\x00j\x82\xd3', '\x03r\xc8\x12\x00\x00\x00\x00')
        
        The time can also be specified via a float in the unit seconds since epoch
        or via a serial/tid. However, these will be used rarely.
        
        >>> ts=dt.timeTime()
        >>> ts
        1199177700.0
        >>> getObjectAt(f, ts).objectIds()
        []
        >>> getObjectAt(f, '\x03r\xc8\x15\x1c\x9f\xb03').objectIds()
        []
Keywords: historical state ZODB analysis recovery
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Framework :: ZODB
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Topic :: Database
Classifier: Topic :: Utilities
