Discussion:
[Zope3-dev] Are pagelets content providers?
Thomas Lotze
2007-10-01 17:09:47 UTC
Permalink
During the gocept sprint on z3c.form last week we found that the interface
of pagelets (z3c.pagelet.interfaces.IPagelet) is a mere marker interface
on top of IBrowserPage, which seems to me a bit thin.

For one, the implementation of pagelets makes use of the render and update
methods. Since these methods are the ones to be customized when writing
custom pagelets, they should be documented.

While it would be easy enough to just add the methods to IPagelet (which
has actually been done for render by now), I think IPagelet should really
be an extension to zope.contentprovider.interfaces.IContentProvider in
addition to IBrowserPage. It is already possible to use pagelets such as
z3c.form.form.Form as content providers. While the pagelet implementation
distinguishes between pagelet and pagelet renderer, only the latter being
declared the content provider, this distinction seems to be made only in
order for the content provider lookup to return the same pagelet instance
that is the view. The renderer then only (sort of) forwards the pagelet's
own content provider functionality, so the pagelet might as well be
declared a content provider itself.

Any thoughts, objections, ideas?
--
Thomas
Roger Ineichen
2007-10-01 20:05:47 UTC
Permalink
Hi Thomas
Betreff: [Zope3-dev] Are pagelets content providers?
During the gocept sprint on z3c.form last week we found that
the interface of pagelets (z3c.pagelet.interfaces.IPagelet)
is a mere marker interface on top of IBrowserPage, which
seems to me a bit thin.
Yes and no ;-)

I was carfully skip some additional method decalration
because I didn't know if we gona use IPagelets without
render and update in other implementations.
For one, the implementation of pagelets makes use of the
render and update methods. Since these methods are the ones
to be customized when writing custom pagelets, they should be
documented.
Yes you are probably right, feel free to add them to the IPagelet
interface. I didn't use the IPagelet interface without
render/update till now and I see no other usecase without
them. Or does anybody see such non render/update usecase
for IPagelet?
While it would be easy enough to just add the methods to
IPagelet (which has actually been done for render by now), I
think IPagelet should really be an extension to
zope.contentprovider.interfaces.IContentProvider in addition
to IBrowserPage. It is already possible to use pagelets such
as z3c.form.form.Form as content providers. While the pagelet
implementation distinguishes between pagelet and pagelet
renderer, only the latter being declared the content
provider, this distinction seems to be made only in order for
the content provider lookup to return the same pagelet
instance that is the view. The renderer then only (sort of)
forwards the pagelet's own content provider functionality, so
the pagelet might as well be declared a content provider itself.
I disagree, the IPagelet is not a IContentProvider. The pagelet
is the component which defines the content and the renderer is
the content provider. It's a delegation pattern.

I explicit didn't implement IContentProvider in IPagelet
because a pagelet has to conceptual functionality of a page
and not of a content provider or viewlet thing.

Hm, probably the naming of the pagelet within it's (*let)
in the name is not so good as I was thinking. It could
suggest that the pagelet is a additional page content like
viewlets or content providers. But a pagelet is a
full replacement for the IBrowserPage and not additional.

The interface IPagelet(IBrowserPage) should reflect the
page replacement.

The IPageletRenderer(IContentProvider) should describe
the pattern how the pagelet content get accessed.


Dou you see my idea behind this declarations?

What do you think, should we add render/update to the
IPagelet which is not defined in IBrowserPage?

Or should we add a IRenderUpdate interface in zope.?
which we can use in zope.formlib, z3c.form, z3c.pagelet
and probably many more interfaces?

Regards
Roger Ineichen
Any thoughts, objections, ideas?
--
Thomas
_______________________________________________
Zope3-dev mailing list
http://mail.zope.org/mailman/options/zope3-dev/dev%40projekt01.ch
Thomas Lotze
2007-10-02 07:53:29 UTC
Permalink
I was carfully skip some additional method decalration because I didn't
know if we gona use IPagelets without render and update in other
implementations.
The z3c.pagelet README.txt says that "Pagelets are views which can be
called and support the update and render pattern." So either this refers
to the particular implementation only, in which case I'd say an
independent definition of the concept of pagelets is missing, or otherwise
it doesn't leave much room for implementations without update and render
methods.
I disagree, the IPagelet is not a IContentProvider. The pagelet is the
component which defines the content and the renderer is the content
provider. It's a delegation pattern.
I explicit didn't implement IContentProvider in IPagelet because a pagelet
has to conceptual functionality of a page and not of a content provider or
viewlet thing.
So the pagelet is really two things: a specific implementation of a
browser page, and a component which defines content. Both should reflect
in its interface, and why should something which defines content and
follows the update/render pattern not formally be declared a content
provider? Calling it something else with the same methods serves only to
keep around an interface twice, by different names.

AFAICS, there's nothing wrong with two content providers taking part in
delivering the pagelet's content: one that originally creates the content
behind the scenes, and one that is called from the layout template and
delegates content creation to the former. You don't have to prohibit a
pagelet to be called a content provider in order not to call it from the
template directly. The issue might just be about interfaces describing how
an object can be used instead of what code is supposed to use it.

OTOH, there's real value in pagelets being content providers: library or
application developers wouldn't have to decide up front whether their
content providing component is to be used for primary or supplementary
page content by deciding whether to implement it as a pagelet or a content
provider; it could be both without adding any dead chicken abstractions.

A real-world use case is z3c.form forms: they are implemented as pagelets
which is fine as long as each form makes up a page of its own. However,
we'd like to combine forms with other stuff, such as a search form with a
result list. This is possible by using a form (a pagelet) as a content
provider, but that feels like a hack as long as it isn't backed by formal
interfaces.
The interface IPagelet(IBrowserPage) should reflect the page replacement.
The IPageletRenderer(IContentProvider) should describe the pattern how the
pagelet content get accessed.
Dou you see my idea behind this declarations?
I do, but I can't follow the conclusion that pagelets should not at the
same time be declared content providers, which they de facto are.
What do you think, should we add render/update to the IPagelet which is
not defined in IBrowserPage?
Or should we add a IRenderUpdate interface in zope.? which we can use in
zope.formlib, z3c.form, z3c.pagelet and probably many more interfaces?
Having thought some more about it since asking it as a question yesterday,
I now definitely think that IPagelet should extend both IBrowserPage and
IContentProvider. I can't see any value in a new IRenderUpdate interface
since the distinction from IContentProvider would be very academic IMO.
--
Thomas
Roger Ineichen
2007-10-02 10:48:34 UTC
Permalink
Hi Thomas
Betreff: [Zope3-dev] Re: AW: Are pagelets content providers?
I was carfully skip some additional method decalration because I
didn't know if we gona use IPagelets without render and update in
other implementations.
The z3c.pagelet README.txt says that "Pagelets are views
which can be called and support the update and render
pattern." So either this refers to the particular
implementation only, in which case I'd say an independent
definition of the concept of pagelets is missing, or
otherwise it doesn't leave much room for implementations
without update and render methods.
Probably we should say;
"Pagelets are views which support the publisher __call__
attribute and provide the update/render pattern."
I disagree, the IPagelet is not a IContentProvider. The
pagelet is the
component which defines the content and the renderer is the content
provider. It's a delegation pattern.
I explicit didn't implement IContentProvider in IPagelet because a
pagelet has to conceptual functionality of a page and not
of a content
provider or viewlet thing.
So the pagelet is really two things: a specific
implementation of a browser page, and a component which
defines content. Both should reflect in its interface, and
why should something which defines content and follows the
update/render pattern not formally be declared a content
provider? Calling it something else with the same methods
serves only to keep around an interface twice, by different names.
You are wrong here. A IContentProvider doesn't define content.
A IContentProvider provides content. That's different.

I a component defines content it provides the IPresentation
interface which is the case for IPagelet.

A IContentProvider knows only how to get content for another
component. Again, it's a delegation pattern.
AFAICS, there's nothing wrong with two content providers
taking part in delivering the pagelet's content: one that
originally creates the content behind the scenes, and one
that is called from the layout template and delegates content
creation to the former. You don't have to prohibit a pagelet
to be called a content provider in order not to call it from
the template directly. The issue might just be about
interfaces describing how an object can be used instead of
what code is supposed to use it.
You are saying, that we have IContentProvider providing content
and defining content. Define content is the part of the
IPresentation interface.
library or application developers wouldn't have to decide up
front whether their content providing component is to be used
for primary or supplementary page content by deciding whether
to implement it as a pagelet or a content provider; it could
be both without adding any dead chicken abstractions.
A real-world use case is z3c.form forms: they are implemented
as pagelets which is fine as long as each form makes up a
page of its own. However, we'd like to combine forms with
other stuff, such as a search form with a result list. This
is possible by using a form (a pagelet) as a content
provider, but that feels like a hack as long as it isn't
backed by formal interfaces.
Probably I don't understand this correct. Are you thinking
about a IContentProvider which collects more then one
pagelet? Probably I don't see your idea. Can you descibe it
what do you mean with "as long as ... page of its own"
and "pagelet as content provider".

I don't understand how a pagelet can get called as a
content provider. The adaption doesn't work because
they support different __init__ method signatures.
The interface IPagelet(IBrowserPage) should reflect the
page replacement.
The IPageletRenderer(IContentProvider) should describe the
pattern how
the pagelet content get accessed.
Dou you see my idea behind this declarations?
I do, but I can't follow the conclusion that pagelets should
not at the same time be declared content providers, which
they de facto are.
What do you think, should we add render/update to the
IPagelet which
is not defined in IBrowserPage?
Or should we add a IRenderUpdate interface in zope.? which
we can use
in zope.formlib, z3c.form, z3c.pagelet and probably many
more interfaces?
Having thought some more about it since asking it as a
question yesterday, I now definitely think that IPagelet
should extend both IBrowserPage and IContentProvider. I can't
see any value in a new IRenderUpdate interface since the
distinction from IContentProvider would be very academic IMO.
Did you recognize that the __init__ are different.

A IContentProvider defines:

def __init__(self, context, request, view)
self.context = context
self.request = request
self.view = view

and a IPagelet defines:

def __init__(self, context, request):
self.context = context
self.request = request

Probably we should describe this in the interface too.
This whould manifest the difference of content provider
which provide content and pagelets whcih defines content
in a better way.


I guess there is nothing wrong with your idea, you
can allways mix IContentProvider and IPagelet in a new
interface. But the existing implementation of IPagelet
is not a IContentProvider out of the box.

A IPagelet called by the IContentProvider TALES expression
whould have to support __init__(self, context, request, view)
which isn't the case in the Pagelet implementation.

Probably it was a mistake to not define this defference in
the interface. But we where thinking that this let us some
room for the implementation. E.g. like you are proposing.
But I still think we should not mix the IPagelet and
IContentProvider pattern into the pagelet implementation
by default.

Does this make sense for you?

btw,
what do you think about to remove the formlib implementation
from the z3c.pagelet package?

Regards
Roger Ineichen
--
Thomas
_______________________________________________
Zope3-dev mailing list
http://mail.zope.org/mailman/options/zope3-dev/dev%40projekt01.ch
Jacob Holm
2007-10-02 11:33:33 UTC
Permalink
Hi Roger,

I didn't follow this discussion closely but thought this needed a comment.

Roger Ineichen wrote:

[snip lots of context...]
Post by Roger Ineichen
Did you recognize that the __init__ are different.
def __init__(self, context, request, view)
self.context = context
self.request = request
self.view = view
self.context = context
self.request = request
Probably we should describe this in the interface too.
This whould manifest the difference of content provider
which provide content and pagelets whcih defines content
in a better way.
It would make sense to have the 'view' attribute a part of the
IContentProvider interface, and *that* might make them different. The
constructor signature is all about the class instead of the instance
and should therefore *not* be part of the interface.

It is perfectly reasonable to have a number of different
(multi-)adapters with different signatures that adapt to the same
interface.

Hope this makes sense. I'll go back to lurking now.

Regards

Jacob
--
Jacob Holm
CTO
Improva ApS
Roger Ineichen
2007-10-02 12:15:39 UTC
Permalink
Hi Jacob, Thomas
Betreff: Re: AW: [Zope3-dev] Re: AW: Are pagelets content providers?
Hi Roger,
I didn't follow this discussion closely but thought this
needed a comment.
[snip lots of context...]
Post by Roger Ineichen
Did you recognize that the __init__ are different.
def __init__(self, context, request, view)
self.context = context
self.request = request
self.view = view
self.context = context
self.request = request
Probably we should describe this in the interface too.
This whould manifest the difference of content provider
which provide
Post by Roger Ineichen
content and pagelets whcih defines content in a better way.
It would make sense to have the 'view' attribute a part of
the IContentProvider interface, and *that* might make them
different. The constructor signature is all about the class
instead of the instance and should therefore *not* be part of
the interface.
It is perfectly reasonable to have a number of different
(multi-)adapters with different signatures that adapt to the
same interface.
Hope this makes sense. I'll go back to lurking now.
Yes you are right, that was the reason I didn't define the
__init__ method in the interface. But I still think a
IPagelet isn't a IContentProvider by default. Of corse
another class can be defined as IContentProvider and IPagelet.
Such a class whould then provide a different __init__ method
then the pagelet does right now.

Thomas;
Should we implement a z3c.form/z3c.pagelet package?
There we could support z3c.form base classes built
up on pagelets.

Probably called z3c.formpagelet which contains
IPageletForm, IPageletAddForm etc.

Regards
Roger Ineichen
Regards
Jacob
--
Jacob Holm
CTO
Improva ApS
_______________________________________________
Zope3-dev mailing list
http://mail.zope.org/mailman/options/zope3-dev/dev%40projekt01.ch
Thomas Lotze
2007-10-02 12:51:04 UTC
Permalink
Yes you are right, that was the reason I didn't define the __init__ method
in the interface. But I still think a IPagelet isn't a IContentProvider by
default. Of corse another class can be defined as IContentProvider and
IPagelet. Such a class whould then provide a different __init__ method
then the pagelet does right now.
See my other response I wrote before I read this message of yours.
Should we implement a z3c.form/z3c.pagelet package? There we could support
z3c.form base classes built up on pagelets.
Probably called z3c.formpagelet which contains IPageletForm,
IPageletAddForm etc.
This would solve my use case but sounds like a lot of architecture, to be
honest. I think this is exactly what I hoped to avoid by pinning the
internal communication between pagelets and pagelet renderers down to
talking IContentProvider and thereby allowing pagelets to be used as
content providers from everywhere. See the "dead chicken" remark in my
first reply to you.
--
Thomas
Roger Ineichen
2007-10-02 13:51:13 UTC
Permalink
Hi Thomas
Betreff: [Zope3-dev] Re: AW: AW: Re: AW: Are pagelets content
providers?
Yes you are right, that was the reason I didn't define the __init__
method in the interface. But I still think a IPagelet isn't a
IContentProvider by default. Of corse another class can be
defined as
IContentProvider and IPagelet. Such a class whould then provide a
different __init__ method then the pagelet does right now.
See my other response I wrote before I read this message of yours.
As longer as I think about your idea, you are probably right.

I agree with not declaring __init__ in the interface. That's what
we did. The only concren I have right now with IPagelet is inherited
from IContentProvider is the default TALES expression which
uses the following code for lookup IContentProvider:

class TALESProviderExpression(expressions.StringExpr):
...
# Try to look up the provider.
provider = zope.component.queryMultiAdapter(
(context, request, view), interfaces.IContentProvider, name)
...

This requieres a specific __init__ method.

What do you recommend to do? I'm open to improve it but how can
we reflect the different adaption concepts like we have with the
different __init__ used by IPagelet and IContentProvider.

I agree that __init__ is not a part of the interface. But I also
think it should be a part of a (probably another) interface since
this is required by a specific lookup pattern.

But that's probably over designed.

Any idea?
Should we implement a z3c.form/z3c.pagelet package? There we could
support z3c.form base classes built up on pagelets.
Probably called z3c.formpagelet which contains IPageletForm,
IPageletAddForm etc.
This would solve my use case but sounds like a lot of
architecture, to be honest. I think this is exactly what I
hoped to avoid by pinning the internal communication between
pagelets and pagelet renderers down to talking
IContentProvider and thereby allowing pagelets to be used as
content providers from everywhere. See the "dead chicken"
remark in my first reply to you.
Ok, I see your idea

Regards
Roger Ineichen
--
Thomas
_______________________________________________
Zope3-dev mailing list
http://mail.zope.org/mailman/options/zope3-dev/dev%40projekt01.ch
Thomas Lotze
2007-10-04 20:53:54 UTC
Permalink
What do you recommend to do? I'm open to improve it but how can we reflect
the different adaption concepts like we have with the different __init__
used by IPagelet and IContentProvider.
It should be easy to do by using a factory function which is registered as
the multiadapter to IContentProvider. It would take the context, request,
and view as arguments, instantiate a pagelet passing only the context and
request as constructor parameters, and finally set its view attribute.
I agree that __init__ is not a part of the interface. But I also think it
should be a part of a (probably another) interface since this is required
by a specific lookup pattern.
No. __init__ is not part of any interface. It is a matter of
implementation. IMO, if there are to be different ways to construct
instances providing the same interface, there ought to be different
factories producing such instances depending on context and chosen
implementation (class). A class itself is just another one of those
factories.
Ok, I see your idea
:o)
--
Thomas
Thomas Lotze
2007-10-02 12:45:53 UTC
Permalink
Post by Roger Ineichen
Probably we should say;
"Pagelets are views which support the publisher __call__ attribute and
provide the update/render pattern."
True.
Post by Roger Ineichen
You are wrong here. A IContentProvider doesn't define content. A
IContentProvider provides content. That's different.
I see difference between creating content and providing it by a content
provider interface, but since the content created by some code must
somehow be passed to whatever then provides IContentProvider if it isn't
the same object anyway, that "some code" might as well provide
IContentProvider itself. In the case of pagelets the implementation does
that already anyway.
Post by Roger Ineichen
I a component defines content it provides the IPresentation interface
which is the case for IPagelet.
No, it isn't. The ancestry of IPagelet doesn't include anything named
IPresentation or similar.
Post by Roger Ineichen
A IContentProvider knows only how to get content for another component.
Again, it's a delegation pattern.
So what's the business with all that delegation? Why must the source of
content be distinct from the content provider? It certainly isn't that way
for viewlets. What more is there to the delegation than in the case of
pagelets, the need to access the same pagelet instance for creating
content that has already been instantiated as the view?
Post by Roger Ineichen
You are saying, that we have IContentProvider providing content and
defining content. Define content is the part of the IPresentation
interface.
Which, in turn, does appear in the ancestry of IContentProvider. Provision
of IPresentation doesn't seem to be a reason for pagelets not to be
content providers.
Post by Roger Ineichen
Probably I don't understand this correct. Are you thinking about a
IContentProvider which collects more then one pagelet?
Exactly. Or rather, more than one content provider, more than one of which
might just happen to be pagelets if someone thought it might make sense to
also use them that way directly.
Post by Roger Ineichen
Probably I don't
see your idea. Can you descibe it what do you mean with "as long as ...
page of its own" and "pagelet as content provider".
Well, z3c.form is about creating an HTML form from a schema. Such a form
appears somewhere on a page, which might be the place the pagelet content
ought to go. If this is all you want, the implementation of a form as a
pagelet is fine. However, you might want something more complex to fill
that place, something that contains a form among other elements. Now
you're in a pinch: you want to use z3c.form for its functionality of
assembling an HTML form from a schema, but what you get is a pagelet that,
by being denied recognition as a content provider, shouldn't be used as a
part of what makes up the pagelet content.
Post by Roger Ineichen
I don't understand how a pagelet can get called as a content provider.
The adaption doesn't work because they support different __init__ method
signatures.
Unless I'm mistaken, this has to do with the way view classes are created
by the ZCML viewlet directive - which is how I've used it so far.
Post by Roger Ineichen
Did you recognize that the __init__ are different.
def __init__(self, context, request, view)
An interface does not define the constructor signature of classes that
might implement it. Interfaces are about communicating with instances of
classes implementing them, not about creating those instances.
Post by Roger Ineichen
I guess there is nothing wrong with your idea, you can allways mix
IContentProvider and IPagelet in a new interface. But the existing
implementation of IPagelet is not a IContentProvider out of the box.
I think that it would be better to define pagelets to be content providers
so as to know what to deal with than to have to repeat that
IContentProvider thing for every extension interface and implementation.
It's not as if IContentProvider was all that specific anyway. Having to
add it explicitly again and again sounds like a dead chicken.
Post by Roger Ineichen
A IPagelet called by the IContentProvider TALES expression whould have
to support __init__(self, context, request, view) which isn't the case
in the Pagelet implementation.
This isn't the interface's business but sounds more like a factory
function that instantiates the pagelet without passing the view to the
constructor and adds it as the __parent__ attribute afterwards.
Post by Roger Ineichen
Does this make sense for you?
I understand the problems that have to be solved, but as long as you're
talking about __init__ being specified in interfaces, it doesn't make
sense to me.
Post by Roger Ineichen
what do you think about to remove the formlib implementation from the
z3c.pagelet package?
I think it would make things cleaner and make it easier to see what
belongs where. Plus there's possibly not much need to wrap zope.formlib in
pagelets given the existence of z3c.form. Removing the stuff sounds like
applying "there ought to be only one way to do it", so I'm all for it.
--
Thomas
Loading...