diff --git a/lazyvars/README.txt b/lazyvars/README.txt new file mode 100644 index 0000000..85498fe --- /dev/null +++ b/lazyvars/README.txt @@ -0,0 +1,72 @@ +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/relations/__init__.py b/lazyvars/__init__.py similarity index 100% rename from relations/__init__.py rename to lazyvars/__init__.py diff --git a/relations/configure.zcml b/lazyvars/configure.zcml similarity index 100% rename from relations/configure.zcml rename to lazyvars/configure.zcml diff --git a/lazyvars/interfaces.py b/lazyvars/interfaces.py new file mode 100644 index 0000000..c697eb1 --- /dev/null +++ b/lazyvars/interfaces.py @@ -0,0 +1,42 @@ +# +# 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 +# + +""" +interface definitions for the LazyVars stuff. + +$Id$ +""" + +from zope.interface import Interface, Attribute + + +class ILazyVars(Interface): + """ Generic adapter that provides lazy setting and returning + of variables. + """ + + def registerVariable(class_, name, function): + """ 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. + """ + diff --git a/lazyvars/lazyvars.py b/lazyvars/lazyvars.py new file mode 100644 index 0000000..2df1962 --- /dev/null +++ b/lazyvars/lazyvars.py @@ -0,0 +1,47 @@ +# +# 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 +# + +""" +Implementation of classes providing lazy variables. + +$Id$ +""" + +from zope.interface import implements +import interfaces + +class LazyVars(object): + """ Basic adapter providing lazy variables. + """ + + implements(interfaces.ILazyVars) + + variables = {} + + def __init__(self, context): + self.context = context + + @classmethod + def registerVariable(class_, name, method): + class_.variables[name] = method + + def __getattr__(self, attr): + value = self.variables[attr](self) + setattr(self, attr, value) + return value + \ No newline at end of file diff --git a/lazyvars/tests.py b/lazyvars/tests.py new file mode 100755 index 0000000..323a078 --- /dev/null +++ b/lazyvars/tests.py @@ -0,0 +1,20 @@ +# $Id$ + +import unittest +from zope.testing.doctestunit import DocFileSuite +from zope.app.testing import ztapi +from zope.app import zapi +from zope.interface.verify import verifyClass + + +class TestMenu(unittest.TestCase): + "Test methods of the Menu class." + + +def test_suite(): + return unittest.TestSuite(( + DocFileSuite('README.txt'), + )) + +if __name__ == '__main__': + unittest.main(defaultTest='test_suite') diff --git a/relation/__init__.py b/relation/__init__.py new file mode 100644 index 0000000..ba03d76 --- /dev/null +++ b/relation/__init__.py @@ -0,0 +1,7 @@ +# -*- coding: UTF-8 -*- +# -*- Mode: Python; py-indent-offset: 4 -*- +# Copyright (C) 2005 Helmut Merz + +""" +$Id$ +""" diff --git a/relation/configure.zcml b/relation/configure.zcml new file mode 100644 index 0000000..52305fe --- /dev/null +++ b/relation/configure.zcml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + diff --git a/relations/interfaces.py b/relation/interfaces.py similarity index 100% rename from relations/interfaces.py rename to relation/interfaces.py diff --git a/relations/utilities.py b/relation/utilities.py similarity index 100% rename from relations/utilities.py rename to relation/utilities.py