From fbcbff77349abb3a7e6de1647f20f8589597f297 Mon Sep 17 00:00:00 2001 From: helmutm Date: Thu, 4 Jan 2007 22:39:57 +0000 Subject: [PATCH] added package storage.pzope git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@1541 fd906abe-77d9-0310-91a1-e0d9ade77398 --- storage/pzope/README.txt | 49 +++++++++++++++++++++++ storage/pzope/__init__.py | 3 ++ storage/pzope/manager.py | 83 +++++++++++++++++++++++++++++++++++++++ storage/pzope/tests.py | 28 +++++++++++++ util/adapter.py | 18 +++++---- 5 files changed, 174 insertions(+), 7 deletions(-) create mode 100644 storage/pzope/README.txt create mode 100644 storage/pzope/__init__.py create mode 100644 storage/pzope/manager.py create mode 100755 storage/pzope/tests.py diff --git a/storage/pzope/README.txt b/storage/pzope/README.txt new file mode 100644 index 0000000..1e63a54 --- /dev/null +++ b/storage/pzope/README.txt @@ -0,0 +1,49 @@ +========================= +Zope-based Object Storage +========================= + + ($Id$) + + >>> from zope.app.testing.setup import placefulSetUp, placefulTearDown + >>> site = placefulSetUp(True) + + >>> from zope import component + >>> from zope.app.intid.interfaces import IIntIds + >>> from cybertools.relation.tests import IntIdsStub + >>> component.provideUtility(IntIdsStub(), IIntIds) + +We first need a class from which we will create objects that later on +will be stored in and retrieved from the storage. + + >>> class Content(object): + ... title = 'demo' + + >>> c1 = Content() + >>> c1.title + 'demo' + >>> c1.title = 'changed' + >>> c1.title + 'changed' + +We can save the object in the storage by getting a storage adapter +from the corresponding factory in the `manager` module and calling +`save()` on it. + + >>> from cybertools.storage.pzope.manager import storages + >>> persistent = storages(c1) + >>> uid = persistent.save('c1') + +For loading an object we get a storage adapter to the object's class and +call `load()` on it. + + >>> persistent = storages(Content) + >>> c2 = persistent.load(uid) + >>> c2.title + 'changed' + + +Fin de partie +============= + + >>> placefulTearDown() + diff --git a/storage/pzope/__init__.py b/storage/pzope/__init__.py new file mode 100644 index 0000000..38314f3 --- /dev/null +++ b/storage/pzope/__init__.py @@ -0,0 +1,3 @@ +""" +$Id$ +""" diff --git a/storage/pzope/manager.py b/storage/pzope/manager.py new file mode 100644 index 0000000..cb0c557 --- /dev/null +++ b/storage/pzope/manager.py @@ -0,0 +1,83 @@ +# +# Copyright (c) 2007 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 +# + +""" +Storage manager implementation for a full Zope 3 environment. + +$Id$ +""" + +from zope import component +from zope.interface import implements +from zope.app.component.hooks import getSite +from zope.app.container.interfaces import IContained +from zope.app.intid.interfaces import IIntIds +from zope.app.traversing.api import traverse, traverseName +from persistent import Persistent as BasePersistent + +from cybertools.util.adapter import AdapterFactory + + +storages = AdapterFactory() + + +class Adapter(object): + + def __init__(self, context): + self.context = context + self.persistent = None + + def save(self, name, path='/'): + intids = component.getUtility(IIntIds) + persistent = self.persistent + if persistent is None: + persistent = Persistent() + site = getSite() + container = traverse(site, path) + container[name] = persistent + uid = intids.register(persistent) + else: + uid = intids.getId(persistent) + persistent.update(self.context.__dict__) + persistent._p_changed = True + self.persistent = persistent + return uid + + def load(self, idOrPath): + if type(idOrPath) is int: + intids = component.getUtility(IIntIds) + persistent = intids.getObject(idOrPath) + else: + site = getSite() + persistent = traverse(site, path) + t = type(self.context) + class_ = t is type and self.context or t + obj = self.context = class_() + obj.__dict__.update(persistent.get()) + return obj + +storages.register(Adapter, object) + + +class Persistent(BasePersistent): + + def update(self, data): + self.__dict__.update(data) + + def get(self): + return self.__dict__ diff --git a/storage/pzope/tests.py b/storage/pzope/tests.py new file mode 100755 index 0000000..3213778 --- /dev/null +++ b/storage/pzope/tests.py @@ -0,0 +1,28 @@ +#! /usr/bin/python + +""" +Tests for the 'cybertools.storage.zope' package. + +$Id$ +""" + +import unittest, doctest +from zope.testing.doctestunit import DocFileSuite + + +class Test(unittest.TestCase): + "Basic tests for the storage package." + + def testBasicStuff(self): + pass + + +def test_suite(): + flags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS + return unittest.TestSuite(( + #unittest.makeSuite(Test), #not used + DocFileSuite('README.txt', optionflags=flags), + )) + +if __name__ == '__main__': + unittest.main(defaultTest='test_suite') diff --git a/util/adapter.py b/util/adapter.py index 1717a3f..61c533f 100644 --- a/util/adapter.py +++ b/util/adapter.py @@ -35,13 +35,7 @@ class AdapterFactory(object): """ self._registry[(adapted, name)] = adapter - def __call__(self, obj, name=''): - """ Return an adapter instance on `obj` with the `name` given. - if obj is a class use this class for the adapter lookup, else - use obj's class. - If there isn't an adapter directly for the class - check also for its base classes. - """ + def queryAdapter(self, obj, name): class_ = type(obj) is type and obj or obj.__class__ adapter = None while adapter is None and class_: @@ -49,4 +43,14 @@ class AdapterFactory(object): if adapter is None: bases = class_.__bases__ class_ = bases and bases[0] or None + return adapter + + def __call__(self, obj, name=''): + """ Return an adapter instance on `obj` with the `name` given. + if obj is a class use this class for the adapter lookup, else + use obj's class. + If there isn't an adapter directly for the class + check also for its base classes. + """ + adapter = self.queryAdapter(obj, name) return adapter is not None and adapter(obj) or None