-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Ross Patterson wrote:
> I got tired of reindexing large indexes that were cleared
> unintelligently by the index import adapters so I wrote the following
> exportimport.pluginindexes and overrides.zcml. I'm posting them here
> in case anyone wants to use the code.
>
> This doesn't handle reindexing indexes when it's needed but it does
> keep the adapters from needlessly clearing the indexes.
Thanks! I've reworked your changes as a patch against the GenericSetup
trunk, including tests of both cases (clear / don't clear). (Patch
attached).
Can anybody offer a reason not to merge this the the trunk? What about
released branches?
Tres.
- --
===================================================================
Tres Seaver +1 540-429-0999 [EMAIL PROTECTED]
Palladion Software "Excellence by Design" http://palladion.com
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.2 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iD8DBQFFdtNc+gerLs4ltQ4RAuG6AJ9bsZvahlbKvwISPfAWgroT4k9NCACgyfZm
ypF8qXGohdAxq51YoUw1hHs=
=QQy6
-----END PGP SIGNATURE-----
Index: PluginIndexes/tests/test_exportimport.py
===================================================================
--- PluginIndexes/tests/test_exportimport.py (revision 71431)
+++ PluginIndexes/tests/test_exportimport.py (working copy)
@@ -18,6 +18,9 @@
import unittest
import Testing
+from xml.dom.minidom import parseString
+
+from Products.GenericSetup.testing import DummySetupEnviron
from Products.GenericSetup.testing import NodeAdapterTestCase
from Products.GenericSetup.testing import ExportImportZCMLLayer
@@ -67,7 +70,63 @@
</index>
"""
+class DummyIndex:
+ _cleared = False
+ def __init__(self, **kw):
+ self.__dict__.update(kw)
+ def clear(self):
+ self._cleared = True
+
+class DummyIndexWithProperties(DummyIndex):
+
+ def __init__(self, props, **kw):
+ DummyIndex.__init__(self, **kw)
+ map = self._map = []
+ pdict = self._pdict = {}
+ for prop in props:
+ info = {'id': prop[0], 'type': prop[1], 'mode': prop[2]}
+ map.append(info)
+ pdict[prop[0]] = info
+
+ def _propertyMap(self):
+ return self._map
+
+ def getProperty(self, name):
+ return getattr(self, name)
+
+ def _updateProperty(self, name, value):
+ setattr(self, name, value)
+
+ def propdict(self):
+ return self._pdict
+
+class DummyDateRangeIndex(DummyIndex):
+
+ def __init__(self, since_field, until_field):
+ self._edit(since_field, until_field)
+
+ def _edit(self, since_field, until_field):
+ self.since_field = since_field
+ self.until_field = until_field
+
+ def getSinceField(self):
+ return self.since_field
+
+ def getUntilField(self):
+ return self.until_field
+
+class DummyFilteredSet(DummyIndex):
+
+ def __init__(self, expr):
+ self.expr = expr
+
+ def getExpression(self):
+ return self.expr
+
+ def setExpression(self, value):
+ self.expr = value
+
class DateIndexNodeAdapterTests(NodeAdapterTestCase):
layer = ExportImportZCMLLayer
@@ -85,7 +144,30 @@
self._obj = DateIndex('foo_date')
self._XML = _DATE_XML
+ def test__importNode_clears_if_change(self):
+ index = DummyIndexWithProperties(
+ [('index_naive_time_as_local', 'boolean', 'w')],
+ index_naive_time_as_local=False,
+ )
+ environ = DummySetupEnviron()
+ adapter = self._getTargetClass()(index, environ)
+ document = parseString(self._XML)
+ adapter._importNode(document.firstChild)
+ self.failUnless(index._cleared)
+ def test__importNode_doesnt_clear_if_no_change(self):
+ index = DummyIndexWithProperties(
+ [('index_naive_time_as_local', 'boolean', 'w')],
+ index_naive_time_as_local=True,
+ )
+ environ = DummySetupEnviron()
+ environ._should_purge = False
+ adapter = self._getTargetClass()(index, environ)
+ document = parseString(self._XML)
+ adapter._importNode(document.firstChild)
+ self.failIf(index._cleared)
+
+
class DateRangeIndexNodeAdapterTests(NodeAdapterTestCase):
layer = ExportImportZCMLLayer
@@ -107,7 +189,24 @@
self._obj = DateRangeIndex('foo_daterange')
self._XML = _DATERANGE_XML
+ def test__importNode_clears_if_change(self):
+ index = DummyDateRangeIndex('qux', 'spam')
+ environ = DummySetupEnviron()
+ adapter = self._getTargetClass()(index, environ)
+ document = parseString(self._XML)
+ adapter._importNode(document.firstChild)
+ self.failUnless(index._cleared)
+ def test__importNode_doesnt_clear_if_no_change(self):
+ index = DummyDateRangeIndex('bar', 'baz')
+ environ = DummySetupEnviron()
+ environ._should_purge = False
+ adapter = self._getTargetClass()(index, environ)
+ document = parseString(self._XML)
+ adapter._importNode(document.firstChild)
+ self.failIf(index._cleared)
+
+
class FieldIndexNodeAdapterTests(NodeAdapterTestCase):
layer = ExportImportZCMLLayer
@@ -128,7 +227,23 @@
self._obj = FieldIndex('foo_field')
self._XML = _FIELD_XML
+ def test__importNode_clears_if_change(self):
+ index = DummyIndex(indexed_attrs=['foo'])
+ environ = DummySetupEnviron()
+ adapter = self._getTargetClass()(index, environ)
+ document = parseString(self._XML)
+ adapter._importNode(document.firstChild)
+ self.failUnless(index._cleared)
+ def test__importNode_doesnt_clear_if_no_change(self):
+ index = DummyIndex(indexed_attrs=['bar'])
+ environ = DummySetupEnviron()
+ environ._should_purge = False
+ adapter = self._getTargetClass()(index, environ)
+ document = parseString(self._XML)
+ adapter._importNode(document.firstChild)
+ self.failIf(index._cleared)
+
class KeywordIndexNodeAdapterTests(NodeAdapterTestCase):
layer = ExportImportZCMLLayer
@@ -150,7 +265,24 @@
self._obj = KeywordIndex('foo_keyword')
self._XML = _KEYWORD_XML
+ def test__importNode_clears_if_change(self):
+ index = DummyIndex(indexed_attrs=['foo'])
+ environ = DummySetupEnviron()
+ adapter = self._getTargetClass()(index, environ)
+ document = parseString(self._XML)
+ adapter._importNode(document.firstChild)
+ self.failUnless(index._cleared)
+ def test__importNode_doesnt_clear_if_no_change(self):
+ index = DummyIndex(indexed_attrs=['bar'])
+ environ = DummySetupEnviron()
+ environ._should_purge = False
+ adapter = self._getTargetClass()(index, environ)
+ document = parseString(self._XML)
+ adapter._importNode(document.firstChild)
+ self.failIf(index._cleared)
+
+
class PathIndexNodeAdapterTests(NodeAdapterTestCase):
layer = ExportImportZCMLLayer
@@ -232,7 +364,24 @@
self._obj = PythonFilteredSet('bar', '')
self._XML = _SET_XML
+ def test__importNode_clears_if_change(self):
+ fste = DummyFilteredSet('o.getId() == "foo"')
+ environ = DummySetupEnviron()
+ adapter = self._getTargetClass()(fste, environ)
+ document = parseString(self._XML)
+ adapter._importNode(document.firstChild)
+ self.failUnless(fste._cleared)
+ def test__importNode_doesnt_clear_if_no_change(self):
+ fste = DummyFilteredSet('True')
+ environ = DummySetupEnviron()
+ environ._should_purge = False
+ adapter = self._getTargetClass()(fste, environ)
+ document = parseString(self._XML)
+ adapter._importNode(document.firstChild)
+ self.failIf(fste._cleared)
+
+
class TopicIndexNodeAdapterTests(NodeAdapterTestCase):
layer = ExportImportZCMLLayer
Index: PluginIndexes/exportimport.py
===================================================================
--- PluginIndexes/exportimport.py (revision 71431)
+++ PluginIndexes/exportimport.py (working copy)
@@ -58,8 +58,9 @@
if child.nodeName == 'indexed_attr':
indexed_attrs.append(
child.getAttribute('value').encode('utf-8'))
- self.context.indexed_attrs = indexed_attrs
- self.context.clear()
+ if getattr(self.context, 'indexed_attrs', None) != indexed_attrs:
+ self.context.indexed_attrs = indexed_attrs
+ self.context.clear()
node = property(_exportNode, _importNode)
@@ -84,9 +85,27 @@
if self.environ.shouldPurge():
self._purgeProperties()
- self._initProperties(node)
- self.context.clear()
+ should_clear = False
+ for p_element in node.getElementsByTagName('property'):
+ p_name = p_element.attributes['name'].value
+ p_map = self.context.propdict().get(p_name, None)
+ if p_map is None:
+ should_clear = True
+ break
+
+ p_value = p_element.childNodes[0].data
+ if p_map.get('type') == 'boolean':
+ p_value = self._convertToBoolean(p_value)
+
+ if self.context.getProperty(p_name) != p_value:
+ should_clear = True
+ break
+
+ if should_clear:
+ self._initProperties(node)
+ self.context.clear()
+
node = property(_exportNode, _importNode)
@@ -108,9 +127,12 @@
def _importNode(self, node):
"""Import the object from the DOM node.
"""
- self.context._edit(node.getAttribute('since_field').encode('utf-8'),
- node.getAttribute('until_field').encode('utf-8'))
- self.context.clear()
+ since_field = node.getAttribute('since_field').encode('utf-8')
+ until_field = node.getAttribute('until_field').encode('utf-8')
+ if (self.context.getSinceField() != since_field or
+ self.context.getUntilField() != until_field):
+ self.context._edit(since_field, until_field)
+ self.context.clear()
node = property(_exportNode, _importNode)
@@ -181,9 +203,10 @@
def _importNode(self, node):
"""Import the object from the DOM node.
"""
- self.context.setExpression(
- node.getAttribute('expression').encode('utf-8'))
- self.context.clear()
+ new_expr = node.getAttribute('expression').encode('utf-8')
+ if new_expr != self.context.getExpression():
+ self.context.setExpression(new_expr)
+ self.context.clear()
node = property(_exportNode, _importNode)
_______________________________________________
Zope-CMF maillist - [email protected]
http://mail.zope.org/mailman/listinfo/zope-cmf
See http://collector.zope.org/CMF for bug reports and feature requests