From 6716db2d929d5acea2cd05470c3356afa34d2c32 Mon Sep 17 00:00:00 2001 From: helmutm Date: Mon, 16 Jan 2006 19:09:34 +0000 Subject: [PATCH] Defined adapters for export/import of nodes git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1008 fd906abe-77d9-0310-91a1-e0d9ade77398 --- README.txt | 48 +++++++++++++++ configure.zcml | 8 +++ external.py | 157 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 213 insertions(+) create mode 100644 external.py diff --git a/README.txt b/README.txt index d38ed40..57633a2 100755 --- a/README.txt +++ b/README.txt @@ -264,8 +264,56 @@ to the bottom, and to the top >>> m11.keys() ['m111', 'm114', 'm112', 'm113'] +Import/Export +------------- + +Nodes may be exported to and loaded from external sources, typically +file representations that allow the transfer of nodes from one Zope +instance to another. + + >>> from loops.external import NodesLoader + >>> loader = NodesLoader(views) + >>> data = [{'name': 'm2', 'path': '', 'description': u'desc 1', + ... 'title': u'M 2', 'body': u'test m2', 'nodeType': 'menu' }, + ... {'name': 'm21', 'path': 'm2', 'description': u'', + ... 'title': u'M 21', 'body': u'test m21', 'nodeType': 'page' }, + ... {'name': 'm114', 'path': 'm1/m11', 'description': u'', + ... 'title': u'M 114', 'body': u'test m114', 'nodeType': 'page' },] + >>> loader.load(data) + >>> views['m2']['m21'].title + u'M 21' + >>> views['m1']['m11']['m114'].title + u'M 114' + + >>> from loops.external import NodesExporter, NodesImporter + >>> exporter = NodesExporter(views) + >>> data = exporter.extractData() + >>> len(data) + 8 + >>> data[3]['path'] + u'm1/m11' + >>> data[3]['name'] + u'm112' + + >>> import os + >>> dumpname = os.path.dirname(__file__) + '/test.tmp' + >>> exporter.filename = dumpname + >>> exporter.dumpData() + +Load them again from the exported file: + + >>> importer = NodesImporter(views) + >>> importer.filename = dumpname + >>> imported = importer.getData() + >>> imported == data + True + + >>> loader.load(imported) + + Fin de partie ============= + >>> os.unlink(dumpname) >>> placefulTearDown() diff --git a/configure.zcml b/configure.zcml index cf11676..bcdfbe9 100644 --- a/configure.zcml +++ b/configure.zcml @@ -173,6 +173,14 @@ + + + + + + + + diff --git a/external.py b/external.py new file mode 100644 index 0000000..e5fa433 --- /dev/null +++ b/external.py @@ -0,0 +1,157 @@ +# +# Copyright (c) 2005 Helmut Merz helmutm@cy55.de +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +""" +Adapter implementations for export, import, ... + +$Id$ +""" + +from zope.interface import implements, Interface +from zope.app import zapi +from zope.component import adapts + +from loops.interfaces import IViewManager +from loops.view import Node + + +# import/export interfaces (for adapters) + +class IExternalContentSource(Interface): + """ Provides content from an external source. + """ + + def getData(): + """ Retrieve content from the external source; return a sequence of + dictionaries in a format like this: + [{'name': ..., 'title': ..., 'body':... }, ...], + """ + + +class ILoader(Interface): + """ Inserts data provided by an IExternalContentSource object into the + database. + """ + + def load(data): + """ Create objects as defined by the data given; this is a sequence + as described for IExternalContentSource.getContent(). + """ + + +class IExporter(Interface): + """ Extracts data and in a format usable by ILoader. + + Optionally dump data to a file. + """ + + def extractData(): + """ Return a data object as described for + IExternalContentSource.getData(). + """ + + def dumpData(file): + """ Dump data returned by extractData() to the file given in a + format that might be read in by a suitable implementation of + IExternalContentSource. + """ + + +# implementations for views/nodes + +class NodesLoader(object): + + implements(ILoader) + adapts(IViewManager) + + def __init__(self, context): + self.context = context + + def load(self, data): + for item in data: + name = item['name'] + path = item['path'] + parent = zapi.traverse(self.context, path) + if name in parent: # replace existing objects + del parent[name] + node = Node() + node.title = item['title'] + node.description = item['description'] + node.body = item['body'] + node.nodeType = item['nodeType'] + parent[name] = node + + +class NodesExporter(object): + + implements(IExporter) + adapts(IViewManager) + + filename = 'loops.dmp' + + def __init__(self, context): + self.context = context + + def extractData(self): + data = [] + for child in self.context.values(): + self.extractNodeData(child, '', data) + return data + + def extractNodeData(self, item, path, data): + name = zapi.getName(item) + data.append({ + 'name': name, + 'path': path, + 'description': item.description, + 'title': item.title, + 'body': item.body, + 'nodeType': item.nodeType + }) + path = path and '%s/%s' % (path, name) or name + for child in item.values(): + self.extractNodeData(child, path, data) + + + def dumpData(self, file=None, noclose=False): + if file is None: + file = open(self.filename, 'w') + data = self.extractData() + text = `data`.replace('},', '},\n').replace('}],', '}],\n') + file.write(text) + if not noclose: + file.close() + + +class NodesImporter(object): + + implements(IExternalContentSource) + adapts(IViewManager) + + filename = 'loops.dmp' + + def __init__(self, context): + self.context = context + + def getData(self, file=None): + if file is None: + file = open(self.filename, 'r') + data = file.read().replace('\n', '') + file.close() + return eval(data, {}, {}) +