[Zope-CVS] SVN: book/trunk/smileyutility/ global and local smiley
utility.
Stephan Richter
srichter at cosmos.phy.tufts.edu
Sat Aug 21 14:16:50 EDT 2004
Log message for revision 27213:
global and local smiley utility.
Changed:
A book/trunk/smileyutility/
A book/trunk/smileyutility/__init__.py
A book/trunk/smileyutility/browser.py
A book/trunk/smileyutility/configure.zcml
A book/trunk/smileyutility/globaltheme.py
A book/trunk/smileyutility/interfaces.py
A book/trunk/smileyutility/localtheme.py
A book/trunk/smileyutility/meta.zcml
A book/trunk/smileyutility/metaconfigure.py
A book/trunk/smileyutility/metadirectives.py
A book/trunk/smileyutility/overview.pt
A book/trunk/smileyutility/smileys/
A book/trunk/smileyutility/smileys/plain/
A book/trunk/smileyutility/smileys/plain/biggrin.png
A book/trunk/smileyutility/smileys/plain/confused.png
A book/trunk/smileyutility/smileys/plain/cool.png
A book/trunk/smileyutility/smileys/plain/oh.png
A book/trunk/smileyutility/smileys/plain/sad.png
A book/trunk/smileyutility/smileys/plain/smile.png
A book/trunk/smileyutility/smileys/plain/tongue.png
A book/trunk/smileyutility/smileys/plain/wink.png
A book/trunk/smileyutility/smileys/yazoo/
A book/trunk/smileyutility/smileys/yazoo/biggrin.png
A book/trunk/smileyutility/smileys/yazoo/confused.png
A book/trunk/smileyutility/smileys/yazoo/cool.png
A book/trunk/smileyutility/smileys/yazoo/oh.png
A book/trunk/smileyutility/smileys/yazoo/sad.png
A book/trunk/smileyutility/smileys/yazoo/smile.png
A book/trunk/smileyutility/smileys/yazoo/tongue.png
A book/trunk/smileyutility/smileys/yazoo/wink.png
A book/trunk/smileyutility/tests/
A book/trunk/smileyutility/tests/__init__.py
A book/trunk/smileyutility/tests/smiley.zcml
A book/trunk/smileyutility/tests/test_directives.py
A book/trunk/smileyutility/tests/test_doc.py
-=-
Added: book/trunk/smileyutility/__init__.py
===================================================================
--- book/trunk/smileyutility/__init__.py 2004-08-21 18:16:23 UTC (rev 27212)
+++ book/trunk/smileyutility/__init__.py 2004-08-21 18:16:50 UTC (rev 27213)
@@ -0,0 +1,97 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""Smiley Themes
+
+Here is an example:
+
+ First we need to prepare the system by creating and registering some themes.
+
+ >>> from zope.publisher.browser import TestRequest
+ >>> from zope.app.tests import ztapi
+
+ >>> import globaltheme
+
+ >>> theme = globaltheme.GlobalSmileyTheme()
+ >>> theme.provideSmiley(':-)', '++resource++plain__smile.png')
+ >>> theme.provideSmiley(';-)', '++resource++plain__wink.png')
+ >>> ztapi.provideUtility(ISmileyTheme, theme, 'plain')
+ >>> globaltheme.declareDefaultSmileyTheme('plain')
+
+ >>> theme = globaltheme.GlobalSmileyTheme()
+ >>> theme.provideSmiley(':-]', '++resource++square__smile.png')
+ >>> theme.provideSmiley(';-]', '++resource++square__wink.png')
+ >>> ztapi.provideUtility(ISmileyTheme, theme, 'square')
+
+ Now we can test the API calls.
+
+ >>> getSmiley(':-)', TestRequest(), 'plain')
+ '/++resource++plain__smile.png'
+ >>> getSmiley(':-)', TestRequest())
+ '/++resource++plain__smile.png'
+ >>> getSmiley(':-)', TestRequest(), 'square')
+ Traceback (most recent call last):
+ ...
+ ComponentLookupError: 'Smiley not found.'
+ >>> getSmiley(':-]', TestRequest())
+ Traceback (most recent call last):
+ ...
+ ComponentLookupError: 'Smiley not found.'
+
+ >>> querySmiley(':-)', TestRequest(), 'plain')
+ '/++resource++plain__smile.png'
+ >>> querySmiley(':-)', TestRequest())
+ '/++resource++plain__smile.png'
+ >>> querySmiley(':-)', TestRequest(), 'square') is None
+ True
+ >>> querySmiley(':-]', TestRequest()) is None
+ True
+
+ >>> themes = getSmileyThemes()
+ >>> themes.sort()
+ >>> themes
+ [u'plain', u'square']
+
+ >>> map = getSmileysMapping(TestRequest(), 'plain')
+ >>> map = map.items()
+ >>> map.sort()
+ >>> import pprint
+ >>> pprint.pprint(map)
+ [(':-)', '/++resource++plain__smile.png'),
+ (';-)', '/++resource++plain__wink.png')]
+
+$Id$
+"""
+__docformat__ = 'restructuredtext'
+
+from zope.app import zapi
+
+from interfaces import ISmileyTheme
+
+def getSmiley(text, request, theme='default'):
+ theme = zapi.getUtility(ISmileyTheme, theme)
+ return theme.getSmiley(text, request)
+
+def querySmiley(text, request, theme='default', default=None):
+ theme = zapi.queryUtility(ISmileyTheme, theme)
+ if theme is None:
+ return default
+ return theme.querySmiley(text, request, default)
+
+def getSmileyThemes():
+ return [name for name, util in zapi.getUtilitiesFor(ISmileyTheme)
+ if name != 'default']
+
+def getSmileysMapping(request, theme='default'):
+ theme = zapi.getUtility(ISmileyTheme, theme)
+ return theme.getSmileysMapping(request)
Added: book/trunk/smileyutility/browser.py
===================================================================
--- book/trunk/smileyutility/browser.py 2004-08-21 18:16:23 UTC (rev 27212)
+++ book/trunk/smileyutility/browser.py 2004-08-21 18:16:50 UTC (rev 27213)
@@ -0,0 +1,33 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""Local Smiley Theme Browser components
+
+$Id$
+"""
+__docformat__ = 'restructuredtext'
+from zope.app import zapi
+
+from localtheme import queryNextTheme, getURL
+
+class Overview(object):
+
+ def getLocalSmileys(self):
+ return [{'text': name, 'url': getURL(smiley, self.request)}
+ for name, smiley in self.context.items()]
+
+ def getAcquiredSmileys(self):
+ theme = queryNextTheme(self.context, zapi.name(self.context))
+ map = theme.getSmileysMapping(self.request)
+ return [{'text': name, 'url': path} for name, path in map.items()
+ if name not in self.context]
Added: book/trunk/smileyutility/configure.zcml
===================================================================
--- book/trunk/smileyutility/configure.zcml 2004-08-21 18:16:23 UTC (rev 27212)
+++ book/trunk/smileyutility/configure.zcml 2004-08-21 18:16:50 UTC (rev 27213)
@@ -0,0 +1,119 @@
+<configure
+ xmlns:zope="http://namespaces.zope.org/zope"
+ xmlns:browser="http://namespaces.zope.org/browser"
+ xmlns="http://namespaces.zope.org/smiley"
+ i18n_domain="smileyutility">
+
+ <theme name="plain">
+ <smiley text=":D" file="./smileys/plain/biggrin.png"/>
+ <smiley text=":-D" file="./smileys/plain/biggrin.png"/>
+ <smiley text=":/" file="./smileys/plain/confused.png"/>
+ <smiley text=":-/" file="./smileys/plain/confused.png"/>
+ <smiley text="8)" file="./smileys/plain/cool.png"/>
+ <smiley text="8-)" file="./smileys/plain/cool.png"/>
+ <smiley text=":o" file="./smileys/plain/oh.png"/>
+ <smiley text=":-o" file="./smileys/plain/oh.png"/>
+ <smiley text=":(" file="./smileys/plain/sad.png"/>
+ <smiley text=":-(" file="./smileys/plain/sad.png"/>
+ <smiley text=":)" file="./smileys/plain/smile.png"/>
+ <smiley text=":-)" file="./smileys/plain/smile.png"/>
+ <smiley text=":P" file="./smileys/plain/tongue.png"/>
+ <smiley text=":-P" file="./smileys/plain/tongue.png"/>
+ <smiley text=";)" file="./smileys/plain/wink.png"/>
+ <smiley text=";-)" file="./smileys/plain/wink.png"/>
+ </theme>
+
+ <theme name="yazoo">
+ <smiley text=":D" file="./smileys/yazoo/biggrin.png"/>
+ <smiley text=":-D" file="./smileys/yazoo/biggrin.png"/>
+ <smiley text=":/" file="./smileys/yazoo/confused.png"/>
+ <smiley text=":-/" file="./smileys/yazoo/confused.png"/>
+ <smiley text="8)" file="./smileys/yazoo/cool.png"/>
+ <smiley text="8-)" file="./smileys/yazoo/cool.png"/>
+ <smiley text=":o" file="./smileys/yazoo/oh.png"/>
+ <smiley text=":-o" file="./smileys/yazoo/oh.png"/>
+ <smiley text=":(" file="./smileys/yazoo/sad.png"/>
+ <smiley text=":-(" file="./smileys/yazoo/sad.png"/>
+ <smiley text=":)" file="./smileys/yazoo/smile.png"/>
+ <smiley text=":-)" file="./smileys/yazoo/smile.png"/>
+ <smiley text=":P" file="./smileys/yazoo/tongue.png"/>
+ <smiley text=":-P" file="./smileys/yazoo/tongue.png"/>
+ <smiley text=";)" file="./smileys/yazoo/wink.png"/>
+ <smiley text=";-)" file="./smileys/yazoo/wink.png"/>
+ </theme>
+
+ <defaultTheme name="plain" />
+
+
+ <zope:content class=".localtheme.SmileyTheme">
+ <zope:factory
+ id="book.smileyutility.SmileyTheme"
+ title="Smiley Theme"
+ description="A Smiley Theme"
+ />
+ <zope:implements
+ interface="zope.app.utility.interfaces.ILocalUtility"
+ />
+ <zope:implements
+ interface="zope.app.container.interfaces.IContentContainer"
+ />
+ <zope:implements
+ interface="zope.app.annotation.interfaces.IAttributeAnnotatable"
+ />
+ <zope:allow
+ interface="zope.app.container.interfaces.IReadContainer"
+ />
+ <zope:require
+ permission="zope.ManageServices"
+ interface="zope.app.container.interfaces.IWriteContainer"
+ />
+ <zope:require
+ permission="zope.ManageServices"
+ interface=".interfaces.ISmileyTheme"
+ set_schema=".interfaces.ISmileyTheme"
+ />
+ </zope:content>
+
+ <zope:content class=".localtheme.Smiley">
+ <zope:require
+ like_class="zope.app.file.image.Image"
+ />
+ </zope:content>
+
+ <browser:tool
+ interface=".interfaces.ISmileyTheme"
+ title="Smiley Themes"
+ description="Smiley Themes allow you to convert text-based to icon-based
+ smileys."
+ />
+
+ <browser:addMenuItem
+ class=".localtheme.Smiley"
+ title="Smiley"
+ description="A Smiley"
+ permission="zope.ManageServices"
+ />
+
+ <browser:addMenuItem
+ class=".localtheme.SmileyTheme"
+ title="Smiley Theme"
+ description="A Smiley Theme"
+ permission="zope.ManageServices"
+ />
+
+ <browser:containerViews
+ for=".localtheme.SmileyTheme"
+ index="book.messageboard.View"
+ contents="zope.ManageServices"
+ add="zope.ManageServices"
+ />
+
+ <browser:page
+ name="overview.html"
+ menu="zmi_views" title="Overview"
+ for=".localtheme.SmileyTheme"
+ permission="zope.ManageServices"
+ class=".browser.Overview"
+ template="overview.pt" />
+
+</configure>
Added: book/trunk/smileyutility/globaltheme.py
===================================================================
--- book/trunk/smileyutility/globaltheme.py 2004-08-21 18:16:23 UTC (rev 27212)
+++ book/trunk/smileyutility/globaltheme.py 2004-08-21 18:16:50 UTC (rev 27213)
@@ -0,0 +1,111 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""Global Smiley Theme Implementation
+
+$Id$
+"""
+__docformat__ = 'restructuredtext'
+from zope.component.exceptions import ComponentLookupError
+from zope.interface import implements
+
+from zope.app import zapi
+from zope.app.traversing.interfaces import IContainmentRoot
+
+from interfaces import ISmileyTheme, IGlobalSmileyTheme
+
+class Root(object):
+ implements(IContainmentRoot)
+
+def getRootURL(request):
+ return str(zapi.getView(Root(), 'absolute_url', request))
+
+
+class GlobalSmileyTheme(object):
+ """A filesystem based smiley theme.
+
+ Let's make sure that the global theme implementation actually fulfills the
+ `ISmileyTheme` API.
+
+ >>> from zope.interface.verify import verifyClass
+ >>> verifyClass(IGlobalSmileyTheme, GlobalSmileyTheme)
+ True
+
+ Initialize the theme and add a couple of smileys.
+
+ >>> theme = GlobalSmileyTheme()
+ >>> theme.provideSmiley(':-)', '++resource++plain__smile.png')
+ >>> theme.provideSmiley(';-)', '++resource++plain__wink.png')
+
+ Let's try to get a smiley out of the registry.
+
+ >>> from zope.publisher.browser import TestRequest
+
+ >>> theme.getSmiley(':-)', TestRequest())
+ '/++resource++plain__smile.png'
+ >>> theme.getSmiley(':-(', TestRequest())
+ Traceback (most recent call last):
+ ...
+ ComponentLookupError: 'Smiley not found.'
+ >>> theme.querySmiley(';-)', TestRequest())
+ '/++resource++plain__wink.png'
+ >>> theme.querySmiley(';-(', TestRequest()) is None
+ True
+
+ And finally we's like to get a dictionary of all smileys.
+
+ >>> map = theme.getSmileysMapping(TestRequest())
+ >>> len(map)
+ 2
+ >>> map[':-)']
+ '/++resource++plain__smile.png'
+ >>> map[';-)']
+ '/++resource++plain__wink.png'
+ """
+ implements(IGlobalSmileyTheme)
+
+ def __init__(self):
+ self.__smileys = {}
+
+ def getSmiley(self, text, request):
+ "See book.smileyutility.interfaces.ISmileyTheme"
+ smiley = self.querySmiley(text, request)
+ if smiley is None:
+ raise ComponentLookupError, 'Smiley not found.'
+ return smiley
+
+ def querySmiley(self, text, request, default=None):
+ "See book.smileyutility.interfaces.ISmileyTheme"
+ if self.__smileys.get(text) is None:
+ return default
+ return getRootURL(request) + '/' + self.__smileys[text]
+
+ def getSmileysMapping(self, request):
+ "See book.smileyutility.interfaces.ISmileyTheme"
+ smileys = self.__smileys.copy()
+ root_url = getRootURL(request)
+ for name, smiley in smileys.items():
+ smileys[name] = root_url + '/' + smiley
+ return smileys
+
+ def provideSmiley(self, text, smiley_path):
+ "See book.smileyutility.interfaces.IGlobalSmileyTheme"
+ self.__smileys[text] = smiley_path
+
+
+def declareDefaultSmileyTheme(name):
+ """Declare the default smiley theme."""
+ utilities = zapi.getService(zapi.servicenames.Utilities)
+ theme = zapi.getUtility(ISmileyTheme, name)
+ # register the utility simply without a name
+ utilities.provideUtility(ISmileyTheme, theme, 'default')
Added: book/trunk/smileyutility/interfaces.py
===================================================================
--- book/trunk/smileyutility/interfaces.py 2004-08-21 18:16:23 UTC (rev 27212)
+++ book/trunk/smileyutility/interfaces.py 2004-08-21 18:16:50 UTC (rev 27213)
@@ -0,0 +1,73 @@
+##############################################################################
+#
+# Copyright (c) 2003, 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.
+#
+##############################################################################
+"""Smiley Utility interfaces
+
+$Id$
+"""
+from zope.interface import Interface
+from zope.schema import Field
+
+from zope.app.container.constraints import ContainerTypesConstraint
+from zope.app.container.constraints import ItemTypePrecondition
+from zope.app.container.interfaces import IContained, IContainer
+from zope.app.file.interfaces import IImage
+
+
+class ISmileyTheme(Interface):
+ """A theme is a collection of smileys having a stylistic theme.
+
+ Themes are intened to be implemented as named utilities, which will be
+ available via a local smiley service.
+ """
+
+ def getSmiley(text, request):
+ """Returns a smiley for the given text and theme.
+
+ If no smiley was found, a ComponentLookupError should be raised.
+ """
+
+ def querySmiley(text, request, default=None):
+ """Returns a smiley for the given text and theme.
+
+ If no smiley was found, the default value is returned.
+ """
+
+ def getSmileysMapping(request):
+ """Return a mapping of text to URL.
+
+ This is incredibly useful when actually attempting to substitute the
+ smiley texts with a URL.
+ """
+
+
+class IGlobalSmileyTheme(ISmileyTheme):
+ """A global smiley theme that also allows managament of smileys."""
+
+ def provideSmiley(text, smiley_path):
+ """Provide a smiley for the utility."""
+
+
+class ISmiley(IImage):
+ """A smiley is just a glorified image"""
+ __parent__ = Field(
+ constraint = ContainerTypesConstraint(ISmileyTheme))
+
+
+class ILocalSmileyTheme(ISmileyTheme, IContainer):
+ """A local smiley themes that manages its smileys via the container API"""
+
+ def __setitem__(name, object):
+ """Add a IMessage object."""
+
+ __setitem__.precondition = ItemTypePrecondition(ISmiley)
Added: book/trunk/smileyutility/localtheme.py
===================================================================
--- book/trunk/smileyutility/localtheme.py 2004-08-21 18:16:23 UTC (rev 27212)
+++ book/trunk/smileyutility/localtheme.py 2004-08-21 18:16:50 UTC (rev 27213)
@@ -0,0 +1,173 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""Local Smiley Theme Implementation
+
+$Id$
+"""
+__docformat__ = 'restructuredtext'
+from zope.component.exceptions import ComponentLookupError
+from zope.interface import implements
+
+from zope.app import zapi
+from zope.app.container.btree import BTreeContainer
+from zope.app.component.localservice import getNextService
+from zope.app.file.image import Image
+
+from interfaces import ISmileyTheme, ISmiley, ILocalSmileyTheme
+
+class Smiley(Image):
+ implements(ISmiley)
+
+class SmileyTheme(BTreeContainer):
+ """A local smiley theme implementation.
+
+ >>> import os
+ >>> from zope.app.tests import setup
+ >>> from zope.app.utility.utility import LocalUtilityService
+ >>> import book.smileyutility
+ >>> site = setup.placefulSetUp()
+ >>> rootFolder = setup.buildSampleFolderTree()
+
+ Setup a simple function to add local smileys to a theme.
+
+ >>> def addSmiley(theme, text, filename):
+ ... base_dir = os.path.dirname(book.smileyutility.__file__)
+ ... filename = os.path.join(base_dir, filename)
+ ... theme[text] = Smiley(open(filename, 'r'))
+
+ Create components in root folder
+
+ >>> site = setup.createServiceManager(rootFolder)
+ >>> utils = setup.addService(site, zapi.servicenames.Utilities,
+ ... LocalUtilityService())
+ >>> theme = SmileyTheme()
+ >>> addSmiley(theme, ':)', 'smileys/plain/smile.png')
+ >>> addSmiley(theme, ':(', 'smileys/plain/sad.png')
+ >>> util = setup.addUtility(site, 'plain', ISmileyTheme, theme)
+
+ Create components in `folder1`
+
+ >>> site = setup.createServiceManager(rootFolder['folder1'])
+ >>> utils = setup.addService(site, zapi.servicenames.Utilities,
+ ... LocalUtilityService())
+ >>> theme = SmileyTheme()
+ >>> addSmiley(theme, ':)', 'smileys/plain/biggrin.png')
+ >>> addSmiley(theme, '8)', 'smileys/plain/cool.png')
+ >>> util = setup.addUtility(site, 'plain', ISmileyTheme, theme)
+
+ Now test the single smiley accessor methods
+
+ >>> from zope.publisher.browser import TestRequest
+ >>> from zope.app.component.localservice import setSite
+ >>> from book.smileyutility import getSmiley, querySmiley
+
+ >>> setSite(rootFolder)
+ >>> getSmiley(':)', TestRequest(), 'plain')
+ 'http://127.0.0.1/++etc++site/default/plain/%3A%29'
+ >>> getSmiley(':(', TestRequest(), 'plain')
+ 'http://127.0.0.1/++etc++site/default/plain/%3A%28'
+ >>> getSmiley('8)', TestRequest(), 'plain')
+ Traceback (most recent call last):
+ ...
+ ComponentLookupError: '8)'
+ >>> querySmiley('8)', TestRequest(), 'plain', 'nothing')
+ 'nothing'
+
+ >>> setSite(rootFolder['folder1'])
+ >>> getSmiley(':)', TestRequest(), 'plain')
+ 'http://127.0.0.1/folder1/++etc++site/default/plain/%3A%29'
+ >>> getSmiley(':(', TestRequest(), 'plain')
+ 'http://127.0.0.1/++etc++site/default/plain/%3A%28'
+ >>> getSmiley('8)', TestRequest(), 'plain')
+ 'http://127.0.0.1/folder1/++etc++site/default/plain/8%29'
+ >>> getSmiley(':|', TestRequest(), 'plain')
+ Traceback (most recent call last):
+ ...
+ ComponentLookupError: ':|'
+ >>> querySmiley(':|', TestRequest(), 'plain', 'nothing')
+ 'nothing'
+
+ Let's now test the `getSmileysMapping()` method. To do that we create a
+ small helper method that helps us compare dictionaries.
+
+ >>> from pprint import pprint
+ >>> from book.smileyutility import getSmileysMapping
+ >>> def output(dict):
+ ... items = dict.items()
+ ... items.sort()
+ ... pprint(items)
+
+ >>> setSite(rootFolder)
+ >>> output(getSmileysMapping(TestRequest(), 'plain'))
+ [(u':(', 'http://127.0.0.1/++etc++site/default/plain/%3A%28'),
+ (u':)', 'http://127.0.0.1/++etc++site/default/plain/%3A%29')]
+
+ >>> setSite(rootFolder['folder1'])
+ >>> output(getSmileysMapping(TestRequest(), 'plain'))
+ [(u'8)', 'http://127.0.0.1/folder1/++etc++site/default/plain/8%29'),
+ (u':(', 'http://127.0.0.1/++etc++site/default/plain/%3A%28'),
+ (u':)', 'http://127.0.0.1/folder1/++etc++site/default/plain/%3A%29')]
+ >>> getSmileysMapping(TestRequest(), 'foobar')
+ Traceback (most recent call last):
+ ...
+ ComponentLookupError: \
+(<InterfaceClass book.smileyutility.interfaces.ISmileyTheme>, 'foobar')
+
+ >>> setup.placefulTearDown()
+ """
+ implements(ILocalSmileyTheme)
+
+ def getSmiley(self, text, request):
+ "See book.smileyutility.interfaces.ISmileyTheme"
+ if text not in self:
+ theme = queryNextTheme(self, zapi.name(self))
+ if theme is None:
+ raise ComponentLookupError(text)
+ else:
+ return theme.getSmiley(text, request)
+ return getURL(self[text], request)
+
+ def querySmiley(self, text, request, default=None):
+ "See book.smileyutility.interfaces.ISmileyTheme"
+ if text not in self:
+ theme = queryNextTheme(self, zapi.name(self))
+ if theme is None:
+ return default
+ else:
+ return theme.querySmiley(text, request, default)
+ return getURL(self[text], request)
+
+ def getSmileysMapping(self, request):
+ "See book.smileyutility.interfaces.ISmileyTheme"
+ theme = queryNextTheme(self, zapi.name(self))
+ if theme is None:
+ smileys = {}
+ else:
+ smileys = theme.getSmileysMapping(request)
+
+ for name, smiley in self.items():
+ smileys[name] = getURL(smiley, request)
+
+ return smileys
+
+
+def queryNextTheme(context, name, default=None):
+ """Get the next theme higher up."""
+ utilities = getNextService(context, zapi.servicenames.Utilities)
+ return utilities.queryUtility(ISmileyTheme, name, default)
+
+def getURL(smiley, request):
+ """Get the URL of the smiley."""
+ url = zapi.getView(smiley, 'absolute_url', request=request)
+ return url()
Added: book/trunk/smileyutility/meta.zcml
===================================================================
--- book/trunk/smileyutility/meta.zcml 2004-08-21 18:16:23 UTC (rev 27212)
+++ book/trunk/smileyutility/meta.zcml 2004-08-21 18:16:50 UTC (rev 27213)
@@ -0,0 +1,28 @@
+<configure xmlns:meta="http://namespaces.zope.org/meta">
+
+ <meta:directives namespace="http://namespaces.zope.org/smiley">
+
+ <meta:complexDirective
+ name="theme"
+ schema=".metadirectives.IThemeDirective"
+ handler=".metaconfigure.theme">
+
+ <meta:subdirective
+ name="smiley"
+ schema=".metadirectives.ISmileySubdirective" />
+
+ </meta:complexDirective>
+
+ <meta:directive
+ name="smiley"
+ schema=".metadirectives.ISmileyDirective"
+ handler=".metaconfigure.smiley" />
+
+ <meta:directive
+ name="defaultTheme"
+ schema=".metadirectives.IDefaultThemeDirective"
+ handler=".metaconfigure.defaultTheme" />
+
+ </meta:directives>
+
+</configure>
Added: book/trunk/smileyutility/metaconfigure.py
===================================================================
--- book/trunk/smileyutility/metaconfigure.py 2004-08-21 18:16:23 UTC (rev 27212)
+++ book/trunk/smileyutility/metaconfigure.py 2004-08-21 18:16:50 UTC (rev 27213)
@@ -0,0 +1,70 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""Smiley Configuration code
+
+$Id: metaconfigure.py,v 1.1 2003/08/22 21:27:33 srichter Exp $
+"""
+import os
+
+from zope.app import zapi
+from zope.app.component.metaconfigure import utility
+from zope.app.publisher.browser.resourcemeta import resource
+
+from interfaces import ISmileyTheme
+from globaltheme import GlobalSmileyTheme, declareDefaultSmileyTheme
+
+__registered_resources = []
+
+def registerSmiley(text, path, theme):
+ theme = zapi.queryUtility(ISmileyTheme, theme)
+ theme.provideSmiley(text, path)
+
+
+class theme(object):
+
+ def __init__(self, _context, name):
+ self.name = name
+ utility(_context, ISmileyTheme,
+ factory=GlobalSmileyTheme, name=name)
+
+ def smiley(self, _context, text, file):
+ return smiley(_context, text, file, self.name)
+
+ def __call__(self):
+ return
+
+
+def smiley(_context, text, file, theme):
+
+ name = theme + '__' + os.path.split(file)[1]
+ path = '/++resource++' + name
+
+ if name not in __registered_resources:
+ resource(_context, name, image=file)
+ __registered_resources.append(name)
+
+ _context.action(
+ discriminator = ('smiley', theme, text),
+ callable = registerSmiley,
+ args = (text, path, theme),
+ )
+
+
+def defaultTheme(_context, name=None):
+ _context.action(
+ discriminator = ('smiley', 'defaultTheme',),
+ callable = declareDefaultSmileyTheme,
+ args = (name,),
+ )
+
Added: book/trunk/smileyutility/metadirectives.py
===================================================================
--- book/trunk/smileyutility/metadirectives.py 2004-08-21 18:16:23 UTC (rev 27212)
+++ book/trunk/smileyutility/metadirectives.py 2004-08-21 18:16:50 UTC (rev 27213)
@@ -0,0 +1,56 @@
+##############################################################################
+#
+# Copyright (c) 2003, 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.
+#
+##############################################################################
+"""Smiley Configuration interfaces
+
+$Id: metadirectives.py,v 1.1 2003/08/22 21:27:33 srichter Exp $
+"""
+from zope.interface import Interface
+from zope.configuration.fields import Path
+from zope.schema import TextLine
+
+class IThemeDirective(Interface):
+ """Define a new theme."""
+
+ name = TextLine(
+ title=u"Theme Name",
+ description=u"The name of the theme.",
+ default=None,
+ required=False)
+
+class ISmileySubdirective(Interface):
+ """This directive adds a new smiley using the theme information of the
+ complex smileys directive."""
+
+ text = TextLine(
+ title=u"Smiley Text",
+ description=u"The text that represents the smiley, i.e. ':-)'",
+ required=True)
+
+ file = Path(
+ title=u"Image file",
+ description=u"Path to the image that represents the smiley.",
+ required=True)
+
+class ISmileyDirective(ISmileySubdirective):
+ """This is a standalone directive registering a smiley for a certain
+ theme."""
+
+ theme = TextLine(
+ title=u"Theme",
+ description=u"The theme the smiley belongs to.",
+ default=None,
+ required=False)
+
+class IDefaultThemeDirective(IThemeDirective):
+ """Specify the default theme."""
Added: book/trunk/smileyutility/overview.pt
===================================================================
--- book/trunk/smileyutility/overview.pt 2004-08-21 18:16:23 UTC (rev 27212)
+++ book/trunk/smileyutility/overview.pt 2004-08-21 18:16:50 UTC (rev 27213)
@@ -0,0 +1,27 @@
+<html metal:use-macro="views/standard_macros/view">
+<head>
+ <title metal:fill-slot="title"
+ i18n:translate="">Smiley Theme</title>
+</head>
+<body>
+<div metal:fill-slot="body">
+
+ <h2 i18n:translate="">Local Smileys</h2>
+ <ul>
+ <li tal:repeat="smiley view/getLocalSmileys">
+ <b tal:content="smiley/text"/> →
+ <img src="" tal:attributes="src smiley/url"/>
+ </li>
+ </ul>
+
+ <h2 i18n:translate="">Acquired Smileys</h2>
+ <ul>
+ <li tal:repeat="smiley view/getAcquiredSmileys">
+ <b tal:content="smiley/text"/> →
+ <img src="" tal:attributes="src smiley/url"/>
+ </li>
+ </ul>
+
+</div>
+</body>
+</html>
Added: book/trunk/smileyutility/smileys/plain/biggrin.png
===================================================================
(Binary files differ)
Property changes on: book/trunk/smileyutility/smileys/plain/biggrin.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: book/trunk/smileyutility/smileys/plain/confused.png
===================================================================
(Binary files differ)
Property changes on: book/trunk/smileyutility/smileys/plain/confused.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: book/trunk/smileyutility/smileys/plain/cool.png
===================================================================
(Binary files differ)
Property changes on: book/trunk/smileyutility/smileys/plain/cool.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: book/trunk/smileyutility/smileys/plain/oh.png
===================================================================
(Binary files differ)
Property changes on: book/trunk/smileyutility/smileys/plain/oh.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: book/trunk/smileyutility/smileys/plain/sad.png
===================================================================
(Binary files differ)
Property changes on: book/trunk/smileyutility/smileys/plain/sad.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: book/trunk/smileyutility/smileys/plain/smile.png
===================================================================
(Binary files differ)
Property changes on: book/trunk/smileyutility/smileys/plain/smile.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: book/trunk/smileyutility/smileys/plain/tongue.png
===================================================================
(Binary files differ)
Property changes on: book/trunk/smileyutility/smileys/plain/tongue.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: book/trunk/smileyutility/smileys/plain/wink.png
===================================================================
(Binary files differ)
Property changes on: book/trunk/smileyutility/smileys/plain/wink.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: book/trunk/smileyutility/smileys/yazoo/biggrin.png
===================================================================
(Binary files differ)
Property changes on: book/trunk/smileyutility/smileys/yazoo/biggrin.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: book/trunk/smileyutility/smileys/yazoo/confused.png
===================================================================
(Binary files differ)
Property changes on: book/trunk/smileyutility/smileys/yazoo/confused.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: book/trunk/smileyutility/smileys/yazoo/cool.png
===================================================================
(Binary files differ)
Property changes on: book/trunk/smileyutility/smileys/yazoo/cool.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: book/trunk/smileyutility/smileys/yazoo/oh.png
===================================================================
(Binary files differ)
Property changes on: book/trunk/smileyutility/smileys/yazoo/oh.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: book/trunk/smileyutility/smileys/yazoo/sad.png
===================================================================
(Binary files differ)
Property changes on: book/trunk/smileyutility/smileys/yazoo/sad.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: book/trunk/smileyutility/smileys/yazoo/smile.png
===================================================================
(Binary files differ)
Property changes on: book/trunk/smileyutility/smileys/yazoo/smile.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: book/trunk/smileyutility/smileys/yazoo/tongue.png
===================================================================
(Binary files differ)
Property changes on: book/trunk/smileyutility/smileys/yazoo/tongue.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: book/trunk/smileyutility/smileys/yazoo/wink.png
===================================================================
(Binary files differ)
Property changes on: book/trunk/smileyutility/smileys/yazoo/wink.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: book/trunk/smileyutility/tests/__init__.py
===================================================================
Added: book/trunk/smileyutility/tests/smiley.zcml
===================================================================
--- book/trunk/smileyutility/tests/smiley.zcml 2004-08-21 18:16:23 UTC (rev 27212)
+++ book/trunk/smileyutility/tests/smiley.zcml 2004-08-21 18:16:50 UTC (rev 27213)
@@ -0,0 +1,21 @@
+<configure
+ xmlns:zope="http://namespaces.zope.org/zope"
+ xmlns="http://namespaces.zope.org/smiley">
+
+ <zope:include package="book.smileyutility" file="meta.zcml" />
+
+ <theme name="yazoo">
+ <smiley text=":(" file="../smileys/yazoo/sad.png"/>
+ <smiley text=":)" file="../smileys/yazoo/smile.png"/>
+ </theme>
+
+ <theme name="plain" />
+
+ <smiley
+ theme="plain"
+ text=":("
+ file="../smileys/yazoo/sad.png"/>
+
+ <defaultTheme name="plain" />
+
+</configure>
Added: book/trunk/smileyutility/tests/test_directives.py
===================================================================
--- book/trunk/smileyutility/tests/test_directives.py 2004-08-21 18:16:23 UTC (rev 27212)
+++ book/trunk/smileyutility/tests/test_directives.py 2004-08-21 18:16:50 UTC (rev 27213)
@@ -0,0 +1,58 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""Test the workflow ZCML namespace directives.
+
+$Id: test_directives.py,v 1.1 2003/08/22 21:27:36 srichter Exp $
+"""
+import unittest
+
+from zope.app import zapi
+from zope.app.tests.placelesssetup import PlacelessSetup
+from zope.configuration import xmlconfig
+
+from book.smileyutility import tests
+from book.smileyutility.interfaces import ISmileyTheme
+
+class DirectivesTest(PlacelessSetup, unittest.TestCase):
+
+ def setUp(self):
+ super(DirectivesTest, self).setUp()
+ self.context = xmlconfig.file("smiley.zcml", tests)
+
+ def test_SmileyDirectives(self):
+ self.assertEqual(
+ zapi.getUtility(ISmileyTheme,
+ 'default')._GlobalSmileyTheme__smileys,
+ {u':(': u'/++resource++plain__sad.png'})
+ self.assertEqual(
+ zapi.getUtility(ISmileyTheme,
+ 'plain')._GlobalSmileyTheme__smileys,
+ {u':(': u'/++resource++plain__sad.png'})
+ self.assertEqual(
+ zapi.getUtility(ISmileyTheme,
+ 'yazoo')._GlobalSmileyTheme__smileys,
+ {u':)': u'/++resource++yazoo__smile.png',
+ u':(': u'/++resource++yazoo__sad.png'})
+
+ def test_defaultTheme(self):
+ self.assertEqual(zapi.getUtility(ISmileyTheme, 'default'),
+ zapi.getUtility(ISmileyTheme, 'plain'))
+
+def test_suite():
+ return unittest.TestSuite((
+ unittest.makeSuite(DirectivesTest),
+ ))
+
+if __name__ == '__main__':
+ unittest.main()
Added: book/trunk/smileyutility/tests/test_doc.py
===================================================================
--- book/trunk/smileyutility/tests/test_doc.py 2004-08-21 18:16:23 UTC (rev 27212)
+++ book/trunk/smileyutility/tests/test_doc.py 2004-08-21 18:16:50 UTC (rev 27213)
@@ -0,0 +1,46 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""Test the workflow ZCML namespace directives.
+
+$Id: test_globalservice.py,v 1.1 2003/08/22 21:27:36 srichter Exp $
+"""
+import unittest
+
+from zope.interface import Interface
+from zope.testing.doctestunit import DocTestSuite
+
+from zope.app.tests import ztapi, placelesssetup
+
+class AbsoluteURL:
+ def __init__(self, context, request):
+ pass
+ def __str__(self):
+ return ''
+
+def setUp():
+ placelesssetup.setUp()
+ ztapi.browserView(Interface, 'absolute_url', AbsoluteURL)
+
+
+def test_suite():
+ return unittest.TestSuite((
+ DocTestSuite('book.smileyutility',
+ setUp=setUp, tearDown=placelesssetup.tearDown),
+ DocTestSuite('book.smileyutility.globaltheme',
+ setUp=setUp, tearDown=placelesssetup.tearDown),
+ DocTestSuite('book.smileyutility.localtheme'),
+ ))
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
More information about the Zope-CVS
mailing list