[Zope-CMF] Re: [dev] Actions: lazy dict not working with DTML?

yuppie y.2004_ at wcm-solutions.de
Wed Aug 4 05:21:12 EDT 2004


Hi!


Dieter Maurer wrote:
> yuppie wrote at 2004-8-2 18:21 +0200:
> 
>>Since last week listFilteredActionsFor() returns ActionInfo objects 
>>instead of dictionaries. I tried to implement ActionInfo as a lazy dict 
>>to defer expensive processing of TALES expressions.
> 
> What is a lazy dict?

Maybe there is a better term for this. I use 'lazy' in analogy to how it 
is used in ZCatalog/Lazy.py or ZPublisher/HTTPRequest.py. I mean a dict 
that computes (some of) its values on demand, avoiding the need to 
compute them on creation time.

The ActionInfo class is checked in here:
<http://cvs.zope.org/CMF/CMFCore/ActionInformation.py?rev=1.24&content-type=text/vnd.viewcvs-markup>

Basically this is a dict with a customized __getitem__ method.

>>This seems to work with the ZPT skin, but not with the old DTML skin.
>>
>>   <dtml-in user_actions mapping>
>>    <a href="&dtml-url;"><dtml-var name></a><br>
>>   </dtml-in>
>>
>>Looks like this code bypasses __getitem__, but I don't understand how 
>>this works because I'm not a C programmer and can't read the 
>>TemplateDict code.
> 
> 
> This is unlikely.
> 
> With the "mapping" keyword, the object itself is pushed
> onto the "TemplateDict" (it is a stack of namespaces);
> without it, it is wrapped before pushing into a "ClientDict" (I think)
> which maps "__getitem__" to "__getattr__".
> 
> The "TemplateDict"s "getitem" asks each namespace on its stack
> for the name using its "__getitem__" until it succeeds or reaches
> the end of the stack.
> 
> When you send me a code fragment showing how your
> "lazy dict" looks and works in principle, I can try to
> analyse the problem.

Great. I attached an unittest that shows the problem. While 
pDocumentTemplate seems to implement TemplateDict based on a 
MultiMapping, MultiMapping works as expected. So cDocumentTemplate seems 
to do something different.

If this is not easy to resolve, I'll check in my workaround for 
listFilteredActionsFor. I guess we can live with that.


Thanks,
	Yuppie
-------------- next part --------------
from unittest import TestCase, TestSuite, makeSuite, main
import Testing
import Zope
Zope.startup()

from DocumentTemplate.DT_Util import TemplateDict
from MultiMapping import MultiMapping


class LazyDict(dict):
    def __getitem__(self, key):
        return 'bar'


class LazyDictTests(TestCase):

    def test_LazyDict(self):
        ld = LazyDict(foo='foo')
        self.assertEqual(ld['foo'], 'bar')

    def test_inMultiMapping(self):
        ld = LazyDict(foo='foo')
        mm = MultiMapping()
        mm.push(ld)
        self.assertEqual(mm['foo'], 'bar')

    def test_inTemplateDict(self):
        ld = LazyDict(foo='foo')
        td = TemplateDict()
        td._push(ld)
        self.assertEqual(td['foo'], 'bar')


def test_suite():
    return TestSuite((
        makeSuite(LazyDictTests),
        ))

if __name__ == '__main__':
    main(defaultTest='test_suite')


More information about the Zope-CMF mailing list