[Checkins] SVN: relstorage/trunk/ Added tests of the zodbconvert utility and removed the verbose option
Shane Hathaway
shane at hathawaymix.org
Fri Oct 30 03:20:28 EDT 2009
Log message for revision 105379:
Added tests of the zodbconvert utility and removed the verbose option
since it was violating an API.
Changed:
U relstorage/trunk/README.txt
A relstorage/trunk/relstorage/tests/test_zodbconvert.py
U relstorage/trunk/relstorage/zodbconvert.py
-=-
Modified: relstorage/trunk/README.txt
===================================================================
--- relstorage/trunk/README.txt 2009-10-29 21:16:07 UTC (rev 105378)
+++ relstorage/trunk/README.txt 2009-10-30 07:20:27 UTC (rev 105379)
@@ -141,7 +141,7 @@
END relstorage_util;
/
-Here are some sample SQL statements for creating the user::
+Here are some sample SQL statements for creating the database user::
CREATE USER zodb IDENTIFIED BY mypassword;
GRANT CONNECT, RESOURCE, CREATE TABLE, CREATE SEQUENCE TO zodb;
@@ -317,16 +317,13 @@
``--clear``
Clears all data from the destination storage before copying. Use
this only if you are certain the destination has no useful data.
+ Currently only works when the destination is a RelStorage instance.
``--dry-run``
Opens both storages and analyzes what would be copied, but does not
actually copy.
- ``--verbose``
- List the transactions and objects as they are copied. This is very
- verbose.
-
Migrating to a new version of RelStorage
----------------------------------------
Added: relstorage/trunk/relstorage/tests/test_zodbconvert.py
===================================================================
--- relstorage/trunk/relstorage/tests/test_zodbconvert.py (rev 0)
+++ relstorage/trunk/relstorage/tests/test_zodbconvert.py 2009-10-30 07:20:27 UTC (rev 105379)
@@ -0,0 +1,130 @@
+##############################################################################
+#
+# Copyright (c) 2009 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+import unittest
+
+class ZODBConvertTests(unittest.TestCase):
+
+ def setUp(self):
+ import os
+ import tempfile
+
+ fd, self.srcfile = tempfile.mkstemp()
+ os.close(fd)
+ os.remove(self.srcfile)
+
+ fd, self.destfile = tempfile.mkstemp()
+ os.close(fd)
+ os.remove(self.destfile)
+
+ cfg = """
+ <filestorage source>
+ path %s
+ </filestorage>
+ <filestorage destination>
+ path %s
+ </filestorage>
+ """ % (self.srcfile, self.destfile)
+
+ fd, self.cfgfile = tempfile.mkstemp()
+ os.write(fd, cfg)
+ os.close(fd)
+
+ def tearDown(self):
+ import os
+ if os.path.exists(self.destfile):
+ os.remove(self.destfile)
+ if os.path.exists(self.srcfile):
+ os.remove(self.srcfile)
+
+ def test_storage_has_data(self):
+ from ZODB.DB import DB
+ from relstorage.zodbconvert import storage_has_data
+ from ZODB.FileStorage import FileStorage
+ src = FileStorage(self.srcfile, create=True)
+ self.assertFalse(storage_has_data(src))
+ db = DB(src) # add the root object
+ db.close()
+ self.assertTrue(storage_has_data(src))
+
+ def test_convert(self):
+ from ZODB.DB import DB
+ from ZODB.FileStorage import FileStorage
+ from relstorage.zodbconvert import main
+ from relstorage.zodbconvert import storage_has_data
+ import transaction
+
+ src = FileStorage(self.srcfile)
+ db = DB(src)
+ conn = db.open()
+ conn.root()['x'] = 10
+ transaction.commit()
+ conn.close()
+ db.close()
+
+ main(['', self.cfgfile], write=lambda x: None)
+
+ dest = FileStorage(self.destfile)
+ db2 = DB(dest)
+ conn2 = db2.open()
+ self.assertEqual(conn2.root().get('x'), 10)
+ conn2.close()
+ db2.close()
+
+ def test_dry_run(self):
+ from ZODB.DB import DB
+ from ZODB.FileStorage import FileStorage
+ from relstorage.zodbconvert import main
+ from relstorage.zodbconvert import storage_has_data
+ import transaction
+
+ src = FileStorage(self.srcfile)
+ db = DB(src)
+ conn = db.open()
+ conn.root()['x'] = 10
+ transaction.commit()
+ conn.close()
+ db.close()
+
+ main(['', '--dry-run', self.cfgfile], write=lambda x: None)
+
+ dest = FileStorage(self.destfile)
+ db2 = DB(dest)
+ conn2 = db2.open()
+ self.assertEqual(conn2.root().get('x'), None)
+ conn2.close()
+ db2.close()
+
+ def test_no_overwrite(self):
+ from ZODB.DB import DB
+ from ZODB.FileStorage import FileStorage
+ from relstorage.zodbconvert import main
+ from relstorage.zodbconvert import storage_has_data
+ import transaction
+
+ src = FileStorage(self.srcfile)
+ db = DB(src) # create the root object
+ db.close()
+
+ dest = FileStorage(self.destfile)
+ db = DB(dest) # create the root object
+ db.close()
+
+ self.assertRaises(SystemExit, main, ['', self.cfgfile],
+ write=lambda x: None)
+
+def test_suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(ZODBConvertTests))
+ return suite
Modified: relstorage/trunk/relstorage/zodbconvert.py
===================================================================
--- relstorage/trunk/relstorage/zodbconvert.py 2009-10-29 21:16:07 UTC (rev 105378)
+++ relstorage/trunk/relstorage/zodbconvert.py 2009-10-30 07:20:27 UTC (rev 105379)
@@ -14,10 +14,9 @@
##############################################################################
"""ZODB storage conversion utility.
-See http://wiki.zope.org/ZODB/ZODBConvert for details.
+See README.txt for details.
"""
-import logging
import optparse
from persistent.TimeStamp import TimeStamp
from StringIO import StringIO
@@ -40,15 +39,18 @@
def storage_has_data(storage):
i = storage.iterator()
try:
- i[0]
- except IndexError:
+ if hasattr(i, 'next'):
+ # New iterator API
+ i.next()
+ else:
+ # Old index lookup API
+ i[0]
+ except (IndexError, StopIteration):
return False
return True
-def main():
- logging.basicConfig()
-
+def main(argv=sys.argv, write=sys.stdout.write):
parser = optparse.OptionParser(description=__doc__,
usage="%prog [options] config_file")
parser.add_option(
@@ -57,11 +59,8 @@
parser.add_option(
"--clear", dest="clear", action="store_true",
help="Clear the contents of the destination storage before copying")
- parser.add_option(
- "-v", "--verbose", dest="verbose", action="store_true",
- help="Show verbose information while copying")
- parser.set_defaults(dry_run=False, clear=False, verbose=False)
- options, args = parser.parse_args()
+ parser.set_defaults(dry_run=False, clear=False)
+ options, args = parser.parse_args(argv[1:])
if len(args) != 1:
parser.error("The name of one configuration file is required.")
@@ -71,42 +70,39 @@
source = config.source.open()
destination = config.destination.open()
- print "Storages opened successfully."
+ write("Storages opened successfully.\n")
if options.dry_run:
- print "Dry run mode: not changing the destination."
+ write("Dry run mode: not changing the destination.\n")
if storage_has_data(destination):
- print "Warning: the destination storage has data"
+ write("Warning: the destination storage has data\n")
count = 0
for txn in source.iterator():
- print '%s user=%s description=%s' % (
- TimeStamp(txn.tid), txn.user, txn.description)
- for rec in txn:
- print ' oid=%s length=%d' % (oid_repr(rec.oid), len(rec.data))
+ write('%s user=%s description=%s\n' % (
+ TimeStamp(txn.tid), txn.user, txn.description))
count += 1
- print "Would copy %d transactions." % count
- sys.exit(0)
+ write("Would copy %d transactions.\n" % count)
- if options.clear:
- if hasattr(destination, 'zap_all'):
- destination.zap_all()
- else:
- msg = ("Error: no API is known for clearing this type of storage."
- " Use another method.")
+ else:
+ if options.clear:
+ if hasattr(destination, 'zap_all'):
+ destination.zap_all()
+ else:
+ msg = ("Error: no API is known for clearing this type "
+ "of storage. Use another method.")
+ sys.exit(msg)
+
+ if storage_has_data(destination):
+ msg = "Error: the destination storage has data. Try --clear."
sys.exit(msg)
- if storage_has_data(destination):
- msg = "Error: the destination storage has data. Try --clear."
- sys.exit(msg)
+ destination.copyTransactionsFrom(source)
- destination.copyTransactionsFrom(source, verbose=options.verbose)
+ source.close()
+ destination.close()
- source.close()
- destination.close()
+ write('All transactions copied successfully.\n')
- print 'All transactions copied successfully.'
-
if __name__ == '__main__':
main()
-
More information about the checkins
mailing list