[Zope3-checkins] SVN: Zope3/trunk/src/zope/app/wiki/ Improved the
file representation of Wiki Pages and Comments. You can now
Stephan Richter
srichter at cosmos.phy.tufts.edu
Fri Jul 2 13:01:24 EDT 2004
Log message for revision 26048:
Improved the file representation of Wiki Pages and Comments. You can now
add and edit comments and wiki pages through FTP!
-=-
Modified: Zope3/trunk/src/zope/app/wiki/browser/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/wiki/browser/configure.zcml 2004-07-02 16:36:19 UTC (rev 26047)
+++ Zope3/trunk/src/zope/app/wiki/browser/configure.zcml 2004-07-02 17:01:24 UTC (rev 26048)
@@ -135,13 +135,13 @@
label="Comment"
name="AddComment.html"
schema="zope.app.wiki.interfaces.IComment"
- content_factory="zope.app.wiki.wikipage.Comment"
+ content_factory="zope.app.wiki.comment.Comment"
permission="zope.app.wiki.AddWikiPage"
fields="title source type"
class=".wikipage.AddComment" />
<browser:addMenuItem
- class="zope.app.wiki.wikipage.Comment"
+ class="zope.app.wiki.comment.Comment"
title="Comment"
description="A Comment"
permission="zope.app.wiki.AddWikiPage"
Added: Zope3/trunk/src/zope/app/wiki/comment.py
===================================================================
--- Zope3/trunk/src/zope/app/wiki/comment.py 2004-07-02 16:36:19 UTC (rev 26047)
+++ Zope3/trunk/src/zope/app/wiki/comment.py 2004-07-02 17:01:24 UTC (rev 26048)
@@ -0,0 +1,207 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""WikiPage Comment
+
+$Id$
+"""
+from persistent import Persistent
+
+from zope.interface import implements
+from zope.schema.vocabulary import getVocabularyRegistry
+from zope.app.dublincore.interfaces import ICMFDublinCore
+from zope.app.filerepresentation.interfaces import IReadFile, IWriteFile
+
+from zope.app.wiki.interfaces import IComment
+from zope.app.wiki.interfaces import IWikiPageContained
+
+
+class Comment(Persistent):
+ r"""A simple persistent comment implementation.
+
+ The comment is really a primitive object, since it only declares a couple
+ of attributes. The only thing interesting here is the title, which
+ retrieved from its Dublin Core value.
+
+ First off let's make sure that we actually implement the interface:
+
+ >>> comment = Comment()
+ >>> IComment.providedBy(comment)
+ True
+
+ Now, verify that the attributes are set correctly.
+
+ >>> comment.source
+ u''
+ >>> comment.source = u'comment 1'
+ >>> comment.source
+ u'comment 1'
+
+ >>> comment.type
+ u'zope.source.rest'
+ >>> comment.type = u'zope.source.stx'
+ >>> comment.type
+ u'zope.source.stx'
+
+ >>> comment.title
+ u''
+ >>> comment.title = u'C1'
+ >>> comment.title
+ u'C1'
+
+ (Note: The comment is not responsible for checking the validity of the
+ type.)
+
+ """
+ implements(IComment, IWikiPageContained)
+
+ # See zope.app.container.interfaces.IContained
+ __parent__ = __name__ = None
+
+ # See zope.app.wiki.interfaces.IComment
+ source = u''
+
+ # See zope.app.wiki.interfaces.IComment
+ type = u'zope.source.rest'
+
+ # See zope.app.wiki.interfaces.IComment
+ def _getTitle(self):
+ dc = ICMFDublinCore(self)
+ return dc.title
+
+ def _setTitle(self, title):
+ dc = ICMFDublinCore(self)
+ dc.title = title
+
+ title = property(_getTitle, _setTitle)
+
+
+# Adapters for file-system style access
+
+class CommentFile:
+ r"""Adapter for letting a Comment look like a regular readable file.
+
+ Example of Usage:
+
+ >>> comment = Comment()
+ >>> comment.title = u'Comment 1'
+ >>> comment.source = u'This is a comment'
+ >>> file = CommentFile(comment)
+
+ Now let's see whether we can read the comment file.
+
+ >>> file.read()
+ u'Title: Comment 1\nType: zope.source.rest\n\nThis is a comment'
+
+ And that the size of the file is correct:
+
+ >>> file.size()
+ 58
+
+ Let's see whether we can also write to a file correctly:
+
+ >>> file.write('Title: C1\nType: zope.source.stx\n\ncomment 1')
+ >>> comment.title
+ u'C1'
+ >>> comment.type
+ u'zope.source.stx'
+ >>> comment.source
+ u'comment 1'
+
+ Sometimes the user might not have entered a valid type; let's ignore the
+ assignment then.
+
+ >>> file.write('Type: zope.source.foo\n\ncomment 2')
+ >>> comment.title
+ u'C1'
+ >>> comment.type
+ u'zope.source.stx'
+ >>> comment.source
+ u'comment 2'
+
+ In the previous example the title was missing, but the type is optional
+ too:
+
+ >>> file.write('Title: C3\n\ncomment 3')
+ >>> comment.title
+ u'C3'
+ >>> comment.type
+ u'zope.source.stx'
+ >>> comment.source
+ u'comment 3'
+ """
+
+ implements(IReadFile, IWriteFile)
+ __used_for__ = IComment
+
+ def __init__(self, context):
+ self.context = context
+
+ def read(self):
+ """See zope.app.filerepresentation.interfaces.IReadFile"""
+ text = 'Title: %s\n' %self.context.title
+ text += 'Type: %s\n\n' %self.context.type
+ text += self.context.source
+ return text
+
+ def size(self):
+ """See zope.app.filerepresentation.interfaces.IReadFile"""
+ return len(self.read())
+
+ def write(self, data):
+ """See zope.app.filerepresentation.interfaces.IWriteFile"""
+ if data.startswith('Title: '):
+ title, data = data.split('\n', 1)
+ self.context.title = unicode(title[7:])
+
+ if data.startswith('Type: '):
+ type, data = data.split('\n', 1)
+ type = type[6:]
+ vocab = getVocabularyRegistry().get(self.context, 'SourceTypes')
+ if type in [term.value for term in vocab]:
+ self.context.type = unicode(type)
+
+ if data.startswith('\n'):
+ data = data[1:]
+
+ self.context.source = unicode(data)
+
+
+class CommentFileFactory(object):
+ r"""A factory that creates a comment.
+
+ This component is used by the WikiPage file representation. If you add a
+ file to a wiki page, then it is interpreted as adding a comment to the
+ wiki page.
+
+ Usage:
+
+ >>> factory = CommentFileFactory(None)
+ >>> comment = factory('foo' ,'',
+ ... 'Title: C1\nType: zope.source.stx\n\nComment 1')
+ >>> comment.title
+ u'C1'
+ >>> comment.type
+ u'zope.source.stx'
+ >>> comment.source
+ u'Comment 1'
+ """
+
+ def __init__(self, context):
+ """Initialize the object."""
+
+ def __call__(self, name, content_type, data):
+ """The comment is created from the provided information."""
+ comment = Comment()
+ CommentFile(comment).write(data)
+ return comment
Modified: Zope3/trunk/src/zope/app/wiki/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/wiki/configure.zcml 2004-07-02 16:36:19 UTC (rev 26047)
+++ Zope3/trunk/src/zope/app/wiki/configure.zcml 2004-07-02 17:01:24 UTC (rev 26048)
@@ -148,7 +148,7 @@
type="zope.app.content.interfaces.IContentType"
/>
- <content class=".wikipage.Comment">
+ <content class=".comment.Comment">
<implements
interface="zope.app.annotation.interfaces.IAttributeAnnotatable" />
@@ -166,7 +166,21 @@
</content>
+ <adapter
+ for=".interfaces.IComment"
+ provides="zope.app.filerepresentation.interfaces.IReadFile"
+ factory=".comment.CommentFile"
+ permission="zope.app.wiki.ViewWikiPage"
+ />
+ <adapter
+ for=".interfaces.IComment"
+ provides="zope.app.filerepresentation.interfaces.IWriteFile"
+ factory=".comment.CommentFile"
+ permission="zope.app.wiki.CommentWikiPage"
+ />
+
+
<!-- Mail Subscriptions support -->
<adapter
factory=".wikipage.MailSubscriptions"
@@ -182,18 +196,24 @@
<!-- WikiPage FTP configurations -->
<adapter
for=".interfaces.IWikiPage"
- provides="zope.app.filerepresentation.interfaces.IReadFile"
- factory=".wikipage.WikiPageReadFile"
+ provides="zope.app.filerepresentation.interfaces.IReadDirectory"
+ factory=".wikipage.Directory"
permission="zope.app.wiki.ViewWikiPage"
/>
<adapter
for=".interfaces.IWikiPage"
- provides="zope.app.filerepresentation.interfaces.IWriteFile"
- factory=".wikipage.WikiPageWriteFile"
- permission="zope.app.wiki.EditWikiPage"
+ provides="zope.app.filerepresentation.interfaces.IWriteDirectory"
+ factory=".wikipage.Directory"
+ permission="zope.app.wiki.CommentWikiPage"
/>
+ <adapter
+ for=".interfaces.IWikiPage"
+ provides="zope.app.filerepresentation.interfaces.IFileFactory"
+ factory="zope.app.wiki.comment.CommentFileFactory"
+ permission="zope.ManageContent"
+ />
<!-- Register mail delivery for change mails -->
<mail:smtpMailer name="wiki-smtp" hostname="localhost" port="25" />
Deleted: Zope3/trunk/src/zope/app/wiki/tests/test_comments.py
===================================================================
--- Zope3/trunk/src/zope/app/wiki/tests/test_comments.py 2004-07-02 16:36:19 UTC (rev 26047)
+++ Zope3/trunk/src/zope/app/wiki/tests/test_comments.py 2004-07-02 17:01:24 UTC (rev 26048)
@@ -1,51 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""ZWiki Tests
-
-$Id$
-"""
-import unittest
-
-from zope.app.wiki.wikipage import Comment
-from zope.app.wiki.interfaces import IComment
-
-class TestComment(unittest.TestCase):
-
- def setUp(self):
- self.comment = Comment()
-
- def test_Interface(self):
- self.failUnless(IComment.providedBy(self.comment))
-
- def test_source(self):
- self.assertEqual('', self.comment.source)
- self.comment.source = 'foo'
- self.assertEqual('foo', self.comment.source)
-
- def test_type(self):
- self.assertEqual('zope.source.rest', self.comment.type)
- self.comment.type = 'foo'
- self.assertEqual('foo', self.comment.type)
-
-
- # XXX: Test title
-
-
-def test_suite():
- return unittest.TestSuite((
- unittest.makeSuite(TestComment),
- ))
-
-if __name__ == '__main__':
- unittest.main()
Added: Zope3/trunk/src/zope/app/wiki/tests/test_docstrings.py
===================================================================
--- Zope3/trunk/src/zope/app/wiki/tests/test_docstrings.py 2004-07-02 16:36:19 UTC (rev 26047)
+++ Zope3/trunk/src/zope/app/wiki/tests/test_docstrings.py 2004-07-02 17:01:24 UTC (rev 26048)
@@ -0,0 +1,72 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Docstring tests for the wiki package.
+
+$Id$
+"""
+import unittest
+from zope.schema.vocabulary import SimpleVocabulary
+from zope.schema.vocabulary import VocabularyRegistry, _clear
+from zope.schema.vocabulary import getVocabularyRegistry
+from zope.schema.vocabulary import setVocabularyRegistry
+from zope.testing.doctestunit import DocTestSuite
+
+from zope.app import zapi
+from zope.app.dublincore.interfaces import ICMFDublinCore
+from zope.app.tests import placelesssetup, ztapi
+
+from zope.app.wiki.interfaces import IComment
+
+
+class DCStub(object):
+
+ def __init__(self, context):
+ self.context = context
+
+ def getTitle(self):
+ return getattr(self.context, 'dc_title', u'')
+
+ def setTitle(self, title):
+ self.context.dc_title = title
+
+ title = property(getTitle, setTitle)
+
+def VocabularyFactory(context):
+ return SimpleVocabulary.fromValues(('zope.source.rest', 'zope.source.stx'))
+
+
+def setUp():
+ placelesssetup.setUp()
+ ztapi.provideAdapter(IComment, ICMFDublinCore, DCStub)
+
+ _clear()
+ registry = VocabularyRegistry()
+ registry.register('SourceTypes', VocabularyFactory)
+ setVocabularyRegistry(registry)
+
+
+def tearDown():
+ placelesssetup.tearDown()
+
+
+def test_suite():
+ return unittest.TestSuite((
+ DocTestSuite('zope.app.wiki.comment',
+ setUp=setUp, tearDown=tearDown),
+ DocTestSuite('zope.app.wiki.wikipage',
+ setUp=setUp, tearDown=tearDown),
+ ))
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
Deleted: Zope3/trunk/src/zope/app/wiki/tests/test_wikipagefile.py
===================================================================
--- Zope3/trunk/src/zope/app/wiki/tests/test_wikipagefile.py 2004-07-02 16:36:19 UTC (rev 26047)
+++ Zope3/trunk/src/zope/app/wiki/tests/test_wikipagefile.py 2004-07-02 17:01:24 UTC (rev 26048)
@@ -1,53 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""ZWiki Tests
-
-$Id$
-"""
-import unittest
-
-from zope.app.wiki.wikipage import WikiPage
-from zope.app.wiki.wikipage import WikiPageReadFile, WikiPageWriteFile
-
-class ReadFileTest(unittest.TestCase):
-
- def setUp(self):
- self._page = WikiPage()
- self._page.source = u'This is the source'
- self._file = WikiPageReadFile(self._page)
-
- def test_read(self):
- self.assertEqual(self._page.source, self._file.read())
-
- def test_size(self):
- self.assertEqual(len(self._page.source), self._file.size())
-
-class WriteFileTest(unittest.TestCase):
-
- def setUp(self):
- self._page = WikiPage()
- self._file = WikiPageWriteFile(self._page)
-
- def test_read(self):
- self._file.write(u'This is the source')
- self.assertEqual(u'This is the source', self._page.source)
-
-def test_suite():
- return unittest.TestSuite((
- unittest.makeSuite(ReadFileTest),
- unittest.makeSuite(WriteFileTest),
- ))
-
-if __name__ == '__main__':
- unittest.main()
Modified: Zope3/trunk/src/zope/app/wiki/wikipage.py
===================================================================
--- Zope3/trunk/src/zope/app/wiki/wikipage.py 2004-07-02 16:36:19 UTC (rev 26047)
+++ Zope3/trunk/src/zope/app/wiki/wikipage.py 2004-07-02 17:01:24 UTC (rev 26048)
@@ -19,25 +19,26 @@
from zope.interface import implements
from zope.event import notify
+from zope.schema.vocabulary import getVocabularyRegistry
from zope.app import zapi
from zope.app.container.btree import BTreeContainer
-from zope.app.dublincore.interfaces import ICMFDublinCore
-from zope.app.filerepresentation.interfaces import IReadFile, IWriteFile
+from zope.app.filerepresentation.interfaces import IReadFile
+from zope.app.filerepresentation.interfaces import IWriteFile
+from zope.app.filerepresentation.interfaces import IReadDirectory
+from zope.app.filerepresentation.interfaces import IWriteDirectory
from zope.app.annotation.interfaces import IAnnotations
from zope.app.event.objectevent import ObjectEvent
from zope.app.container.interfaces import \
IObjectAddedEvent, IObjectRemovedEvent
from zope.app.mail.interfaces import IMailDelivery
-from zope.app.wiki.interfaces import IWiki, IWikiPage, IComment
+from zope.app.wiki.interfaces import IWiki, IWikiPage
from zope.app.wiki.interfaces import IWikiContained, IWikiPageContained
from zope.app.wiki.interfaces import IWikiPageHierarchy, IMailSubscriptions
from zope.app.wiki.interfaces import IWikiPageEditEvent
from zope.app.wiki.diff import textdiff
-__metaclass__ = type
-
HierarchyKey = 'http://www.zope.org/zwiki#1.0/PageHierarchy/parents'
SubscriberKey = 'http://www.zope.org/zwiki#1.0/MailSubscriptions/emails'
@@ -69,7 +70,7 @@
type = u'zope.source.rest'
-class WikiPageHierarchyAdapter:
+class WikiPageHierarchyAdapter(object):
__doc__ = IWikiPageHierarchy.__doc__
implements(IWikiPageHierarchy)
@@ -119,65 +120,167 @@
return tuple(children)
-# Simple comments implementation
-class Comment(Persistent):
- """A simple persistent comment implementation."""
- implements(IComment, IWikiPageContained)
-
- # See zope.app.container.interfaces.IContained
- __parent__ = __name__ = None
+# Adapters for file-system style access
- # See zope.app.wiki.interfaces.IComment
- source = u''
-
- # See zope.app.wiki.interfaces.IComment
- type = u'zope.source.rest'
+class Directory(object):
+ r"""Adapter to provide a file-system rendition of wiki pages
+ Usage:
- # See zope.app.wiki.interfaces.IComment
- def _getTitle(self):
- dc = ICMFDublinCore(self)
- return dc.title
+ >>> page = WikiPage()
+ >>> page.source = 'This is the FrontPage.'
- def _setTitle(self, title):
- dc = ICMFDublinCore(self)
- dc.title = title
+ >>> from comment import Comment
+ >>> comment = Comment()
+ >>> comment.title = u'C1'
+ >>> comment.source = u'Comment 1'
+ >>> page[u'comment1'] = comment
- title = property(_getTitle, _setTitle)
+ >>> dir = Directory(page)
+ >>> IReadDirectory.providedBy(dir)
+ True
+ >>> IWriteDirectory.providedBy(dir)
+ True
+ >>> dir.keys()
+ [u'comment1', u'content.txt']
+ >>> len(dir)
+ 2
-# Adapters for file-system style access
+ >>> content = dir.get('content.txt')
+ >>> content.__class__ == ContentFile
+ True
+ >>> comment = dir.get('comment1')
+ >>> comment.__class__ == Comment
+ True
-class WikiPageReadFile:
- """Adapter for letting a Wiki Page look like a regular readable file."""
+ >>> del dir[u'content.txt']
+ >>> dir.keys()
+ [u'comment1', u'content.txt']
+ >>> del dir[u'comment1']
+ >>> dir.keys()
+ [u'content.txt']
+ """
- implements(IReadFile)
+ content_file = u'content.txt'
+ implements(IReadDirectory, IWriteDirectory)
__used_for__ = IWikiPage
def __init__(self, context):
self.context = context
- def read(self):
- """See zope.app.filerepresentation.interfaces.IReadFile"""
- return self.context.source
+ def keys(self):
+ return list(self.context.keys()) + [self.content_file]
- def size(self):
- """See zope.app.filerepresentation.interfaces.IReadFile"""
- return len(self.context.source)
+ def get(self, key, default=None):
+ if key == self.content_file:
+ return ContentFile(self.context)
+ return self.context.get(key, default)
+ def __iter__(self):
+ return iter(self.keys())
-class WikiPageWriteFile:
- """Adapter for letting a Wiki Page look like a regular writable file."""
+ def __getitem__(self, key):
+ v = self.get(key, self)
+ if v is self:
+ raise KeyError, key
+ return v
- implements(IWriteFile)
+ def values(self):
+ return map(self.get, self.keys())
+
+ def __len__(self):
+ return len(self.context)+1
+
+ def items(self):
+ get = self.get
+ return [(key, get(key)) for key in self.keys()]
+
+ def __contains__(self, key):
+ return self.get(key) is not None
+
+ def __setitem__(self, name, object):
+ if name == self.content_file:
+ pass
+ else:
+ self.context.__setitem__(name, object)
+
+ def __delitem__(self, name):
+ if name == self.content_file:
+ pass
+ else:
+ self.context.__delitem__(name)
+
+
+class ContentFile:
+ r"""Adapter for letting a Wiki Page look like a regular file.
+
+ Usage:
+
+ >>> page = WikiPage()
+ >>> page.source = 'This is the FrontPage.'
+
+ >>> file = ContentFile(page)
+ >>> IReadFile.providedBy(file)
+ True
+ >>> IWriteFile.providedBy(file)
+ True
+
+ >>> file.read()
+ u'Source Type: zope.source.rest\n\nThis is the FrontPage.'
+ >>> file.size()
+ 53
+
+ >>> file.write('Type: zope.source.stx\n\nThis is the FrontPage 2.')
+ >>> file.context.type
+ u'zope.source.stx'
+ >>> file.context.source
+ u'This is the FrontPage 2.'
+
+ Sometimes the user might not have entered a valid type; let's ignore the
+ assignment then.
+
+ >>> file.write('Type: zope.source.foo\n\nThis is the FrontPage 3.')
+ >>> file.context.type
+ u'zope.source.stx'
+ >>> file.context.source
+ u'This is the FrontPage 3.'
+
+ Or the type was ommitted altogether.
+
+ >>> file.write('This is the FrontPage 4.')
+ >>> file.context.type
+ u'zope.source.stx'
+ >>> file.context.source
+ u'This is the FrontPage 4.'
+ """
+
+ implements(IReadFile, IWriteFile)
__used_for__ = IWikiPage
-
+
def __init__(self, context):
self.context = context
+ def read(self):
+ """See zope.app.filerepresentation.interfaces.IReadFile"""
+ text = u'Source Type: %s\n\n' %self.context.type
+ text += self.context.source
+ return text
+
+ def size(self):
+ """See zope.app.filerepresentation.interfaces.IReadFile"""
+ return len(self.read())
+
def write(self, data):
"""See zope.app.filerepresentation.interfaces.IWriteFile"""
+ if data.startswith('Type: '):
+ type, data = data.split('\n\n', 1)
+ type = type[6:]
+ vocab = getVocabularyRegistry().get(self.context, 'SourceTypes')
+ if type in [term.value for term in vocab]:
+ self.context.type = unicode(type)
+
self.context.source = unicode(data)
More information about the Zope3-Checkins
mailing list