[Checkins] SVN: zc.beforestorage/trunk/ 1. Added a new option "before_from_file" that can be used to preserve the beforestorage state between restarts.

Satchidanand Haridas satchit at zope.com
Thu Dec 9 17:19:16 EST 2010


Log message for revision 118782:
  1. Added a new option "before_from_file" that can be used to preserve the beforestorage state between restarts.
  
  2. Updated test part in buildout.cfg to add zope.testing so tests could be run.
  
  

Changed:
  U   zc.beforestorage/trunk/buildout.cfg
  U   zc.beforestorage/trunk/src/zc/beforestorage/README.txt
  U   zc.beforestorage/trunk/src/zc/beforestorage/__init__.py
  U   zc.beforestorage/trunk/src/zc/beforestorage/component.xml

-=-
Modified: zc.beforestorage/trunk/buildout.cfg
===================================================================
--- zc.beforestorage/trunk/buildout.cfg	2010-12-09 22:02:53 UTC (rev 118781)
+++ zc.beforestorage/trunk/buildout.cfg	2010-12-09 22:19:16 UTC (rev 118782)
@@ -14,3 +14,4 @@
 [test]
 recipe = zc.recipe.testrunner
 eggs = zc.beforestorage
+    zope.testing

Modified: zc.beforestorage/trunk/src/zc/beforestorage/README.txt
===================================================================
--- zc.beforestorage/trunk/src/zc/beforestorage/README.txt	2010-12-09 22:02:53 UTC (rev 118781)
+++ zc.beforestorage/trunk/src/zc/beforestorage/README.txt	2010-12-09 22:19:16 UTC (rev 118782)
@@ -82,6 +82,9 @@
 Using ZConfig to configure Before storages
 ==========================================
 
+"before" option
+---------------
+
 To use before storages from ZConfig configuration files, you need to
 import zc.beforestorage and then use a before storage section.
 
@@ -164,6 +167,190 @@
     2008-01-21 18:22:43.000000
     >>> storage.close()
 
+
+"before-from-file" option
+-------------------------
+
+The "before-from-file" option can be used to preserve the changes file between
+restarts. It's value is the absolute path to a file. If the file exists, the
+"before" time will be read from that file. If the file does not exist,
+it will be created and the current UTC time will be written to it
+
+When used with a Changes file that does NOT have the "create=true"
+option set, the database will be preserved between restarts.
+
+    >>> import os.path
+    >>> import tempfile
+
+    >>> tempdir = tempfile.mkdtemp()
+    >>> before_file = os.path.join(tempdir, 'before-file')
+
+Currently the file does not exist. So it'll be created and written with the
+current time. In order to make this repeatable, we "monkeypatch" the "get_now"
+function in the module to return a fixed value:
+
+    >>> import datetime
+    >>> import zc.beforestorage
+
+    >>> def fake_get_utcnow():
+    ...     return datetime.datetime(2008, 1, 1, 15, 0)
+    >>> orig_get_utcnow = zc.beforestorage.get_utcnow
+    >>> zc.beforestorage.get_utcnow = fake_get_utcnow
+
+    >>> os.path.exists(before_file)
+    False
+
+    >>> storage = ZODB.config.storageFromString("""
+    ...
+    ... %%import zc.beforestorage
+    ...
+    ... <before>
+    ...     before-from-file %s
+    ...     <filestorage>
+    ...         path my.fs
+    ...     </filestorage>
+    ... </before>
+    ... """ % before_file)
+
+    >>> storage
+    <Before: my.fs before 2008-01-01 15:00:00.000000>
+
+    >>> storage.close()
+
+The file will now have been created:
+
+    >>> os.path.exists(before_file)
+    True
+
+    >>> f = open(before_file)
+    >>> f.read() == fake_get_utcnow().replace(microsecond=0).isoformat()
+    True
+
+If we now write a new value to the file, the storage will be started with that
+time.
+
+    >>> f = open(before_file, 'w')
+    >>> f.write('1990-01-01T11:11')
+    >>> f.close()
+
+    >>> storage = ZODB.config.storageFromString("""
+    ...
+    ... %%import zc.beforestorage
+    ...
+    ... <before>
+    ...     before-from-file %s
+    ...     <filestorage>
+    ...         path my.fs
+    ...     </filestorage>
+    ... </before>
+    ... """ % before_file)
+
+    >>> storage
+    <Before: my.fs before 1990-01-01 11:11:00.000000>
+
+    >>> storage.close()
+
+If we restart the storage, the value from the file will be used.
+
+    >>> storage = ZODB.config.storageFromString("""
+    ...
+    ... %%import zc.beforestorage
+    ...
+    ... <before>
+    ...     before-from-file %s
+    ...     <filestorage>
+    ...         path my.fs
+    ...     </filestorage>
+    ... </before>
+    ... """ % before_file)
+
+    >>> storage
+    <Before: my.fs before 1990-01-01 11:11:00.000000>
+
+    >>> storage.close()
+
+This will continue to happen until we remove the file. The "before_from_file"
+path is stored on the storage itself, so applications that use it have access
+to it.
+
+    >>> os.remove(storage.before_from_file)
+
+    >>> os.path.exists(before_file)
+    False
+
+If we restart the storage again, a new file will be created.
+
+    >>> storage = ZODB.config.storageFromString("""
+    ...
+    ... %%import zc.beforestorage
+    ...
+    ... <before>
+    ...     before-from-file %s
+    ...     <filestorage>
+    ...         path my.fs
+    ...     </filestorage>
+    ... </before>
+    ... """ % before_file)
+
+    >>> storage
+    <Before: my.fs before 2008-01-01 15:00:00.000000>
+
+    >>> storage.close()
+
+Note that unlike the "before" option, the "before-from-file" file cannot
+contain special values such as "now" or "startup".
+
+    >>> f = open(before_file, 'w')
+    >>> f.write('now')
+    >>> f.close()
+
+    >>> storage = ZODB.config.storageFromString("""
+    ...
+    ... %%import zc.beforestorage
+    ...
+    ... <before>
+    ...     before-from-file %s
+    ...     <filestorage>
+    ...         path my.fs
+    ...     </filestorage>
+    ... </before>
+    ... """ % before_file)
+
+    >>> storage
+    Traceback (most recent call last):
+      ...
+    ValueError: 8-character string expected
+
+    >>> storage.close()
+
+Note that only one of "before" or "before-from-file" options can be specified,
+not both:
+
+    >>> storage = ZODB.config.storageFromString("""
+    ...
+    ... %%import zc.beforestorage
+    ...
+    ... <before>
+    ...     before 2008-01-01
+    ...     before-from-file %s
+    ...     <filestorage>
+    ...         path my.fs
+    ...     </filestorage>
+    ... </before>
+    ... """ % before_file)
+    Traceback (most recent call last):
+      ...
+    ValueError: Only one of "before" or "before-from-file" options can be specified, not both
+
+
+Cleanup...
+
+    >>> import shutil
+    >>> shutil.rmtree(tempdir)
+
+    >>> zc.beforestorage.get_utcnow = orig_get_utcnow
+
+
 Demonstration (doctest)
 =======================
 

Modified: zc.beforestorage/trunk/src/zc/beforestorage/__init__.py
===================================================================
--- zc.beforestorage/trunk/src/zc/beforestorage/__init__.py	2010-12-09 22:02:53 UTC (rev 118781)
+++ zc.beforestorage/trunk/src/zc/beforestorage/__init__.py	2010-12-09 22:19:16 UTC (rev 118782)
@@ -12,6 +12,8 @@
 #
 ##############################################################################
 
+import datetime
+import os.path
 import time
 
 import ZODB.POSException
@@ -26,6 +28,9 @@
     before = repr(ZODB.TimeStamp.TimeStamp(*(g[:5] + (g[5]+(t%1), ))))
     return before
 
+def get_utcnow():
+    return datetime.datetime.utcnow()
+
 startup_time_stamp = time_stamp()
 
 class Before:
@@ -169,10 +174,28 @@
     def open(self):
         base = self.config.base.open()
         before = self.config.before
-        if isinstance(before, basestring):
+        before_from_file = self.config.before_from_file
+        if (before and before_from_file):
+            raise ValueError(
+                'Only one of "before" or "before-from-file" options '
+                'can be specified, not both')
+        if before and isinstance(before, basestring):
             if before.lower() == 'now':
                 self.config.before = None
             elif before.lower() == 'startup':
                 self.config.before = startup_time_stamp
-        return Before(base, self.config.before)
+        elif before_from_file:
+            if os.path.exists(before_from_file):
+                f = open(before_from_file)
+                self.config.before = f.read()
+            else:
+                f = open(before_from_file, 'w')
+                self.config.before = get_utcnow().replace(microsecond=0).isoformat()
+                f.write(self.config.before)
+            f.close()
+        before_storage = Before(base, self.config.before)
+        before_storage.before_from_file = self.config.before_from_file
+        return before_storage
 
+
+

Modified: zc.beforestorage/trunk/src/zc/beforestorage/component.xml
===================================================================
--- zc.beforestorage/trunk/src/zc/beforestorage/component.xml	2010-12-09 22:02:53 UTC (rev 118781)
+++ zc.beforestorage/trunk/src/zc/beforestorage/component.xml	2010-12-09 22:19:16 UTC (rev 118782)
@@ -21,6 +21,15 @@
         opening of the beforestorage.
       </description>
     </key>
+    <key name="before-from-file" datatype="string" required="no">
+      <description>
+        An absolute path to a file used to track the 'before' time. If the file
+        exists it should contain the before time to use. Note that unlike the
+        'before' option, 'now' and 'startup' cannot be used here.
+        If the file does not exist, it'll be created and written with the
+        current time.
+      </description>
+    </key>
   </sectiontype>
 
 </component>



More information about the checkins mailing list