Re: [Repoze-dev] owrap layout through zcml

2009-09-12 Thread Chris McDonough
Tim Hoffman wrote:
> HI Chris
> 
> I a way you describing something simliar to what we have in zope2, in
> that from a tal expression we have access to
> (via acquisition) all of the portal tools etc...
> 
> I wonder if a couple of hi level functions could be put into the
> namespace, (or the view for instance) that allow you
> to lookup adapters and utilities in a simpler way, or alternately use
> a view class and push the view handle into the template
> and hang all of the extra api you need there. I have taken to useing
> view classes most of the time and
> always providing "view" as well as context and request.

That's another way to think of it, yep.

BFG views can be classes, but aren't necessarily classes, so I'd like to 
try to find some solution that would take this into account.

I suppose that we could come up with a "page" directive that wrapped a 
callable which always returned a dictionary:



The callable referenced by the directive would be something that 
promised to returne a dictionary, e.g.:

def my_page(context, request):
 return {'a':1}

The BFG view wrapper created by the "page" ZCML definition would look 
more or less like so:

from webob import Response

class Page:
 def __init__(self, callable, template):
 self.callable = callable
 self.template = template

 def __call__(self, context, request):
 dictionary = self.callable(context, request)
 dictionary.setdefault('page', self)
 return Response(self.template(**dictionary))

view = Page()

But having "page" in the template namespace won't help us too much 
unless we can vary the page view wrapper implementation, adding methods 
and such, at least on a per-application basis, ala:



Seems a little clunky though, eh?

- C

> 
> T
> 
> 
> On Sun, Sep 13, 2009 at 5:43 AM, Chris McDonough  wrote:
>> So I've been trying to puzzle out some issues, which might or might not
>> be related to this topic.
>>
>> In KARL, we currently write all of our views something in the form of:
>>
>> def myview(context, request):
>>[ do stuff ]
>>api = TemplateAPI(context, request) # a utility class
>>return render_template_to_response('atemplate.pt', api=api,
>>   foo=1, bar=2)
>>
>> In the template, we do things like "tal:replace="href api.context_url"
>> and so on.  Basically, the KARL "api" object is a "garbage barge" of
>> utility attributes and functions totally specific to the application
>> itself.  There is nothing general about it.
>>
>> What I'd like to do is to be able to write a KARL view like this:
>>
>> def myview(context, request):
>>[ do stuff ]
>>return render_template_to_response('atemplate.pt', foo=1, bar=2)
>>
>> ... but still have some way of accessing the KARL "api" in the template.
>>  In essence, I'd like to put the BFG templating system in charge of
>> adding one or more globals that is accessible within the template.
>>
>> There's a half step towards this that's simple.  It'd be relatively easy
>> to put both "context" and "request" into the names passed to all
>> templates.  But this doesn't help us very much in the common case,
>> because then we'd need to write a lot of hairy expressions to compute
>> things based on those values.  Basically the template would assume the
>> job of our current "API", which is not ideal.
>>
>> It'd be better if we could add some configuration that would one or more
>> globals to a template's namespace.  For example, one configuration might
>> look like (via ZCML):
>>
>>  
>>
>> The ".api.TemplateAPI" class would accept, say, a context and a request
>> (or just a request, as requests already have a context attribute), ala:
>>
>> class TemplateAPI(object):
>> def __init__(self, context, request):
>> self.context = context
>> self.request = request
>> self.context_url = model_url(context)
>>
>> At this point the name "api" would just be jammed into the template
>> names on each template rendering and it could have both attributes and
>> methods accessible via "api.whatever".
>>
>> At some point I had considered using a Chameleon expression prefix to
>> separate these sorts of "builtin" names from the main template namespace
>> names.  For example, instead of "tal:replace="href api.context_url",
>> you'd access builtins via an expression type, e.g. "tal:replace="href
>> api:context_url".  That bugged Malthe because it's essentially a "second
>> "python:" expression type that happens to not use the "main" template
>> namespace.  I'm not sure about it either, because it's obvious that
>> you'll want to use the names passed to the template explicitly in those
>> expressions too, and the semantics and implementation could get pretty
>> confusing if you need to make that possible.
>>
>> Can anyone think of a better way of achieving this goal?  If we don't
>> collectively come up with something better, I am apt to just allow folks
>> to register factories via ZCML that prod

Re: [Repoze-dev] owrap layout through zcml

2009-09-12 Thread Tim Hoffman
HI Chris

I a way you describing something simliar to what we have in zope2, in
that from a tal expression we have access to
(via acquisition) all of the portal tools etc...

I wonder if a couple of hi level functions could be put into the
namespace, (or the view for instance) that allow you
to lookup adapters and utilities in a simpler way, or alternately use
a view class and push the view handle into the template
and hang all of the extra api you need there. I have taken to useing
view classes most of the time and
always providing "view" as well as context and request.

T


On Sun, Sep 13, 2009 at 5:43 AM, Chris McDonough  wrote:
> So I've been trying to puzzle out some issues, which might or might not
> be related to this topic.
>
> In KARL, we currently write all of our views something in the form of:
>
> def myview(context, request):
>    [ do stuff ]
>    api = TemplateAPI(context, request) # a utility class
>    return render_template_to_response('atemplate.pt', api=api,
>                                       foo=1, bar=2)
>
> In the template, we do things like "tal:replace="href api.context_url"
> and so on.  Basically, the KARL "api" object is a "garbage barge" of
> utility attributes and functions totally specific to the application
> itself.  There is nothing general about it.
>
> What I'd like to do is to be able to write a KARL view like this:
>
> def myview(context, request):
>    [ do stuff ]
>    return render_template_to_response('atemplate.pt', foo=1, bar=2)
>
> ... but still have some way of accessing the KARL "api" in the template.
>  In essence, I'd like to put the BFG templating system in charge of
> adding one or more globals that is accessible within the template.
>
> There's a half step towards this that's simple.  It'd be relatively easy
> to put both "context" and "request" into the names passed to all
> templates.  But this doesn't help us very much in the common case,
> because then we'd need to write a lot of hairy expressions to compute
> things based on those values.  Basically the template would assume the
> job of our current "API", which is not ideal.
>
> It'd be better if we could add some configuration that would one or more
> globals to a template's namespace.  For example, one configuration might
> look like (via ZCML):
>
>  
>
> The ".api.TemplateAPI" class would accept, say, a context and a request
> (or just a request, as requests already have a context attribute), ala:
>
> class TemplateAPI(object):
>     def __init__(self, context, request):
>         self.context = context
>         self.request = request
>         self.context_url = model_url(context)
>
> At this point the name "api" would just be jammed into the template
> names on each template rendering and it could have both attributes and
> methods accessible via "api.whatever".
>
> At some point I had considered using a Chameleon expression prefix to
> separate these sorts of "builtin" names from the main template namespace
> names.  For example, instead of "tal:replace="href api.context_url",
> you'd access builtins via an expression type, e.g. "tal:replace="href
> api:context_url".  That bugged Malthe because it's essentially a "second
> "python:" expression type that happens to not use the "main" template
> namespace.  I'm not sure about it either, because it's obvious that
> you'll want to use the names passed to the template explicitly in those
> expressions too, and the semantics and implementation could get pretty
> confusing if you need to make that possible.
>
> Can anyone think of a better way of achieving this goal?  If we don't
> collectively come up with something better, I am apt to just allow folks
> to register factories via ZCML that produce something that is jamed into
> the main template namespace, ala the "templatename" ZCML directive
> above.  Any number of them will be registerable.  A conflict will occur
> during ZCML processing if two share the same name.  These functions, if
> they exist, will be called on each template rendering and their results
> will be jammed into the top-level namespace.
>
> Robert Marianski wrote:
>> On Mon, Aug 24, 2009 at 10:11:04PM -0400, Chris McDonough wrote:
>>> I like this.
>>>
>>> Some variations:
>>>
>>> - Have IOWrap be a multiadapter on context and request, so we can vary the
>>> o-wrap based on request type too (e.g. "IManagementRequest" vs. 
>>> "IRetailRequest").
>>
>> Good idea. I'll go ahead and add this in.
>>
>>> - If IOWrap can't be adapted, just return the result of the view (instead of
>>> throwing a component lookup error).
>>
>> I'm kind of torn on this. On the one hand, I like that a specific
>> exception would get thrown, so it's easy to know when there's a
>> configuration problem and how to fix it. On the other, getting no wrap
>> is obvious itself, and may be better for users to initially see an
>> unwrapped page rather than seeing their applications explode.
>>
>> I'd expect that there would typically be a catch-all owrap defin

Re: [Repoze-dev] owrap layout through zcml

2009-09-12 Thread Chris McDonough
So I've been trying to puzzle out some issues, which might or might not 
be related to this topic.

In KARL, we currently write all of our views something in the form of:

def myview(context, request):
[ do stuff ]
api = TemplateAPI(context, request) # a utility class
return render_template_to_response('atemplate.pt', api=api,
   foo=1, bar=2)

In the template, we do things like "tal:replace="href api.context_url" 
and so on.  Basically, the KARL "api" object is a "garbage barge" of 
utility attributes and functions totally specific to the application 
itself.  There is nothing general about it.

What I'd like to do is to be able to write a KARL view like this:

def myview(context, request):
[ do stuff ]
return render_template_to_response('atemplate.pt', foo=1, bar=2)

... but still have some way of accessing the KARL "api" in the template. 
  In essence, I'd like to put the BFG templating system in charge of 
adding one or more globals that is accessible within the template.

There's a half step towards this that's simple.  It'd be relatively easy 
to put both "context" and "request" into the names passed to all 
templates.  But this doesn't help us very much in the common case, 
because then we'd need to write a lot of hairy expressions to compute 
things based on those values.  Basically the template would assume the 
job of our current "API", which is not ideal.

It'd be better if we could add some configuration that would one or more 
globals to a template's namespace.  For example, one configuration might 
look like (via ZCML):

  

The ".api.TemplateAPI" class would accept, say, a context and a request 
(or just a request, as requests already have a context attribute), ala:

class TemplateAPI(object):
 def __init__(self, context, request):
 self.context = context
 self.request = request
 self.context_url = model_url(context)

At this point the name "api" would just be jammed into the template 
names on each template rendering and it could have both attributes and 
methods accessible via "api.whatever".

At some point I had considered using a Chameleon expression prefix to 
separate these sorts of "builtin" names from the main template namespace 
names.  For example, instead of "tal:replace="href api.context_url", 
you'd access builtins via an expression type, e.g. "tal:replace="href 
api:context_url".  That bugged Malthe because it's essentially a "second 
"python:" expression type that happens to not use the "main" template 
namespace.  I'm not sure about it either, because it's obvious that 
you'll want to use the names passed to the template explicitly in those 
expressions too, and the semantics and implementation could get pretty 
confusing if you need to make that possible.

Can anyone think of a better way of achieving this goal?  If we don't 
collectively come up with something better, I am apt to just allow folks 
to register factories via ZCML that produce something that is jamed into 
the main template namespace, ala the "templatename" ZCML directive 
above.  Any number of them will be registerable.  A conflict will occur 
during ZCML processing if two share the same name.  These functions, if 
they exist, will be called on each template rendering and their results 
will be jammed into the top-level namespace.

Robert Marianski wrote:
> On Mon, Aug 24, 2009 at 10:11:04PM -0400, Chris McDonough wrote:
>> I like this.
>>
>> Some variations:
>>
>> - Have IOWrap be a multiadapter on context and request, so we can vary the 
>> o-wrap based on request type too (e.g. "IManagementRequest" vs. 
>> "IRetailRequest").
> 
> Good idea. I'll go ahead and add this in.
> 
>> - If IOWrap can't be adapted, just return the result of the view (instead of 
>> throwing a component lookup error).
> 
> I'm kind of torn on this. On the one hand, I like that a specific
> exception would get thrown, so it's easy to know when there's a
> configuration problem and how to fix it. On the other, getting no wrap
> is obvious itself, and may be better for users to initially see an
> unwrapped page rather than seeing their applications explode.
> 
> I'd expect that there would typically be a catch-all owrap defined
> anyway, so it's unlikely that this will be much of an issue in practice.
> But in retrospect again, I think it's better to fail more gracefully by
> showing an unwrapped view instead of an exception. I'll go ahead and
> make this change too.
> 
>> Please forgive the digression, but this is physically sort of tied in: we 
>> still 
>> need a good way to allow a set of "top level names" to be supplied to 
>> templates. 
>>   So far, the best we could do for that pattern has been something like 
>> ("api" 
>> is not a good name, I can't think of anything better, though):
> 
> Can you give an example use case for this? For the cases in my mind, I'd
> prefer to push as much logic out into the owrap as possible, so that the
> actual