From 3ea664a763e1212ad4a070274a46fc2106a9598d Mon Sep 17 00:00:00 2001 From: helmutm Date: Mon, 31 Oct 2005 15:44:01 +0000 Subject: [PATCH] a whole bunch of work mainly introducing viewlet stuff; and a few renames... git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@646 fd906abe-77d9-0310-91a1-e0d9ade77398 --- browser/README.txt | 11 ++ browser/__init__.py | 29 ++++ browser/pageprovider.py | 77 ++++++++++ browser/skin/configure.zcml | 55 ++++++-- browser/skin/cyberview.txt | 23 +++ browser/skin/index.pt | 44 ++++++ browser/skin/left_slot.pt | 5 +- browser/skin/main.pt | 53 +++++++ browser/skin/view_macros.pt | 1 + browser/skin/viewlet_menu.pt | 2 + ftests.py | 14 ++ lazynamespace/README.txt | 133 ++++++++++++++++++ {lazyvars => lazynamespace}/__init__.py | 0 {lazyvars => lazynamespace}/configure.zcml | 12 +- {lazyvars => lazynamespace}/interfaces.py | 10 +- .../lazynamespace.py | 21 ++- {lazyvars => lazynamespace}/tests.py | 0 lazyvars/README.txt | 72 ---------- tests/test_cybertools.py => tests.py | 5 +- tests/__init__.py | 4 - 20 files changed, 466 insertions(+), 105 deletions(-) create mode 100644 browser/README.txt create mode 100644 browser/pageprovider.py create mode 100644 browser/skin/cyberview.txt create mode 100644 browser/skin/index.pt create mode 100644 browser/skin/main.pt create mode 100644 browser/skin/viewlet_menu.pt create mode 100755 ftests.py create mode 100644 lazynamespace/README.txt rename {lazyvars => lazynamespace}/__init__.py (100%) rename {lazyvars => lazynamespace}/configure.zcml (54%) rename {lazyvars => lazynamespace}/interfaces.py (84%) rename lazyvars/lazyvars.py => lazynamespace/lazynamespace.py (71%) rename {lazyvars => lazynamespace}/tests.py (100%) delete mode 100644 lazyvars/README.txt rename tests/test_cybertools.py => tests.py (89%) delete mode 100644 tests/__init__.py diff --git a/browser/README.txt b/browser/README.txt new file mode 100644 index 0000000..fc2705b --- /dev/null +++ b/browser/README.txt @@ -0,0 +1,11 @@ +Use Content Providers and Viewlets for setting up web pages +=========================================================== + +We first set up a test and working environment: + + >>> from zope.app import zapi + >>> from zope.app.testing import ztapi + >>> from cybertools.browser.pageprovider import BaseView, PageProviderView + >>> from cybertools.browser.pageprovider import PageProvider + + \ No newline at end of file diff --git a/browser/__init__.py b/browser/__init__.py index 4bc90fb..12b99a0 100644 --- a/browser/__init__.py +++ b/browser/__init__.py @@ -1,4 +1,33 @@ +# +# Copyright (c) 2005 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 +# + """ +cybertools browser package. + $Id$ """ +from zope.viewlet.interfaces import IViewletManager + +class ILeft(IViewletManager): + """ Left slot. + """ + +class IBody(IViewletManager): + """ Body (main) content slot. + """ diff --git a/browser/pageprovider.py b/browser/pageprovider.py new file mode 100644 index 0000000..994075c --- /dev/null +++ b/browser/pageprovider.py @@ -0,0 +1,77 @@ +# +# Copyright (c) 2005 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 +# + +""" +cybertools regions. + +$Id$ +""" + +from zope.interface import implements +import zope.component +from zope.app.publisher.interfaces.browser import IBrowserView +from zope.app.publisher.browser import BrowserView +from zope.contentprovider.interfaces import IContentProvider +from zope.viewlet.manager import ViewletManagerBase + + +class BaseView(object): + """ Basic view class using a template and possibly doing some other + setup stuff. + """ + + implements(IBrowserView) + + def __call__(self): + # render the template associated with this view: + return self.index() + + +class PageProviderView(object): + """ Simple view class using a content provider for setting up a page. + """ + + implements(IBrowserView) + + def __call__(self): + context = self.context + request = self.request + name = 'cybertools.pageprovider' + provider = zope.component.queryMultiAdapter( + (context, request, self), IContentProvider, name) + provider.update() + return provider.render() + + +class PageProvider(ViewletManagerBase): + """ Simple implementation that provides a whole page. + """ + + implements(IContentProvider) + + def __init__(self, context, request, view): + self.context = context + self. request = request + self.view = view + self.__parent__ = view + + def update(self): + return ViewletManagerBase.update(self) + + def render(self): + return ViewletManagerBase.render(self) diff --git a/browser/skin/configure.zcml b/browser/skin/configure.zcml index e48d04d..1630fef 100644 --- a/browser/skin/configure.zcml +++ b/browser/skin/configure.zcml @@ -15,10 +15,23 @@ zope.app.zopetop.templates rotterdam default" /> - + layer="cyberview" />--> + + + + @@ -32,21 +45,43 @@ - - + + + + + + >> from zope.app import zapi + >>> from zope.app.testing import ztapi + >>> from zope.app.component import site, interfaces + + >>> from zope.testbrowser import Browser + >>> browser = Browser() + >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw') + +We can now open a page using the CyberView skin: + + >>> browser.addHeader('Accept-Language', 'en-US') + >>> browser.open('http://localhost/++skin++CyberView') + >>> print browser.headers + Status: 200 Ok... + + >>> browser.url + 'http://localhost/++skin++CyberView' + \ No newline at end of file diff --git a/browser/skin/index.pt b/browser/skin/index.pt new file mode 100644 index 0000000..ca50aed --- /dev/null +++ b/browser/skin/index.pt @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + +
 NameTitleCreatedModified
+ + + ID here +    
diff --git a/browser/skin/left_slot.pt b/browser/skin/left_slot.pt index f03026c..a95c61e 100644 --- a/browser/skin/left_slot.pt +++ b/browser/skin/left_slot.pt @@ -2,9 +2,6 @@ Headline
-
- +
Left Slot
diff --git a/browser/skin/main.pt b/browser/skin/main.pt new file mode 100644 index 0000000..02d9344 --- /dev/null +++ b/browser/skin/main.pt @@ -0,0 +1,53 @@ + + + + + + cyberconcepts IT-Consulting + + + + + + +
+ + cyberconcepts IT-Consulting + + + Logged in as user + +
+ + + + + +
+ +
+
+ +
+
+ + + + +
diff --git a/browser/skin/view_macros.pt b/browser/skin/view_macros.pt index becb812..0e87532 100644 --- a/browser/skin/view_macros.pt +++ b/browser/skin/view_macros.pt @@ -42,6 +42,7 @@ --> Here comes the body + diff --git a/browser/skin/viewlet_menu.pt b/browser/skin/viewlet_menu.pt new file mode 100644 index 0000000..35598ba --- /dev/null +++ b/browser/skin/viewlet_menu.pt @@ -0,0 +1,2 @@ +
diff --git a/ftests.py b/ftests.py new file mode 100755 index 0000000..d083c32 --- /dev/null +++ b/ftests.py @@ -0,0 +1,14 @@ +# $Id$ + +import unittest, doctest +from zope.testing.doctestunit import DocFileSuite +from zope.app.testing.functional import FunctionalDocFileSuite + + +def test_suite(): + flags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS + browser = FunctionalDocFileSuite('browser/skin/cyberview.txt', optionflags=flags) + return unittest.TestSuite((browser,)) + +if __name__ == '__main__': + unittest.main(defaultTest='test_suite') diff --git a/lazynamespace/README.txt b/lazynamespace/README.txt new file mode 100644 index 0000000..91302a6 --- /dev/null +++ b/lazynamespace/README.txt @@ -0,0 +1,133 @@ +Setting up and using LazyNamespace objects +========================================== + +A LazyNamespace contains variables that are only calculated when really +needed, and these are calculated only once during the lifetime of the +LazyNamespace objects they live in. + +This is especially useful when rendering web pages as during this +rendering often the same data are used again and again, whereas you don't +know at the beginning of the rendering process which data you will really +need. + +We first need a function that will be used to provide a value +for a variable we want to use in the LazyNamespace. This function will expect +one parameter that will be set to the LazyNamespace object when the function +is called. + +Our demonstration function will increment a counter on a context object +(provided via the vars parameter) and return this counter so that we can easily +follow the calls to the function: + + >>> def getNumber(vars): + ... context = vars.context + ... context.counter += 1 + ... return context.counter + +We now register the function with our LazyNamespace class under the name +we later want to use for accessing the variable: + + >>> from cybertools.lazynamespace.lazynamespace import LazyNamespace + >>> LazyNamespace.registerVariable('number', getNumber) + +We also need a context object - that one which carries the above mentioned +counter: + + >>> from zope.interface import Interface, implements + >>> class Number(object): + ... implements(Interface) + ... counter = 0 + >>> context = Number() + +This object is now used as the context parameter when creating a LazyNamespace +object: + + >>> lns = LazyNamespace(context) + +So let's look if the LazyNamespace object can give us a value for the variable +we have registered: + + >>> lns.number + 1 + +The getNumber() function has been called that apparently has +incremented the counter. + +What happens if we access the variable again? + + >>> lns.number + 1 + +Same result, no incrementation, as it is now stored in the LazyNamespace +object and retrieved without recalculation. Really lazy... + +We can even use the same function for more than one variable. When we first +access the new variable the function is called again: + + >>> LazyNamespace.registerVariable('number2', getNumber) + >>> lns.number2 + 2 + +Our first variable is not affected by this: + + >>> lns.number + 1 + +Typically you will use a LazyNamespace class for adapters. When you want +to use a LazyNamespace when rendering a browser web page you may use +a LazyBrowserNamespace: + + +LazyBrowserNamespace +~~~~~~~~~~~~~~~~~~~~ + +A LazyBrowserNamespace is meant to be used as a multi-adapter on a context +object, a request, and a view. + + >>> from cybertools.lazynamespace.lazynamespace import LazyBrowserNamespace + >>> from cybertools.lazynamespace.interfaces import ILazyNamespace + + >>> import zope.component + >>> from zope.publisher.interfaces.browser import IDefaultBrowserLayer + >>> from zope.app.publisher.interfaces.browser import IBrowserView + >>> zope.component.provideAdapter(LazyBrowserNamespace, + ... (Interface, IDefaultBrowserLayer, IBrowserView), + ... ILazyNamespace) + +We can now get at a LazyBrowserNamespace adapter using our context object +from above and supplying a request and a view in addition. + + >>> from zope.publisher.browser import TestRequest + >>> request = TestRequest() + + >>> class View(object): + ... implements(IBrowserView) + ... def __init__(self, context, request): + ... pass + >>> view = View(context, request) + + >>> from zope.app import zapi + >>> lbns = zapi.getMultiAdapter((context, request, view), ILazyNamespace) + + The LazyBrowserNamespace is independent of the LazyNamespace class and + provides its own registry. So we won't find our variable from above + there: + + >>> lbns.number + Traceback (most recent call last): + ... + KeyError: 'number' + +So we again register a variable, now with the LazyBrowserNamespace: + + >>> LazyBrowserNamespace.registerVariable('number', getNumber) + >>> lbns.number + 3 + >>> lbns.number + 3 + +The old stuff from above is not affected: + + >>> lns.number + 1 + \ No newline at end of file diff --git a/lazyvars/__init__.py b/lazynamespace/__init__.py similarity index 100% rename from lazyvars/__init__.py rename to lazynamespace/__init__.py diff --git a/lazyvars/configure.zcml b/lazynamespace/configure.zcml similarity index 54% rename from lazyvars/configure.zcml rename to lazynamespace/configure.zcml index 52305fe..cba2516 100644 --- a/lazyvars/configure.zcml +++ b/lazynamespace/configure.zcml @@ -9,11 +9,13 @@ - - - + diff --git a/lazyvars/interfaces.py b/lazynamespace/interfaces.py similarity index 84% rename from lazyvars/interfaces.py rename to lazynamespace/interfaces.py index c697eb1..be0d5a7 100644 --- a/lazyvars/interfaces.py +++ b/lazynamespace/interfaces.py @@ -25,7 +25,7 @@ $Id$ from zope.interface import Interface, Attribute -class ILazyVars(Interface): +class ILazyNamespace(Interface): """ Generic adapter that provides lazy setting and returning of variables. """ @@ -34,9 +34,9 @@ class ILazyVars(Interface): """ Class method: register a variable 'name' on class 'class_' that will be provided by calling the function given. - The function should have one parameter that is set to the LazyVars - object when the function is called. Thus the method has access - to the instance variables (and other methods) of the LazyVars - object. + The function should have one parameter that is set to the + LazyNamespace object when the function is called. Thus the method + has access to the instance variables (and other methods) of the + LazyVars object. """ diff --git a/lazyvars/lazyvars.py b/lazynamespace/lazynamespace.py similarity index 71% rename from lazyvars/lazyvars.py rename to lazynamespace/lazynamespace.py index 2df1962..f468a01 100644 --- a/lazyvars/lazyvars.py +++ b/lazynamespace/lazynamespace.py @@ -25,11 +25,11 @@ $Id$ from zope.interface import implements import interfaces -class LazyVars(object): - """ Basic adapter providing lazy variables. +class LazyNamespace(object): + """ Basic adapter providing a lazy namespace. """ - implements(interfaces.ILazyVars) + implements(interfaces.ILazyNamespace) variables = {} @@ -44,4 +44,19 @@ class LazyVars(object): value = self.variables[attr](self) setattr(self, attr, value) return value + + +class LazyBrowserNamespace(LazyNamespace): + """ A multi-adapter providing a lazy namespace for to be used for + browser views. + """ + + variables = {} # LazyBrowserNamespace class should get its own registry. + + def __init__(self, context, request, view): + self.context = context + self.request = request + self.view = view + + \ No newline at end of file diff --git a/lazyvars/tests.py b/lazynamespace/tests.py similarity index 100% rename from lazyvars/tests.py rename to lazynamespace/tests.py diff --git a/lazyvars/README.txt b/lazyvars/README.txt deleted file mode 100644 index 85498fe..0000000 --- a/lazyvars/README.txt +++ /dev/null @@ -1,72 +0,0 @@ -Setting up and using LazyVars objects -===================================== - -Lazy variables are only calculated when really needed, and they are -calculated only once during the lifetime of the LazyVars objects they -live in. - -This is especially useful when rendering web pages as during this -rendering often the same data are used again and again, whereas you don't -know at the beginning of the rendering process which data you will really -need. - -We first need a function that will be used to provide a value -for our lazy variable. This function will expect one parameter that will -be set to the LazyVars object when the function is called. - -Our demonstration function will increment a counter on a context object -(provided via the vars parameter) and return this counter so that we can easily -follow the calls to the function: - - >>> def getNumber(vars): - ... context = vars.context - ... context.counter += 1 - ... return context.counter - -We now register the function with our LazyVars class under the name we later -want to use for accessing the variable: - - >>> from cybertools.lazyvars.lazyvars import LazyVars - >>> LazyVars.registerVariable('number', getNumber) - -We also need a context object - that one which carries the above mentioned -counter: - - >>> class Number(object): - ... counter = 0 - >>> context = Number() - -This object is now used as the context parameter when creating a LazyVars -object: - - >>> lv = LazyVars(context) - -So let's look if the LazyVars object can give us a value for the variable -we have registered: - - >>> lv.number - 1 - -The getNumber() function has been called that apparently has -incremented the counter. - -What happens if we access the variable again? - - >>> lv.number - 1 - -Same result, no incrementation, as it is now stored in the LazyVars object and -retrieved without recalculation. Really lazy... - -We can even use the same function for more than one variable. When we first -access the new variable the function is called again: - - >>> LazyVars.registerVariable('number2', getNumber) - >>> lv.number2 - 2 - -Our first variable is not affected by this: - - >>> lv.number - 1 - diff --git a/tests/test_cybertools.py b/tests.py similarity index 89% rename from tests/test_cybertools.py rename to tests.py index bdcfde7..d43217f 100755 --- a/tests/test_cybertools.py +++ b/tests.py @@ -40,8 +40,9 @@ class TestMenu(unittest.TestCase): def test_suite(): return unittest.TestSuite(( - unittest.makeSuite(TestMenu), - DocFileSuite('../doc/menu.txt'), + unittest.makeSuite(TestMenu), + DocFileSuite('browser/README.txt'), + DocFileSuite('doc/menu.txt'), )) if __name__ == '__main__': diff --git a/tests/__init__.py b/tests/__init__.py deleted file mode 100644 index 4bc90fb..0000000 --- a/tests/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -""" -$Id$ -""" -