From eddf4287ec838f7d4961a5499f41dbb9d7aeab0f Mon Sep 17 00:00:00 2001 From: helmutm Date: Sun, 14 Feb 2010 09:51:49 +0000 Subject: [PATCH] work in progress: loops site synchronization: export (and subsequent import) of changes git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@3729 fd906abe-77d9-0310-91a1-e0d9ade77398 --- external/base.py | 3 --- organize/job/base.py | 2 +- system/README.txt | 3 +++ system/browser.py | 42 +++++++++++++++++++++++++++++++ system/configure.zcml | 14 ++++++++--- system/interfaces.py | 17 ++++++++++++- system/job.py | 51 ++++++++++++++++++++++++++++++++++++++ system/setup.py | 8 +++++- system/sync/README.txt | 32 ++++++++++++++++++++++++ system/sync/__init__.py | 3 +++ system/sync/browser.py | 49 ++++++++++++++++++++++++++++++++++++ system/sync/configure.zcml | 16 ++++++++++++ system/sync/control.pt | 10 ++++++++ system/sync/tests.py | 27 ++++++++++++++++++++ 14 files changed, 268 insertions(+), 9 deletions(-) create mode 100644 system/browser.py create mode 100644 system/job.py create mode 100644 system/sync/README.txt create mode 100644 system/sync/__init__.py create mode 100644 system/sync/browser.py create mode 100644 system/sync/configure.zcml create mode 100644 system/sync/control.pt create mode 100755 system/sync/tests.py diff --git a/external/base.py b/external/base.py index 498ce8f..52faf7f 100644 --- a/external/base.py +++ b/external/base.py @@ -194,9 +194,6 @@ class Extractor(Base): element = self.getDeassignmentElement(obj, child, pred) if element is not None: yield element - # TODO: include new parent and child relations - # TODO: include statements for removal of relations if necessary - # (or remove relations not in import file upon import) # TODO: include children and resources if corresponding flags are set. def extractForParents(self, parents, predicates=None, diff --git a/organize/job/base.py b/organize/job/base.py index 1737694..09d2371 100644 --- a/organize/job/base.py +++ b/organize/job/base.py @@ -37,4 +37,4 @@ class JobManager(object): self.context = context def process(self): - raise NotImplementedError("Method 'process' has to be implementd by subclass.") + raise NotImplementedError("Method 'process' has to be implemented by subclass.") diff --git a/system/README.txt b/system/README.txt index 3bc1aae..ab90402 100644 --- a/system/README.txt +++ b/system/README.txt @@ -42,6 +42,9 @@ In addition to the application site we need a loops system management site. [u'domain', u'file', u'hasType', u'job', u'note', u'predicate', u'standard', u'textdocument', u'type'] + >>> list(systemRoot.getRecordManager().keys()) + [u'jobs'] + Agents and Jobs =============== diff --git a/system/browser.py b/system/browser.py new file mode 100644 index 0000000..f00c9a1 --- /dev/null +++ b/system/browser.py @@ -0,0 +1,42 @@ +# +# Copyright (c) 2010 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 +# + +""" +Views for loops system management. + +$Id$ +""" + +from cybertools.tracking.btree import TrackingStorage +from loops.system.job import JobRecord + + +class SetupActions(object): + """ Collection of methods for manually setting up system objects + within a loops site. + """ + + def __init__(self, context, request): + self.context = context + self.request = request + + def setupJobRecords(self): + records = self.context.getRecordManager() + if 'jobs' not in records: + records['jobs'] = TrackingStorage(trackFactory=JobRecord) + return 'Done' diff --git a/system/configure.zcml b/system/configure.zcml index 2441ce6..bc2c008 100644 --- a/system/configure.zcml +++ b/system/configure.zcml @@ -3,11 +3,19 @@ + i18n_domain="loops"> - + + + + diff --git a/system/interfaces.py b/system/interfaces.py index bb16900..db4a2c9 100644 --- a/system/interfaces.py +++ b/system/interfaces.py @@ -25,10 +25,23 @@ $Id$ from zope.interface import Interface, Attribute from zope import interface, component, schema +from cybertools.tracking.interfaces import ITrack from loops.interfaces import IConceptSchema from loops.util import _ +class IJobRecords(Interface): + + pass + + +class IJobRecord(ITrack): + + pass + + +# agent-based job control - not used at the moment. + class IJob(IConceptSchema): """ Specifies/represents a job to be executed by a cybertools.agent instance. @@ -43,7 +56,8 @@ class IJob(IConceptSchema): title=_(u'Agent Identifier'), description=_(u'The identifier of the agent that will ' 'execute the job; this identifies also the type ' - 'of job, e.g. a crawling or transport job.') + 'of job, e.g. a crawling or transport job.'), + required=False,) startTime = schema.Date( title=_(u'Start Date/Time'), description=_(u'Date/time at which the job should be ' @@ -63,3 +77,4 @@ class IJobManager(IConceptSchema): """ A container/manager for jobs to be executed by a cybertools.agent instance. """ + diff --git a/system/job.py b/system/job.py new file mode 100644 index 0000000..29c2a53 --- /dev/null +++ b/system/job.py @@ -0,0 +1,51 @@ +# +# Copyright (c) 2010 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 +# + +""" +Recording changes to loops objects. + +$Id$ +""" + +from zope.interface import implements +from zope.cachedescriptors.property import Lazy +from zope.component import adapter + +from cybertools.meta.interfaces import IOptions +from cybertools.tracking.btree import Track, getTimeStamp +from loops.organize.tracking.base import BaseRecordManager +from loops.system.interfaces import IJobRecord, IJobRecords +from loops import util + + +class JobRecords(BaseRecordManager): + + implements(IJobRecords) + + storageName = 'jobs' + + def __init__(self, context): + self.context = context + + +class JobRecord(Track): + + implements(IJobRecord) + + typeName = 'JobRecord' + diff --git a/system/setup.py b/system/setup.py index 8da391e..8518157 100644 --- a/system/setup.py +++ b/system/setup.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2008 Helmut Merz helmutm@cy55.de +# Copyright (c) 2010 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 @@ -25,9 +25,11 @@ $Id$ from zope.component import adapts from zope.interface import implements, Interface +from cybertools.tracking.btree import TrackingStorage from loops.concept import Concept from loops.interfaces import ITypeConcept from loops.setup import SetupManager as BaseSetupManager +from loops.system.job import JobRecord class SetupManager(BaseSetupManager): @@ -39,4 +41,8 @@ class SetupManager(BaseSetupManager): # type concepts: job = self.addAndConfigureObject(concepts, Concept, 'job', title=u'Job', conceptType=type) + # job records: + records = self.context.getRecordManager() + if 'jobs' not in records: + records['jobs'] = TrackingStorage(trackFactory=JobRecord) diff --git a/system/sync/README.txt b/system/sync/README.txt new file mode 100644 index 0000000..e237ea8 --- /dev/null +++ b/system/sync/README.txt @@ -0,0 +1,32 @@ +=============================================================== +loops - Linked Objects for Organization and Processing Services +=============================================================== + + ($Id$) + + >>> from zope import component + >>> from zope.traversing.api import getName + +Let's set up a loops site with basic and example concepts and resources. + + >>> from zope.app.testing.setup import placefulSetUp, placefulTearDown + >>> site = placefulSetUp(True) + + >>> from loops.expert.testsetup import TestSite + >>> t = TestSite(site) + >>> concepts, resources, views = t.setup() + >>> loopsRoot = site['loops'] + >>> len(concepts), len(resources), len(views) + (30, 3, 1) + + +Synchronize: Transfer Changes from one loops Site to Another +============================================================ + + >>> from loops.system.sync.browser import SyncChanges + + +Fin de Partie +============= + + >>> placefulTearDown() diff --git a/system/sync/__init__.py b/system/sync/__init__.py new file mode 100644 index 0000000..38314f3 --- /dev/null +++ b/system/sync/__init__.py @@ -0,0 +1,3 @@ +""" +$Id$ +""" diff --git a/system/sync/browser.py b/system/sync/browser.py new file mode 100644 index 0000000..7027143 --- /dev/null +++ b/system/sync/browser.py @@ -0,0 +1,49 @@ +# +# Copyright (c) 2010 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 +# + +""" +view class(es) for import/export. + +$Id$ +""" + +from cStringIO import StringIO +import os +import time +from zope import component +from zope.interface import Interface, implements +from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile +from zope.cachedescriptors.property import Lazy +from zope.traversing.api import getName, getPath + +from loops.organize.tracking.report import RecentChanges +from loops import util + + +control_macros = ViewPageTemplateFile('control.pt') + + +class SyncChanges(RecentChanges): + """ View for controlling the transfer of changes from a loops site + to another one. + """ + + @Lazy + def macro(self): + return control_macros.macros['main'] + diff --git a/system/sync/configure.zcml b/system/sync/configure.zcml new file mode 100644 index 0000000..f7bfc44 --- /dev/null +++ b/system/sync/configure.zcml @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/system/sync/control.pt b/system/sync/control.pt new file mode 100644 index 0000000..abd22d4 --- /dev/null +++ b/system/sync/control.pt @@ -0,0 +1,10 @@ + + + + + +
+ + +
diff --git a/system/sync/tests.py b/system/sync/tests.py new file mode 100755 index 0000000..e294ff6 --- /dev/null +++ b/system/sync/tests.py @@ -0,0 +1,27 @@ +# $Id$ + +import unittest, doctest +import os +from zope.testing.doctestunit import DocFileSuite +from zope.interface.verify import verifyClass + + +dataDirectory = os.path.join(os.path.dirname(__file__), 'testdata') + + +class Test(unittest.TestCase): + "Basic tests for the loops.system.sync package." + + def testSomething(self): + pass + + +def test_suite(): + flags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS + return unittest.TestSuite(( + unittest.makeSuite(Test), + DocFileSuite('README.txt', optionflags=flags), + )) + +if __name__ == '__main__': + unittest.main(defaultTest='test_suite')