[Zope-CVS] SVN: PluginRegistry/trunk/ Added support for exporting / importing registry via GenericSetup.

Tres Seaver tseaver at palladion.com
Fri Nov 4 16:34:10 EST 2005


Log message for revision 39896:
  Added support for exporting / importing registry via GenericSetup.
  
  

Changed:
  U   PluginRegistry/trunk/CHANGES.txt
  A   PluginRegistry/trunk/exportimport.py
  A   PluginRegistry/trunk/tests/test_exportimport.py
  A   PluginRegistry/trunk/xml/
  A   PluginRegistry/trunk/xml/pirExport.xml

-=-
Modified: PluginRegistry/trunk/CHANGES.txt
===================================================================
--- PluginRegistry/trunk/CHANGES.txt	2005-11-04 21:09:13 UTC (rev 39895)
+++ PluginRegistry/trunk/CHANGES.txt	2005-11-04 21:34:09 UTC (rev 39896)
@@ -3,6 +3,8 @@
 
   After PluginRegistry-1.0.2
 
+    - Added support for exporting / importing registry via GenericSetup.
+      
     - Saner version name
 
     - Added a new ZMI tab offering a simple overview over active/available

Added: PluginRegistry/trunk/exportimport.py
===================================================================
--- PluginRegistry/trunk/exportimport.py	2005-11-04 21:09:13 UTC (rev 39895)
+++ PluginRegistry/trunk/exportimport.py	2005-11-04 21:34:09 UTC (rev 39896)
@@ -0,0 +1,116 @@
+""" GenericSetup export / import support for PluginRegistry.
+
+$Id$
+"""
+from Persistence import PersistentMapping
+
+from Products.GenericSetup.utils import ExportConfiguratorBase
+from Products.GenericSetup.utils import ImportConfiguratorBase
+from Products.GenericSetup.utils import _getDottedName
+from Products.GenericSetup.utils import _resolveDottedName
+from Products.GenericSetup.utils import CONVERTER
+from Products.GenericSetup.utils import DEFAULT
+from Products.GenericSetup.utils import KEY
+from Products.PageTemplates.PageTemplateFile import PageTemplateFile
+
+from interfaces.plugins import IPluginRegistry
+
+def _providedBy(obj, iface):
+    try:
+        return iface.providedBy(obj)
+    except AttributeError:
+        return iface.isImplementedBy(obj) # Z2 interfaces
+
+_FILENAME = 'pluginregistry.xml'
+
+def _getRegistry(site):
+    registries = [x for x in site.objectValues()
+                    if _providedBy(x, IPluginRegistry)]
+
+    if len(registries) < 1:
+        raise ValueError, 'No plugin registries'
+
+    if len(registries) > 1:
+        raise ValueError, 'Too many plugin registries'
+
+    return registries[0]
+
+def exportPluginRegistry(context):
+    """ Export plugin registry as an XML file.
+    """
+    registry = _getRegistry(context.getSite())
+    pre = PluginRegistryExporter(registry).__of__(registry)
+    xml = pre.generateXML()
+    context.writeDataFile(_FILENAME, xml, 'text/xml')
+
+    return 'Plugin registry exported.'
+
+def importPluginRegistry(context):
+    """ Import plugin registry from an XML file.
+    """
+    registry = _getRegistry(context.getSite())
+    encoding = context.getEncoding()
+
+    xml = context.readDataFile(_FILENAME)
+    if xml is None:
+        return 'Site properties: Nothing to import.'
+
+    if context.shouldPurge():
+
+        registry._plugin_types = []
+        registry._plugin_type_info = PersistentMapping()
+        registry._plugins = PersistentMapping()
+
+    pir = PluginRegistryImporter(registry, encoding)
+    reg_info = pir.parseXML(xml)
+
+    for info in reg_info['plugin_types']:
+        iface = _resolveDottedName(info['interface'])
+        registry._plugin_types.append(iface)
+        registry._plugin_type_info[iface] = {'id': info['id'],
+                                             'title': info['title'],
+                                             'description': info['description'],
+                                            }
+        registry._plugins[iface] = tuple([x['id'] for x in info['plugins']])
+
+    return 'Plugin registry imported.'
+
+class PluginRegistryExporter(ExportConfiguratorBase):
+
+    def __init__(self, context, encoding=None):
+        ExportConfiguratorBase.__init__(self, None, encoding)
+        self.context = context
+
+    def _getExportTemplate(self):
+        return PageTemplateFile('xml/pirExport.xml', globals())
+
+    def listPluginTypes(self):
+        for info in self.context.listPluginTypeInfo():
+            iface = info['interface']
+            info['interface'] = _getDottedName(iface)
+            info['plugins'] = self.context.listPluginIds(iface)
+            yield info
+
+class PluginRegistryImporter(ImportConfiguratorBase):
+
+    def __init__(self, context, encoding=None):
+        ImportConfiguratorBase.__init__(self, None, encoding)
+        self.context = context
+
+    def _getImportMapping(self):
+
+        return {
+          'plugin-registry':
+            {'plugin-type': {KEY: 'plugin_types', DEFAULT: ()},
+            },
+          'plugin-type':
+            {'id':          {KEY: 'id'},
+             'interface':   {KEY: 'interface'},
+             'title':       {KEY: 'title'},
+             'description': {KEY: 'description'},
+             'plugin':      {KEY: 'plugins', DEFAULT: ()}
+            },
+          'plugin':
+            {'id':          {KEY: 'id'},
+            },
+         }


Property changes on: PluginRegistry/trunk/exportimport.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: PluginRegistry/trunk/tests/test_exportimport.py
===================================================================
--- PluginRegistry/trunk/tests/test_exportimport.py	2005-11-04 21:09:13 UTC (rev 39895)
+++ PluginRegistry/trunk/tests/test_exportimport.py	2005-11-04 21:34:09 UTC (rev 39896)
@@ -0,0 +1,405 @@
+""" Unit tests for GenericSetup-based export / import of PluginRegistry.
+
+$Id$
+"""
+import unittest
+
+try:
+    import Products.GenericSetup
+except ImportError:  # No GenericSetup, so no tests
+
+    print 'XXXX:  No GenericSetup!'
+    def test_suite():
+        return unittest.TestSuite()
+
+else:
+    from Products.GenericSetup.tests.common import BaseRegistryTests
+    from Products.GenericSetup.tests.common import DummyExportContext
+    from Products.GenericSetup.tests.common import DummyImportContext
+    from Products.GenericSetup.utils import _getDottedName
+
+    from zope.interface import Interface
+    from zope.app.tests.placelesssetup import PlacelessSetup
+
+    class IFoo(Interface):
+        pass
+
+    class IBar(Interface):
+        pass
+
+    _EMPTY_PLUGINREGISTRY_EXPORT = """\
+<?xml version="1.0"?>
+<plugin-registry>
+</plugin-registry>
+"""
+
+    _PLUGIN_TYPE_INFO = (
+      ( IFoo
+      , 'IFoo'
+      , 'foo'
+      , "Some plugin interface"
+      )
+    , ( IBar
+      , 'IBar'
+      , 'bar'
+      , "Another plugin interface"
+      )
+    )
+
+    _NO_PLUGINS_PLUGINREGISTRY_EXPORT = """\
+<?xml version="1.0"?>
+<plugin-registry>
+ <plugin-type
+    id="IFoo"
+    interface="%s"
+    title="foo"
+    description="Some plugin interface">
+ </plugin-type>
+ <plugin-type
+    id="IBar"
+    interface="%s"
+    title="bar"
+    description="Another plugin interface">
+ </plugin-type>
+</plugin-registry>
+""" % (_getDottedName(IFoo), _getDottedName(IBar))
+
+    _NORMAL_PLUGINREGISTRY_EXPORT = """\
+<?xml version="1.0"?>
+<plugin-registry>
+ <plugin-type
+    id="IFoo"
+    interface="%s"
+    title="foo"
+    description="Some plugin interface">
+  <plugin id="foo_plugin_1" />
+  <plugin id="foo_plugin_2" />
+ </plugin-type>
+ <plugin-type
+    id="IBar"
+    interface="%s"
+    title="bar"
+    description="Another plugin interface">
+ </plugin-type>
+</plugin-registry>
+""" % (_getDottedName(IFoo), _getDottedName(IBar))
+
+    class _TestBase(PlacelessSetup, BaseRegistryTests):
+
+        def _initRegistry(self, plugin_type_info=(), plugins={}):
+            from OFS.Folder import Folder
+            from OFS.SimpleItem import SimpleItem
+            from Products.PluginRegistry.PluginRegistry import PluginRegistry
+
+            app = Folder()
+            app.getPhysicalPath = lambda: ()
+            app.getPhysicalRoot = lambda: app
+
+            app._setObject('foo_plugin_1', SimpleItem())
+            app._setObject('foo_plugin_2', SimpleItem())
+
+            registry = PluginRegistry(plugin_type_info)
+            registry._plugins = {} # it is usually lazy
+
+            for plugin_type, registered in plugins.items():
+                registry._plugins[plugin_type] = registered
+
+            app._setObject('plugin_registry', registry)
+            registry = app._getOb('plugin_registry')
+            return app, registry
+
+    class PluginRegistryExporterTests(_TestBase):
+
+        def _getTargetClass(self):
+            from Products.PluginRegistry.exportimport \
+                import PluginRegistryExporter
+            return PluginRegistryExporter
+
+        def test_empty(self):
+
+            app, registry = self._initRegistry()
+            exporter = self._makeOne(registry).__of__(registry)
+            xml = exporter.generateXML()
+
+            self._compareDOM(xml, _EMPTY_PLUGINREGISTRY_EXPORT)
+
+        def test_normal_no_plugins(self):
+            app, registry = self._initRegistry(
+                                    plugin_type_info=_PLUGIN_TYPE_INFO)
+            exporter = self._makeOne(registry).__of__(registry)
+            xml = exporter.generateXML()
+
+            self._compareDOM(xml, _NO_PLUGINS_PLUGINREGISTRY_EXPORT)
+
+        def test_normal_with_plugins(self):
+            app, registry = self._initRegistry(
+                                    plugin_type_info=_PLUGIN_TYPE_INFO,
+                                    plugins={IFoo: ('foo_plugin_1',
+                                                    'foo_plugin_2')},
+                                        )
+            exporter = self._makeOne(registry).__of__(registry)
+            xml = exporter.generateXML()
+
+            self._compareDOM(xml, _NORMAL_PLUGINREGISTRY_EXPORT)
+
+    class Test_exportPluginRegistry(_TestBase):
+
+        def test_empty(self):
+            from Products.PluginRegistry.exportimport \
+                import exportPluginRegistry
+
+            app, registry = self._initRegistry()
+            context = DummyExportContext(app)
+            exportPluginRegistry(context)
+
+            self.assertEqual( len(context._wrote), 1 )
+            filename, text, content_type = context._wrote[0]
+            self.assertEqual(filename, 'pluginregistry.xml')
+            self._compareDOM(text, _EMPTY_PLUGINREGISTRY_EXPORT)
+            self.assertEqual(content_type, 'text/xml')
+
+        def test_normal_no_plugins(self):
+            from Products.PluginRegistry.exportimport \
+                import exportPluginRegistry
+
+            app, registry = self._initRegistry(
+                                    plugin_type_info=_PLUGIN_TYPE_INFO)
+            context = DummyExportContext(app)
+            exportPluginRegistry(context)
+
+            self.assertEqual( len(context._wrote), 1 )
+            filename, text, content_type = context._wrote[0]
+            self.assertEqual(filename, 'pluginregistry.xml')
+            self._compareDOM(text, _NO_PLUGINS_PLUGINREGISTRY_EXPORT)
+            self.assertEqual(content_type, 'text/xml')
+
+        def test_normal_with_plugins(self):
+            from Products.PluginRegistry.exportimport \
+                import exportPluginRegistry
+
+            app, registry = self._initRegistry(
+                                    plugin_type_info=_PLUGIN_TYPE_INFO,
+                                    plugins={IFoo: ('foo_plugin_1',
+                                                    'foo_plugin_2')},
+                                        )
+            context = DummyExportContext(app)
+            exportPluginRegistry(context)
+
+            self.assertEqual( len(context._wrote), 1 )
+            filename, text, content_type = context._wrote[0]
+            self.assertEqual(filename, 'pluginregistry.xml')
+            self._compareDOM(text, _NORMAL_PLUGINREGISTRY_EXPORT)
+            self.assertEqual(content_type, 'text/xml')
+
+    class PluginRegistryImporterTests(_TestBase):
+
+        def _getTargetClass(self):
+            from Products.PluginRegistry.exportimport \
+                import PluginRegistryImporter
+            return PluginRegistryImporter
+
+        def test_parseXML_empty(self):
+
+            app, registry = self._initRegistry()
+            importer = self._makeOne(registry).__of__(registry)
+            reg_info = importer.parseXML(_EMPTY_PLUGINREGISTRY_EXPORT)
+
+            self.assertEqual( len( reg_info['plugin_types'] ), 0 )
+
+        def test_parseXML_normal_no_plugins(self):
+
+            app, registry = self._initRegistry()
+            importer = self._makeOne(registry).__of__(registry)
+            reg_info = importer.parseXML(_NO_PLUGINS_PLUGINREGISTRY_EXPORT)
+
+            self.assertEqual( len( reg_info['plugin_types'] ), 2 )
+
+            info = reg_info['plugin_types'][0]
+            self.assertEqual(info['id'], 'IFoo')
+            self.assertEqual(info['interface'], _getDottedName(IFoo))
+            self.assertEqual(info['title'], 'foo')
+            self.assertEqual(info['description'], 'Some plugin interface')
+            self.assertEqual(len( info['plugins'] ), 0)
+
+            info = reg_info['plugin_types'][1]
+            self.assertEqual(info['id'], 'IBar')
+            self.assertEqual(info['interface'], _getDottedName(IBar))
+            self.assertEqual(info['title'], 'bar')
+            self.assertEqual(info['description'], 'Another plugin interface')
+            self.assertEqual(len( info['plugins'] ), 0 )
+
+        def test_parseXML_normal_with_plugins(self):
+
+            app, registry = self._initRegistry()
+            importer = self._makeOne(registry).__of__(registry)
+            reg_info = importer.parseXML(_NORMAL_PLUGINREGISTRY_EXPORT)
+
+            self.assertEqual(len(reg_info['plugin_types'] ), 2 )
+
+            info = reg_info['plugin_types'][0]
+            self.assertEqual(info['id'], 'IFoo')
+            self.assertEqual(info['interface'], _getDottedName(IFoo))
+            self.assertEqual(info['title'], 'foo')
+            self.assertEqual(info['description'], 'Some plugin interface')
+            plugins = info['plugins']
+            self.assertEqual(len(plugins), 2)
+            self.assertEqual(plugins[0]['id'], 'foo_plugin_1')
+            self.assertEqual(plugins[1]['id'], 'foo_plugin_2')
+
+            info = reg_info['plugin_types'][1]
+            self.assertEqual(info['id'], 'IBar')
+            self.assertEqual(info['interface'], _getDottedName(IBar))
+            self.assertEqual(info['title'], 'bar')
+            self.assertEqual(info['description'], 'Another plugin interface')
+            self.assertEqual(len(info['plugins']), 0 )
+
+    class Test_importPluginRegistry(_TestBase):
+
+        def test_empty_default_purge(self):
+            from Products.PluginRegistry.exportimport \
+                import importPluginRegistry
+
+            app, registry = self._initRegistry(
+                                    plugin_type_info=_PLUGIN_TYPE_INFO,
+                                    plugins={IFoo: ('foo_plugin_1',
+                                                    'foo_plugin_2')},
+                                   )
+
+            self.assertEqual(len(registry.listPluginTypeInfo()), 2)
+            self.assertEqual(len(registry.listPlugins(IFoo)), 2)
+            self.assertEqual(len(registry.listPlugins(IBar)), 0)
+
+            context = DummyImportContext(app)
+            context._files['pluginregistry.xml'] = _EMPTY_PLUGINREGISTRY_EXPORT
+
+            importPluginRegistry(context)
+
+            self.assertEqual(len(registry.listPluginTypeInfo()), 0)
+            self.assertRaises(KeyError, registry.listPlugins, IFoo)
+            self.assertRaises(KeyError, registry.listPlugins, IBar)
+
+        def test_empty_explicit_purge(self):
+            from Products.PluginRegistry.exportimport \
+                import importPluginRegistry
+
+            app, registry = self._initRegistry(
+                                    plugin_type_info=_PLUGIN_TYPE_INFO,
+                                    plugins={IFoo: ('foo_plugin_1',
+                                                    'foo_plugin_2')},
+                                   )
+
+            self.assertEqual(len(registry.listPluginTypeInfo()), 2)
+            self.assertEqual(len(registry.listPlugins(IFoo)), 2)
+            self.assertEqual(len(registry.listPlugins(IBar)), 0)
+
+            context = DummyImportContext(app, True)
+            context._files['pluginregistry.xml'] = _EMPTY_PLUGINREGISTRY_EXPORT
+
+            importPluginRegistry(context)
+
+            self.assertEqual(len(registry.listPluginTypeInfo()), 0)
+            self.assertRaises(KeyError, registry.listPlugins, IFoo)
+            self.assertRaises(KeyError, registry.listPlugins, IBar)
+
+        def test_empty_skip_purge(self):
+            from Products.PluginRegistry.exportimport \
+                import importPluginRegistry
+
+            app, registry = self._initRegistry(
+                                    plugin_type_info=_PLUGIN_TYPE_INFO,
+                                    plugins={IFoo: ('foo_plugin_1',
+                                                    'foo_plugin_2')},
+                                   )
+
+            self.assertEqual(len(registry.listPluginTypeInfo()), 2)
+            self.assertEqual(len(registry.listPlugins(IFoo)), 2)
+            self.assertEqual(len(registry.listPlugins(IBar)), 0)
+
+            context = DummyImportContext(app, False)
+            context._files['pluginregistry.xml'] = _EMPTY_PLUGINREGISTRY_EXPORT
+
+            importPluginRegistry(context)
+
+            self.assertEqual(len(registry.listPluginTypeInfo()), 2)
+            self.assertEqual(len(registry.listPlugins(IFoo)), 2)
+            self.assertEqual(len(registry.listPlugins(IBar)), 0)
+
+        def test_normal_no_plugins(self):
+            from Products.PluginRegistry.exportimport \
+                import importPluginRegistry
+
+            app, registry = self._initRegistry()
+
+            self.assertEqual(len(registry.listPluginTypeInfo()), 0)
+            self.assertRaises(KeyError, registry.listPlugins, IFoo)
+            self.assertRaises(KeyError, registry.listPlugins, IBar)
+
+            context = DummyImportContext(app, False)
+            context._files['pluginregistry.xml'
+                          ] = _NO_PLUGINS_PLUGINREGISTRY_EXPORT
+
+            importPluginRegistry(context)
+
+            self.assertEqual(len(registry.listPluginTypeInfo()), 2)
+
+            info = registry.listPluginTypeInfo()[0]
+            self.assertEqual(info['id'], 'IFoo')
+            self.assertEqual(info['title'], 'foo')
+            self.assertEqual(info['description'], 'Some plugin interface')
+
+            info = registry.listPluginTypeInfo()[1]
+            self.assertEqual(info['id'], 'IBar')
+            self.assertEqual(info['title'], 'bar')
+            self.assertEqual(info['description'], 'Another plugin interface')
+
+            self.assertEqual(len(registry.listPlugins(IFoo)), 0)
+            self.assertEqual(len(registry.listPlugins(IBar)), 0)
+
+        def test_normal_with_plugins(self):
+            from Products.PluginRegistry.exportimport \
+                import importPluginRegistry
+
+            app, registry = self._initRegistry()
+
+            self.assertEqual(len(registry.listPluginTypeInfo()), 0)
+            self.assertRaises(KeyError, registry.listPlugins, IFoo)
+            self.assertRaises(KeyError, registry.listPlugins, IBar)
+
+            context = DummyImportContext(app, False)
+            context._files['pluginregistry.xml'
+                          ] = _NORMAL_PLUGINREGISTRY_EXPORT
+
+            importPluginRegistry(context)
+
+            self.assertEqual(len(registry.listPluginTypeInfo()), 2)
+
+            info = registry.listPluginTypeInfo()[0]
+            self.assertEqual(info['id'], 'IFoo')
+            self.assertEqual(info['title'], 'foo')
+            self.assertEqual(info['description'], 'Some plugin interface')
+
+            info = registry.listPluginTypeInfo()[1]
+            self.assertEqual(info['id'], 'IBar')
+            self.assertEqual(info['title'], 'bar')
+            self.assertEqual(info['description'], 'Another plugin interface')
+
+            self.assertEqual(len(registry.listPlugins(IFoo)), 2)
+            plugins = registry.listPlugins(IFoo)
+            self.assertEqual(plugins[0][0], 'foo_plugin_1')
+            self.assertEqual(plugins[0][1], app._getOb('foo_plugin_1'))
+            self.assertEqual(plugins[1][0], 'foo_plugin_2')
+            self.assertEqual(plugins[1][1], app._getOb('foo_plugin_2'))
+
+            self.assertEqual(len(registry.listPlugins(IBar)), 0)
+
+    def test_suite():
+        return unittest.TestSuite((
+            unittest.makeSuite( PluginRegistryExporterTests ),
+            unittest.makeSuite( PluginRegistryImporterTests ),
+            unittest.makeSuite( Test_exportPluginRegistry ),
+            unittest.makeSuite( Test_importPluginRegistry ),
+           ))
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')
+


Property changes on: PluginRegistry/trunk/tests/test_exportimport.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: PluginRegistry/trunk/xml/pirExport.xml
===================================================================
--- PluginRegistry/trunk/xml/pirExport.xml	2005-11-04 21:09:13 UTC (rev 39895)
+++ PluginRegistry/trunk/xml/pirExport.xml	2005-11-04 21:34:09 UTC (rev 39896)
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<plugin-registry xmlns:tal="http://xml.zope.org/namespaces/tal">
+ <plugin-type
+    id="PLUGIN_TYPE_ID"
+    title="PLUGIN_TYPE_TITLE"
+    description="PLUGIN_TYPE_DESCRIPTION"
+    interface="PLUGIN_TYPE_INTERFACE"
+    tal:repeat="pt context/listPluginTypes"
+    tal:attributes="id pt/id;
+                    title pt/title;
+                    description pt/description;
+                    interface pt/interface;
+                   "
+    >
+  <plugin
+    id="PLUGIN_ID"
+    tal:repeat="plugin_id pt/plugins"
+    tal:attributes="id plugin_id" />
+ </plugin-type>
+</plugin-registry>


Property changes on: PluginRegistry/trunk/xml/pirExport.xml
___________________________________________________________________
Name: svn:eol-style
   + native



More information about the Zope-CVS mailing list