[z3-five] Does Five support Local Utilities?

Chris Withers chris at simplistix.co.uk
Tue Sep 19 12:25:55 CEST 2006


Philipp von Weitershausen wrote:
> (Interlude:
> 
> Note that Zope 3 has a decent mail framework that's transaction aware 
> and all that, so while you might want to create the mail message 
> yourself, you probably want to use zope.sendmail [zope.app.mail 
> previously] for sending it out. 

Yup, bear in mind that Twiddler is not aimed soley at Zope ;-)
I'd imagine there would be an IOutput for Zope 2 that subclasses 
emailer.Email and uses a MailHost for Zope 2, and something similar for 
Zope 3 that uses zope.sendmail or a Zope 3 MailHost equivalent...

> Plus, it feels weird to do the mail 
> sending in an twiddler output renderer, but I don't know the framework...
> )

You don't have to, but it can be convenient. The output essentially just 
renders the mail, you can send it whenever you want:

msg = t.render(mto=('philipp at weitershausen.de',),as_message=True)
f = open('virus.bin','rb')
msg.add_file(f)
msg.send()

...you could even choose to send the mail using something else:

smtp.send(you_from,your_to,msg.as_string())

> At least storing the twiddler tree in the global utility seems weird to 
> me. 

That doesn't happen, a copy of the utility is stored as an attribute of 
the Twiddler, which is how the plain python version works, as shown by 
this snippet from ITwiddler:

     input = Attribute("""
         An object implementing IInput.

         If this attribute is set, then setSource should be called with
         the original or new source to re-parse it.

         NB: No checking is done when this attribute is set, be careful!
         """)


> I *think* you could express all this better through adapters. Let's 
> take the first example:
> 
>   class DefaultRenderer(object):
>       adapts(ITwiddler)
>       implements(IOutput)
> 
>       def __init__(self, context):
>           self.context = context
> 
>       def __call__(self, *args, **kw):
>          root = self.context
>          return u''.join(_render(output, root._root, {}))
> 
> The mail rendering could be expressed with a different adapter:
> 
>   class MailRenderer(DefaultRenderer):
>       adapts(IMailTwiddler)
> 
>       smtp_host = 'localhost'
>       smtp_port = 25
>       mfrom = None
>       mto = None
> 
>       def __call__(self, *args, **kw):
>          return MTMultipart(self,
>                             values['mfrom'],
>                             values['mto'],
>                             **multipart_kw).to_string()
> 
> Now you would just register different incarnations of this mail renderer 
> (with different configuration values) for your various twiddlers. The 
> only downside is that you need marker interfaces to express this 
> properly. Or you use named adapters.

Yeah, this feels like too much Zope kool aid to me. I'm happy to have 
Twiddler depend on zope.interface, since it's becoming the defacto 
python interface implementation, and I'm happy to rely on zope.testing 
is you want to run the tests, purely 'cos the doctest is better, but 
making twiddler reliant on zope.component is not what I want.

The utility stuff I'm playing with is mainly to help build and configure 
Twiddlers under Zope 2. How well do adapters play in the Zope2/Five world?

As a specific question, how would I build a TTW configurable set of 
adapters and a UI to pick and choose between them?

For example, there's also IExectutor, which specifies where to find code 
to execute at render time, as a a simple example for Zope 2 land, I want 
to be able to do something akin to:

t = Twiddler('<html>...etc..</html>',
              executor=Zope2Traverser('/folder/python_script'))

where Zope2Traverser is something like:

class Zope2Traverser:

   implements(IExecutor)

   def __init__(self,path):
     self.path = path

   def __call__(self):
     return self.unrestrictedTraverse(self.path)

In the adapter model, how would you see IExecutor panning out?

Where would I put the '/folder/python_script' and how would I configure 
it, bearing in mind that it might be different for each and every Twiddler?

cheers,

Chris

PS: Interestingly, in Zope 3, none of this will likely be an issue, 
since the Twiddler will be set up in the BrowserView, likely as a class 
attribute, and can be constructed using the plain-python twiddler 
semantics. However, this issue does return as soon as they become 
configurably TTW ;-)

-- 
Simplistix - Content Management, Zope & Python Consulting
            - http://www.simplistix.co.uk


More information about the z3-five mailing list