work in progress: wiki implementation for Zope 2 based on generic object access interfaces
git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@3610 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
a08922f990
commit
df079e9955
15 changed files with 482 additions and 10 deletions
|
@ -38,17 +38,36 @@ class WikiConfigInfo(dict):
|
||||||
return self.get(attr, None)
|
return self.get(attr, None)
|
||||||
|
|
||||||
|
|
||||||
|
class BaseConfigurator(object):
|
||||||
|
|
||||||
|
def __init__(self, context):
|
||||||
|
self.context = context
|
||||||
|
|
||||||
|
def initialize(self):
|
||||||
|
ci = WikiConfigInfo()
|
||||||
|
self.context._configInfo = ci
|
||||||
|
return ci
|
||||||
|
|
||||||
|
def getConfigInfo(self):
|
||||||
|
return self.context._configInfo
|
||||||
|
|
||||||
|
|
||||||
class BaseConfiguration(object):
|
class BaseConfiguration(object):
|
||||||
""" The base class for all wiki configuration implementations.
|
""" The base class for all wiki configuration implementations.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
implements(IWikiConfiguration)
|
implements(IWikiConfiguration)
|
||||||
|
|
||||||
|
configurator = BaseConfigurator
|
||||||
|
|
||||||
_configInfo = None
|
_configInfo = None
|
||||||
|
|
||||||
|
def getConfigInfo(self):
|
||||||
|
return self.configurator(self).getConfigInfo()
|
||||||
|
|
||||||
def getConfig(self, functionality):
|
def getConfig(self, functionality):
|
||||||
c = None
|
c = None
|
||||||
ci = self._configInfo
|
ci = self.getConfigInfo()
|
||||||
if ci is not None:
|
if ci is not None:
|
||||||
c = ci.get(functionality)
|
c = ci.get(functionality)
|
||||||
if c is None:
|
if c is None:
|
||||||
|
@ -58,9 +77,10 @@ class BaseConfiguration(object):
|
||||||
return c
|
return c
|
||||||
|
|
||||||
def setConfig(self, functionality, value):
|
def setConfig(self, functionality, value):
|
||||||
if self._configInfo is None:
|
ci = self.getConfigInfo()
|
||||||
self._configInfo = WikiConfigInfo()
|
if ci is None:
|
||||||
self._configInfo.set(functionality, value)
|
ci = self.configurator(self).initialize()
|
||||||
|
ci.set(functionality, value)
|
||||||
|
|
||||||
def getConfigParent(self):
|
def getConfigParent(self):
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -38,15 +38,16 @@ class WikiManager(BaseConfiguration):
|
||||||
|
|
||||||
implements(IWikiManager)
|
implements(IWikiManager)
|
||||||
|
|
||||||
def __init__(self):
|
def setup(self):
|
||||||
self.wikis = {}
|
self.wikis = {}
|
||||||
|
self.plugins = {}
|
||||||
|
|
||||||
def addWiki(self, wiki):
|
def addWiki(self, wiki):
|
||||||
name = wiki.name
|
name = wiki.name
|
||||||
if name in self.wikis:
|
if name in self.wikis:
|
||||||
raise ValueError("Wiki '%s' already registered." % name)
|
raise ValueError("Wiki '%s' already registered." % name)
|
||||||
self.wikis[name] = wiki
|
self.wikis[name] = wiki
|
||||||
wiki.manager = self
|
wiki.setManager(self)
|
||||||
return wiki
|
return wiki
|
||||||
|
|
||||||
def removeWiki(self, wiki):
|
def removeWiki(self, wiki):
|
||||||
|
@ -57,16 +58,25 @@ class WikiManager(BaseConfiguration):
|
||||||
def listWikis(self):
|
def listWikis(self):
|
||||||
return self.wikis.values()
|
return self.wikis.values()
|
||||||
|
|
||||||
def getPlugin(self, type, name):
|
def getPlugin(self, type, name=None):
|
||||||
|
plugins = self.getPlugins()
|
||||||
|
if (type, name) in plugins:
|
||||||
|
plugin = plugins[(type, name)]
|
||||||
|
if type is None:
|
||||||
|
return plugin
|
||||||
|
return type(plugin)
|
||||||
return component.getUtility(type, name=name)
|
return component.getUtility(type, name=name)
|
||||||
|
|
||||||
|
def getPlugins(self):
|
||||||
|
return self.plugins
|
||||||
|
|
||||||
def getUid(self, obj):
|
def getUid(self, obj):
|
||||||
return component.getUtility(IIntIds).getId(obj)
|
return self.getPlugin(IIntIds).register(obj)
|
||||||
|
|
||||||
def getObject(self, uid):
|
def getObject(self, uid):
|
||||||
obj = self.resolveUid(uid)
|
obj = self.resolveUid(uid)
|
||||||
if obj is None:
|
if obj is None:
|
||||||
return component.getUtility(IIntIds).getObject(int(uid))
|
return self.getPlugin(IIntIds).getObject(int(uid))
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def resolveUid(self, uid):
|
def resolveUid(self, uid):
|
||||||
|
@ -92,10 +102,19 @@ class Wiki(BaseConfiguration):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.title = title or name
|
self.title = title or name
|
||||||
self.pages = {}
|
self.pages = {}
|
||||||
|
self.setup()
|
||||||
|
|
||||||
|
def setup(self):
|
||||||
|
self.getManager().addWiki(self)
|
||||||
|
self.createPage('StartPage', u'Start Page',
|
||||||
|
u'The text of the **Start Page**')
|
||||||
|
|
||||||
def getManager(self):
|
def getManager(self):
|
||||||
return self.manager
|
return self.manager
|
||||||
|
|
||||||
|
def setManager(self, manager):
|
||||||
|
self.manager = manager
|
||||||
|
|
||||||
def createPage(self, name, title=None):
|
def createPage(self, name, title=None):
|
||||||
if name in self.pages:
|
if name in self.pages:
|
||||||
raise ValueError("Name '%s' already present." % name)
|
raise ValueError("Name '%s' already present." % name)
|
||||||
|
@ -138,6 +157,10 @@ class WikiPage(BaseConfiguration):
|
||||||
def __init__(self, name, title=None):
|
def __init__(self, name, title=None):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.title = title or name
|
self.title = title or name
|
||||||
|
self.setup()
|
||||||
|
|
||||||
|
def setup(self):
|
||||||
|
pass
|
||||||
|
|
||||||
def getWiki(self):
|
def getWiki(self):
|
||||||
return self.wiki
|
return self.wiki
|
||||||
|
|
3
wiki/browser/__init__.py
Normal file
3
wiki/browser/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
"""
|
||||||
|
$Id$
|
||||||
|
"""
|
3
wiki/generic/__init__.py
Normal file
3
wiki/generic/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
"""
|
||||||
|
$Id$
|
||||||
|
"""
|
179
wiki/generic/wiki.py
Normal file
179
wiki/generic/wiki.py
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2009 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
|
||||||
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
Wiki implementation = adapters for Zope2 content objects.
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
"""
|
||||||
|
|
||||||
|
from Acquisition import aq_inner, aq_parent
|
||||||
|
from BTrees.IOBTree import IOTreeSet
|
||||||
|
from BTrees.OOBTree import OOBTree
|
||||||
|
from persistent.mapping import PersistentMapping
|
||||||
|
from zope.app.intid import IntIds
|
||||||
|
from zope.app.intid.interfaces import IIntIds
|
||||||
|
from zope.cachedescriptors.property import Lazy
|
||||||
|
from zope import component
|
||||||
|
from zope.component import adapts
|
||||||
|
from zope.interface import implements
|
||||||
|
|
||||||
|
from cybertools.util.generic.interfaces import IGenericObject, IGenericFolder
|
||||||
|
from cybertools.wiki.base.config import WikiConfigInfo, BaseConfigurator
|
||||||
|
from cybertools.wiki.base.wiki import WikiManager as BaseWikiManager
|
||||||
|
from cybertools.wiki.base.wiki import Wiki as BaseWiki
|
||||||
|
from cybertools.wiki.base.wiki import WikiPage as BaseWikiPage
|
||||||
|
from cybertools.wiki.interfaces import ILinkManager, IWikiConfigInfo
|
||||||
|
from cybertools.wiki.tracking.link import Link, TrackingStorage
|
||||||
|
|
||||||
|
|
||||||
|
class PersistentConfigInfo(PersistentMapping):
|
||||||
|
|
||||||
|
implements(IWikiConfigInfo)
|
||||||
|
|
||||||
|
def set(self, functionality, value):
|
||||||
|
self[functionality] = value
|
||||||
|
|
||||||
|
def __getattr__(self, attr):
|
||||||
|
return self.get(attr, None)
|
||||||
|
|
||||||
|
|
||||||
|
class GenericConfigurator(BaseConfigurator):
|
||||||
|
|
||||||
|
def initialize(self):
|
||||||
|
ci = PersistentConfigInfo()
|
||||||
|
self.context.context.setGenericAttribute('configInfo', ci)
|
||||||
|
return ci
|
||||||
|
|
||||||
|
def getConfigInfo(self):
|
||||||
|
return self.context.context.getGenericAttribute('configInfo', None)
|
||||||
|
|
||||||
|
|
||||||
|
class WikiManager(BaseWikiManager):
|
||||||
|
|
||||||
|
adapts(IGenericObject)
|
||||||
|
|
||||||
|
configurator = GenericConfigurator
|
||||||
|
|
||||||
|
def __init__(self, context):
|
||||||
|
self.context = context
|
||||||
|
|
||||||
|
def setup(self):
|
||||||
|
self.context.setGenericAttribute('wikis', IOTreeSet())
|
||||||
|
plugins = self.context.setGenericAttribute('plugins', PersistentMapping())
|
||||||
|
plugins[(IIntIds, None)] = IntIds()
|
||||||
|
linkStorage = TrackingStorage(trackFactory=Link)
|
||||||
|
plugins[(ILinkManager, 'tracking')] = linkStorage
|
||||||
|
self.setConfig('linkManager', 'tracking')
|
||||||
|
|
||||||
|
def addWiki(self, wiki):
|
||||||
|
uid = self.getUid(wiki)
|
||||||
|
self.wikiUids.insert(uid)
|
||||||
|
wiki.setManager(self)
|
||||||
|
return wiki
|
||||||
|
|
||||||
|
def removeWiki(self, wiki):
|
||||||
|
uid = self.getUid(wiki)
|
||||||
|
if uid in self.wikiUids:
|
||||||
|
self.wikiUids.remove(uid)
|
||||||
|
|
||||||
|
def listWikis(self):
|
||||||
|
for uid in self.wikiUids:
|
||||||
|
yield self.getObject(uid)
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def wikiUids(self):
|
||||||
|
return self.context.getGenericAttribute('wikis')
|
||||||
|
|
||||||
|
def getPlugins(self):
|
||||||
|
return self.context.getGenericAttribute('plugins')
|
||||||
|
|
||||||
|
def getUid(self, obj):
|
||||||
|
return super(WikiManager, self).getUid(obj.context)
|
||||||
|
|
||||||
|
def getObject(self, uid):
|
||||||
|
obj = self.resolveUid(uid)
|
||||||
|
if obj is None:
|
||||||
|
co = super(WikiManager, self).getObject(uid)
|
||||||
|
return co.typeInterface(co)
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
class Wiki(BaseWiki):
|
||||||
|
|
||||||
|
adapts(IGenericFolder)
|
||||||
|
|
||||||
|
def __init__(self, context):
|
||||||
|
self.context = context
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return self.context.getId()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def pages(self):
|
||||||
|
# TODO: restrict to wiki page objects; use generic access methods
|
||||||
|
return dict((k, WikiPage(v)) for k, v in self.context.objectItems())
|
||||||
|
|
||||||
|
def createPage(self, name, title, text=u''):
|
||||||
|
obj = self.context.pageFactory(name)
|
||||||
|
page = WikiPage(obj)
|
||||||
|
page.title = title
|
||||||
|
page.text = text
|
||||||
|
self.context._setObject(name, obj)
|
||||||
|
return getattr(self.context, name)
|
||||||
|
|
||||||
|
def getManager(self):
|
||||||
|
# TODO: fetch tool/utility in a generic way
|
||||||
|
co = self.context.portal_wikimanager
|
||||||
|
return co.typeInterface(co)
|
||||||
|
|
||||||
|
def absolute_url(self):
|
||||||
|
return self.context.absolute_url()
|
||||||
|
|
||||||
|
|
||||||
|
class WikiPage(BaseWikiPage):
|
||||||
|
|
||||||
|
adapts(IGenericFolder)
|
||||||
|
|
||||||
|
def __init__(self, context):
|
||||||
|
self.context = context
|
||||||
|
|
||||||
|
def getTitle(self):
|
||||||
|
return self.context.title
|
||||||
|
def setTitle(self, title):
|
||||||
|
self.context.title = title
|
||||||
|
title = property(getTitle, setTitle)
|
||||||
|
|
||||||
|
def getText(self):
|
||||||
|
return self.context.text
|
||||||
|
def setText(self, text):
|
||||||
|
if self.context.getProperty('text') is None:
|
||||||
|
self.context.manage_addProperty('text', text, 'text')
|
||||||
|
else:
|
||||||
|
self.context.manage_changeProperties(id='text', value=text)
|
||||||
|
text = property(getText, setText)
|
||||||
|
|
||||||
|
def getWiki(self):
|
||||||
|
# TODO: fetch wiki in a generic way
|
||||||
|
return Wiki(aq_parent(aq_inner(self.context)))
|
||||||
|
#return Wiki(getParent(self.context))
|
||||||
|
|
||||||
|
def absolute_url(self):
|
||||||
|
return self.context.absolute_url()
|
||||||
|
|
|
@ -23,6 +23,7 @@ $Id$
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from zope.interface import Interface, Attribute
|
from zope.interface import Interface, Attribute
|
||||||
|
from zope import schema
|
||||||
|
|
||||||
|
|
||||||
class IWikiConfigInfo(Interface):
|
class IWikiConfigInfo(Interface):
|
||||||
|
@ -96,6 +97,8 @@ class IWiki(Interface):
|
||||||
""" A collection of wiki pages, or - more generally - wiki components.
|
""" A collection of wiki pages, or - more generally - wiki components.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
title = schema.TextLine(title=u'Title')
|
||||||
|
|
||||||
name = Attribute('The name or address of the wiki unique within the '
|
name = Attribute('The name or address of the wiki unique within the '
|
||||||
'scope of the wiki manager.')
|
'scope of the wiki manager.')
|
||||||
pages = Attribute('')
|
pages = Attribute('')
|
||||||
|
|
|
@ -53,7 +53,7 @@ class Test(unittest.TestCase):
|
||||||
def setUp(testCase):
|
def setUp(testCase):
|
||||||
component.provideAdapter(WikiURL, (IWiki, IBrowserRequest), IAbsoluteURL)
|
component.provideAdapter(WikiURL, (IWiki, IBrowserRequest), IAbsoluteURL)
|
||||||
component.provideAdapter(PageURL, (IWikiPage, IBrowserRequest), IAbsoluteURL)
|
component.provideAdapter(PageURL, (IWikiPage, IBrowserRequest), IAbsoluteURL)
|
||||||
component.provideUtility(IntIdsStub())
|
#component.provideUtility(IntIdsStub())
|
||||||
component.provideUtility(WikiConfiguration())
|
component.provideUtility(WikiConfiguration())
|
||||||
component.provideUtility(DocutilsHTMLWriter(), name='docutils.html')
|
component.provideUtility(DocutilsHTMLWriter(), name='docutils.html')
|
||||||
component.provideUtility(DocutilsRstxParser(), name='docutils.rstx')
|
component.provideUtility(DocutilsRstxParser(), name='docutils.rstx')
|
||||||
|
@ -62,6 +62,8 @@ def setUp(testCase):
|
||||||
component.provideAdapter(link.LinkManager)
|
component.provideAdapter(link.LinkManager)
|
||||||
links = link.setupLinkManager(None)
|
links = link.setupLinkManager(None)
|
||||||
component.provideUtility(links, name='tracking')
|
component.provideUtility(links, name='tracking')
|
||||||
|
from cybertools.wiki.generic import wiki
|
||||||
|
wiki.IntIds = IntIdsStub
|
||||||
|
|
||||||
|
|
||||||
def test_suite():
|
def test_suite():
|
||||||
|
|
|
@ -135,6 +135,7 @@ class LinkManager(BaseLinkManager):
|
||||||
return self.context
|
return self.context
|
||||||
|
|
||||||
|
|
||||||
|
# for testing only:
|
||||||
def setupLinkManager(manager):
|
def setupLinkManager(manager):
|
||||||
ts = TrackingStorage(trackFactory=Link)
|
ts = TrackingStorage(trackFactory=Link)
|
||||||
return ILinkManager(ts)
|
return ILinkManager(ts)
|
||||||
|
|
10
z2/README.txt
Normal file
10
z2/README.txt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
=================================================================
|
||||||
|
Supporting the Zope2 Environment for Zope3/ZTK-based Applications
|
||||||
|
=================================================================
|
||||||
|
|
||||||
|
($Id$)
|
||||||
|
|
||||||
|
>>> from zope import component
|
||||||
|
>>> from zope.publisher.browser import TestRequest
|
||||||
|
|
||||||
|
|
3
z2/__init__.py
Normal file
3
z2/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
"""
|
||||||
|
$Id$
|
||||||
|
"""
|
48
z2/browser.py
Normal file
48
z2/browser.py
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2009 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
|
||||||
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
Base classes for views.
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
"""
|
||||||
|
|
||||||
|
from zope.cachedescriptors.property import Lazy
|
||||||
|
from zope import component
|
||||||
|
from Products.Five import BrowserView
|
||||||
|
|
||||||
|
|
||||||
|
class GenericView(BrowserView):
|
||||||
|
|
||||||
|
name = 'index_html'
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def object(self):
|
||||||
|
return self.context.typeInterface(self.context)
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def objectView(self):
|
||||||
|
return component.getMultiAdapter((self.object, self.request), name=self.name)
|
||||||
|
|
||||||
|
def __call__(self):
|
||||||
|
return self.objectView()
|
||||||
|
|
||||||
|
|
||||||
|
class GenericAddForm(GenericView):
|
||||||
|
|
||||||
|
name = 'create.html'
|
29
z2/configure.zcml
Normal file
29
z2/configure.zcml
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<!-- $Id$ -->
|
||||||
|
|
||||||
|
<configure
|
||||||
|
xmlns:zope="http://namespaces.zope.org/zope"
|
||||||
|
xmlns:browser="http://namespaces.zope.org/browser">
|
||||||
|
|
||||||
|
<!-- <zope:adapter
|
||||||
|
for="cybertools.z2.interfaces.IBase
|
||||||
|
zope.publisher.interfaces.browser.IBrowserRequest"
|
||||||
|
provides="zope.publisher.interfaces.browser.IBrowserPublisher"
|
||||||
|
factory="cybertools.z2.traversal.Traverser" />
|
||||||
|
|
||||||
|
<zope:adapter factory="cybertools.z2.base.BaseObject" />
|
||||||
|
<zope:adapter factory="cybertools.z2.base.BaseFolder"
|
||||||
|
provides="cybertools.util.generic.interfaces.IGenericFolder" />-->
|
||||||
|
|
||||||
|
<browser:page
|
||||||
|
name="index_html"
|
||||||
|
for="cybertools.util.generic.interfaces.IGeneric"
|
||||||
|
class="cybertools.z2.browser.GenericView"
|
||||||
|
permission="zope2.View" />
|
||||||
|
|
||||||
|
<browser:page
|
||||||
|
name="create.html"
|
||||||
|
for="cybertools.util.generic.interfaces.IGeneric"
|
||||||
|
class="cybertools.z2.browser.GenericAddForm"
|
||||||
|
permission="zope2.ManageProperties" />
|
||||||
|
|
||||||
|
</configure>
|
75
z2/generic.py
Normal file
75
z2/generic.py
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2009 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
|
||||||
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
Base classes.
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
"""
|
||||||
|
|
||||||
|
from persistent.mapping import PersistentMapping
|
||||||
|
from zope.app.container.interfaces import IObjectAddedEvent
|
||||||
|
from zope import component
|
||||||
|
from zope.interface import implements
|
||||||
|
|
||||||
|
from cybertools.util.generic.interfaces import IGeneric
|
||||||
|
from cybertools.util.generic.interfaces import IGenericObject, IGenericFolder
|
||||||
|
|
||||||
|
|
||||||
|
_not_found = object()
|
||||||
|
|
||||||
|
|
||||||
|
class GenericObject(object):
|
||||||
|
""" A mixin class supporting generic attribute access and other
|
||||||
|
basic or common functionality when combined with Zope2's
|
||||||
|
SimpleItem.
|
||||||
|
"""
|
||||||
|
|
||||||
|
implements(IGenericObject)
|
||||||
|
|
||||||
|
typeInterface = None
|
||||||
|
|
||||||
|
def setup(self):
|
||||||
|
self.__generic_attributes__ = PersistentMapping()
|
||||||
|
if self.typeInterface:
|
||||||
|
obj = self.typeInterface(self)
|
||||||
|
obj.setup()
|
||||||
|
|
||||||
|
def getGenericAttribute(self, attr, default=_not_found):
|
||||||
|
value = self.__generic_attributes__.get(attr, default)
|
||||||
|
if value is _not_found:
|
||||||
|
raise AttributeError(attr)
|
||||||
|
return value
|
||||||
|
|
||||||
|
def setGenericAttribute(self, attr, value):
|
||||||
|
self.__generic_attributes__[attr] = value
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
class GenericFolder(GenericObject):
|
||||||
|
""" Provide generic (i.e. dictionary-like) folder access to Zope2's
|
||||||
|
Folder or BTreeFolder.
|
||||||
|
"""
|
||||||
|
|
||||||
|
implements(IGenericFolder)
|
||||||
|
|
||||||
|
|
||||||
|
@component.adapter(IGeneric, IObjectAddedEvent)
|
||||||
|
def setup(obj, event):
|
||||||
|
obj.setup()
|
||||||
|
component.provideHandler(setup)
|
28
z2/tests.py
Executable file
28
z2/tests.py
Executable file
|
@ -0,0 +1,28 @@
|
||||||
|
#! /usr/bin/python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Tests for the 'cybertools.z2' package.
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
"""
|
||||||
|
|
||||||
|
import unittest, doctest
|
||||||
|
from zope.testing.doctestunit import DocFileSuite
|
||||||
|
|
||||||
|
|
||||||
|
class Test(unittest.TestCase):
|
||||||
|
"Basic tests for the wiki package."
|
||||||
|
|
||||||
|
def testBasicStuff(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')
|
45
z2/traversal.py
Normal file
45
z2/traversal.py
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2009 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
|
||||||
|
#
|
||||||
|
"""
|
||||||
|
IPublishTraverse adapter for Zope 2 objects providing IBase.
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
"""
|
||||||
|
|
||||||
|
from zope import component
|
||||||
|
from ZPublisher.BaseRequest import DefaultPublishTraverse
|
||||||
|
from ZPublisher.HTTPRequest import HTTPRequest
|
||||||
|
|
||||||
|
from cybertools.util.generic.interfaces import IGeneric
|
||||||
|
|
||||||
|
|
||||||
|
class Traverser(DefaultPublishTraverse):
|
||||||
|
|
||||||
|
def publishTraverse(self, request, name):
|
||||||
|
typeInterface = getattr(self.context, 'typeInterface', None)
|
||||||
|
if typeInterface is not None:
|
||||||
|
genObj = IGeneric(self.context, None)
|
||||||
|
if genObj is not None:
|
||||||
|
obj = typeInterface(genObj, None)
|
||||||
|
if obj is not None:
|
||||||
|
view = component.queryMultiAdapter((obj, request), name=name)
|
||||||
|
#print '*** obj', obj, view
|
||||||
|
if view is not None:
|
||||||
|
return view
|
||||||
|
return super(Traverser, self).publishTraverse(request, name)
|
||||||
|
|
Loading…
Add table
Reference in a new issue