[Checkins] SVN: zope.viewlet/trunk/ - Bugfix,
implemented missing __contains__ method defined from
IReadMapping in viewlet manager
Roger Ineichen
roger at projekt01.ch
Wed Dec 26 11:01:24 EST 2007
Log message for revision 82455:
- Bugfix, implemented missing __contains__ method defined from IReadMapping in viewlet manager
- Implemented additional viewlet manager base classes offering weight ordered sorting and conditional filtering
- Implemented unit tests
- Update Changes.txt
Changed:
U zope.viewlet/trunk/CHANGES.txt
U zope.viewlet/trunk/src/zope/viewlet/README.txt
U zope.viewlet/trunk/src/zope/viewlet/manager.py
-=-
Modified: zope.viewlet/trunk/CHANGES.txt
===================================================================
--- zope.viewlet/trunk/CHANGES.txt 2007-12-26 15:36:41 UTC (rev 82454)
+++ zope.viewlet/trunk/CHANGES.txt 2007-12-26 16:01:23 UTC (rev 82455)
@@ -2,6 +2,16 @@
CHANGES
=======
+3.5.0dev (unreleased)
+------------------
+
+- bugfix, implemented missing __contains__ method in IViewletManager
+
+- implemented additional viewlet managers offering weight ordered sorting
+
+- implemented additional viewlet managers offering conditional filtering
+
+
3.4.0 (2007-10-10)
------------------
Modified: zope.viewlet/trunk/src/zope/viewlet/README.txt
===================================================================
--- zope.viewlet/trunk/src/zope/viewlet/README.txt 2007-12-26 15:36:41 UTC (rev 82454)
+++ zope.viewlet/trunk/src/zope/viewlet/README.txt 2007-12-26 16:01:23 UTC (rev 82455)
@@ -185,6 +185,15 @@
>>> leftColumn.get('weather')
<WeatherBox ...>
+The viewlet manager also provides the __contains__ method defined in
+IReadMapping:
+
+ >>> 'weather' in leftColumn
+ True
+
+ >>> 'unknown' in leftColumn
+ False
+
If the viewlet is not found, then the expected behavior is provided:
>>> leftColumn['stock']
@@ -261,14 +270,219 @@
</div>
+WeightOrderedViewletManager
+---------------------------
+
+The weight ordered viewlet manager offers ordering viewlets by a additional
+weight argument. Viewlets which doesn't provide a weight attribute will get
+a weight of 0 (zero).
+
+Let's define a new column:
+
+ >>> class IWeightedColumn(interfaces.IViewletManager):
+ ... """Column with weighted viewlet manager."""
+
+First register a template for the weight ordered viewlet manager:
+
+ >>> weightedColTemplate = os.path.join(temp_dir, 'weightedColTemplate.pt')
+ >>> open(weightedColTemplate, 'w').write('''
+ ... <div class="weighted-column">
+ ... <tal:block repeat="viewlet options/viewlets"
+ ... replace="structure viewlet/render" />
+ ... </div>
+ ... ''')
+
+And create a new weight ordered viewlet manager:
+
+ >>> from zope.viewlet.manager import WeightOrderedViewletManager
+ >>> WeightedColumn = manager.ViewletManager(
+ ... 'left', IWeightedColumn, bases=(WeightOrderedViewletManager,),
+ ... template=weightedColTemplate)
+ >>> weightedColumn = WeightedColumn(content, request, view)
+
+Let's create some viewlets:
+
+ >>> from zope.viewlet import viewlet
+ >>> class FirstViewlet(viewlet.ViewletBase):
+ ...
+ ... weight = 1
+ ...
+ ... def render(self):
+ ... return u'<div>first</div>'
+
+ >>> class SecondViewlet(viewlet.ViewletBase):
+ ...
+ ... weight = 2
+ ...
+ ... def render(self):
+ ... return u'<div>second</div>'
+
+ >>> class ThirdViewlet(viewlet.ViewletBase):
+ ...
+ ... weight = 3
+ ...
+ ... def render(self):
+ ... return u'<div>third</div>'
+
+ >>> class UnWeightedViewlet(viewlet.ViewletBase):
+ ...
+ ... def render(self):
+ ... return u'<div>unweighted</div>'
+
+ >>> defineChecker(FirstViewlet, viewletChecker)
+ >>> defineChecker(SecondViewlet, viewletChecker)
+ >>> defineChecker(ThirdViewlet, viewletChecker)
+ >>> defineChecker(UnWeightedViewlet, viewletChecker)
+
+ >>> zope.component.provideAdapter(
+ ... ThirdViewlet,
+ ... (zope.interface.Interface, IDefaultBrowserLayer,
+ ... IBrowserView, IWeightedColumn),
+ ... interfaces.IViewlet, name='third')
+
+ >>> zope.component.provideAdapter(
+ ... FirstViewlet,
+ ... (zope.interface.Interface, IDefaultBrowserLayer,
+ ... IBrowserView, IWeightedColumn),
+ ... interfaces.IViewlet, name='first')
+
+ >>> zope.component.provideAdapter(
+ ... SecondViewlet,
+ ... (zope.interface.Interface, IDefaultBrowserLayer,
+ ... IBrowserView, IWeightedColumn),
+ ... interfaces.IViewlet, name='second')
+
+ >>> zope.component.provideAdapter(
+ ... UnWeightedViewlet,
+ ... (zope.interface.Interface, IDefaultBrowserLayer,
+ ... IBrowserView, IWeightedColumn),
+ ... interfaces.IViewlet, name='unweighted')
+
+And check the order:
+
+ >>> weightedColumn.update()
+ >>> print weightedColumn.render().strip()
+ <div class="weighted-column">
+ <div>unweighted</div>
+ <div>first</div>
+ <div>second</div>
+ <div>third</div>
+ </div>
+
+
+WeightOrderedViewletManager
+---------------------------
+
+The conditional ordered viewlet manager offers ordering viewlets by a
+additional weight argument and filters by the available attribute if a
+supported by the viewlet. Viewlets which doesn't provide a available attribute
+will not get skiped. The default weight value for vielwets which doesn't
+provide a weight attribute is o (zero).
+
+Let's define a new column:
+
+ >>> class IConditionalColumn(interfaces.IViewletManager):
+ ... """Column with weighted viewlet manager."""
+
+First register a template for the weight ordered viewlet manager:
+
+ >>> conditionalColTemplate = os.path.join(temp_dir,
+ ... 'conditionalColTemplate.pt')
+ >>> open(conditionalColTemplate, 'w').write('''
+ ... <div class="conditional-column">
+ ... <tal:block repeat="viewlet options/viewlets"
+ ... replace="structure viewlet/render" />
+ ... </div>
+ ... ''')
+
+And create a new conditional viewlet manager:
+
+ >>> from zope.viewlet.manager import ConditionalViewletManager
+ >>> ConditionalColumn = manager.ViewletManager(
+ ... 'left', IConditionalColumn, bases=(ConditionalViewletManager,),
+ ... template=conditionalColTemplate)
+ >>> conditionalColumn = ConditionalColumn(content, request, view)
+
+Let's create some viewlets. We also use the previous viewlets supporting no
+weight and or no available attribute:
+
+ >>> from zope.viewlet import viewlet
+ >>> class AvailableViewlet(viewlet.ViewletBase):
+ ...
+ ... weight = 4
+ ...
+ ... available = True
+ ...
+ ... def render(self):
+ ... return u'<div>available</div>'
+
+ >>> class UnAvailableViewlet(viewlet.ViewletBase):
+ ...
+ ... weight = 5
+ ...
+ ... available = False
+ ...
+ ... def render(self):
+ ... return u'<div>not available</div>'
+
+ >>> defineChecker(AvailableViewlet, viewletChecker)
+ >>> defineChecker(UnAvailableViewlet, viewletChecker)
+
+ >>> zope.component.provideAdapter(
+ ... ThirdViewlet,
+ ... (zope.interface.Interface, IDefaultBrowserLayer,
+ ... IBrowserView, IConditionalColumn),
+ ... interfaces.IViewlet, name='third')
+
+ >>> zope.component.provideAdapter(
+ ... FirstViewlet,
+ ... (zope.interface.Interface, IDefaultBrowserLayer,
+ ... IBrowserView, IConditionalColumn),
+ ... interfaces.IViewlet, name='first')
+
+ >>> zope.component.provideAdapter(
+ ... SecondViewlet,
+ ... (zope.interface.Interface, IDefaultBrowserLayer,
+ ... IBrowserView, IConditionalColumn),
+ ... interfaces.IViewlet, name='second')
+
+ >>> zope.component.provideAdapter(
+ ... UnWeightedViewlet,
+ ... (zope.interface.Interface, IDefaultBrowserLayer,
+ ... IBrowserView, IConditionalColumn),
+ ... interfaces.IViewlet, name='unweighted')
+
+ >>> zope.component.provideAdapter(
+ ... AvailableViewlet,
+ ... (zope.interface.Interface, IDefaultBrowserLayer,
+ ... IBrowserView, IConditionalColumn),
+ ... interfaces.IViewlet, name='available')
+
+ >>> zope.component.provideAdapter(
+ ... UnAvailableViewlet,
+ ... (zope.interface.Interface, IDefaultBrowserLayer,
+ ... IBrowserView, IConditionalColumn),
+ ... interfaces.IViewlet, name='unavailable')
+
+And check the order:
+
+ >>> conditionalColumn.update()
+ >>> print conditionalColumn.render().strip()
+ <div class="conditional-column">
+ <div>unweighted</div>
+ <div>first</div>
+ <div>second</div>
+ <div>third</div>
+ <div>available</div>
+ </div>
+
+
Viewlet Base Classes
--------------------
To make the creation of viewlets simpler, a set of useful base classes and
-helper functions are provided:
+helper functions are provided.
- >>> from zope.viewlet import viewlet
-
The first class is a base class that simply defines the constructor:
>>> base = viewlet.ViewletBase('context', 'request', 'view', 'manager')
Modified: zope.viewlet/trunk/src/zope/viewlet/manager.py
===================================================================
--- zope.viewlet/trunk/src/zope/viewlet/manager.py 2007-12-26 15:36:41 UTC (rev 82454)
+++ zope.viewlet/trunk/src/zope/viewlet/manager.py 2007-12-26 16:01:23 UTC (rev 82455)
@@ -41,7 +41,6 @@
self.context = context
self.request = request
-
def __getitem__(self, name):
"""See zope.interface.common.mapping.IReadMapping"""
# Find the viewlet
@@ -72,6 +71,10 @@
zope.security.interfaces.Unauthorized):
return default
+ def __contains__(self, name):
+ """See zope.interface.common.mapping.IReadMapping"""
+ return bool(self.get(name, False))
+
def filter(self, viewlets):
"""Sort out all content providers
@@ -140,3 +143,47 @@
'<ViewletManager providing %s>' % interface.getName(), bases, attrDict)
zope.interface.classImplements(ViewletManager, interface)
return ViewletManager
+
+
+def getWeight((name, viewlet)):
+ try:
+ return int(viewlet.weight)
+ except AttributeError:
+ return 0
+
+
+class WeightOrderedViewletManager(ViewletManagerBase):
+ """Weight ordered viewlet managers."""
+
+ def sort(self, viewlets):
+ return sorted(viewlets, key=getWeight)
+
+ def render(self):
+ """See zope.contentprovider.interfaces.IContentProvider"""
+ # do not render a manager template if no viewlets are avaiable
+ if not self.viewlets:
+ return u''
+ elif self.template:
+ return self.template(viewlets=self.viewlets)
+ else:
+ return u'\n'.join([viewlet.render() for viewlet in self.viewlets])
+
+
+def isAvilable(viewlet):
+ try:
+ return zope.security.canAccess(viewlet, 'render') and viewlet.available
+ except AttributeError:
+ return True
+
+
+class ConditionalViewletManager(WeightOrderedViewletManager):
+ """Conditional weight ordered viewlet managers."""
+
+ def filter(self, viewlets):
+ """Sort out all viewlets which are explicit not available
+
+ ``viewlets`` is a list of tuples of the form (name, viewlet).
+ """
+ return [(name, viewlet) for name, viewlet in viewlets
+ if isAvilable(viewlet)]
+
More information about the Checkins
mailing list