the beginnings of megrok.feeds

View: New views
6 Messages — Rating Filter:   Alert me  

the beginnings of megrok.feeds

by Brandon Craig Rhodes :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I have started writing a "megrok.feeds" package that will let you easily
turn container-like objects into Atom and RSS feeds, and objects in your
containers into items inside of those feeds.  (Should I call this
"megrok.syndication" instead?  It takes longer to type.)  You can look
inside the Zope repository to see what I have done so far.

Some of you might recall that I have differences with Derek Richardson,
the author of "vice.outbound", about how his work should be extended to
create "megrok.feeds".  I had initally imagined that, for each Grok
container which could support a feed, the Grok programmer would write
something like:

    class FolderFeed(megrok.feeds.AtomFeed):
        grok.name('atom')
        grok.context('Folder')
        def update(self):
            self.title = Folder %r Feed' % self.name
            self.description = 'Recent changes to folder %r' % self.name
            ...

And I would write a grokker that did roughly what a grok.View grokker
does, except that there would be no choice of template (an "atom.pt"
from "megrok.feeds" would be used automatically), and there might be a
bit more logic under the covers to gather any extra information that the
feed needed.

 <SIDE QUESTION>
 Why does the "ViewGrokker" in Grok's "meta.py" call "provideAdapter",
 which I think is a global registration command, when registering a
 View?  Shouldn't it instead register the view as a local adapter inside
 of its particular Grok site?  Imagine that I have a Python module that
 provides "Foo" objects, and I instantiate two different Grok apps in my
 database that both use "Foo" objects; to be concrete, imagine that
 "app1" defines a "/one" view on a "Foo" object and that "app2" defines
 a "/two" view.  Since the grokker defines each view globally, then it
 seems that not only would these two desired URLs work:

    http://localhost:8080/app1/foo/one
    http://localhost:8080/app2/foo/two

 but also the two unwanted URLs:

    http://localhost:8080/app1/foo/two
    http://localhost:8080/app2/foo/one

 because the global registrations would make each application's views
 magically appear over in the other application?
 </SIDE QUESTION>

Derek instead advocated a different approach.  First, the application
designer would define, say, "/atom" as the way to view any feed-able
container as an Atom feed.  Second, they would then write an adapter for
each kind of container that they wanted turned into a feed.  The result
in Grok code might look like:

    class Atom(megrok.feeds.AtomFeed):
        grok.name('atom')

    class FolderFeed(megrok.feeds.Feed):
        grok.context('Folder')
        def update(self):
            self.title = Folder %r Feed' % self.name
            self.description = 'Recent changes to folder %r' % self.name
            ...

After thinking about Derek's scheme for two or three weeks, I realized
that it did have at least one nice feature: it forced programmers to use
the same name for feeds across their whole site.  With my example scheme
shown up above, if a programmer was not careful then they could wind up
with all sorts of names for a given kind of feed on a given site
('/atom', '/Atom', '/feed', etcetera) - and sites whose feed names are
inconsistent are really annoying.  Whereas with Derek's scheme, they
just say once "Atom feeds are located at /atom for all my containers",
and don't have to repeat the name over and over again for each container
that they describe how to feed-ify.

So because I like the idea of consistency, I tried doing things Derek's
way; you can take a look at the Grokkers here:

http://svn.zope.org/megrok.feeds/trunk/src/megrok/feeds/meta.py?rev=88618&view=auto

As you can see, per Derek's design, there are three registrations that
have to get done before an Atom feed can work; for example, for the
classes defined above, this would look like:

 - The feed view itself has to be registered as a multi-adapter:
   (factory=Atom, adapts=(IFeedable, IBrowserRequest), name='atom')

 - The adapter that turns the container into the feed is a single-adapter:
   (factory=FolderFeed, adapts=(Feed,), provides=IFeed)

 - The container type itself has to be marked as feedable:
   classImplements(Folder, IFeedable)

That way, when you say 'myfolder/atom', the "Atom" view will get
activated because 'myfolder' will be marked as "IFeedable", then it will
try to adapt its context to IFeed, and will succeed because the adapter
to IFeed exists.

In my recent exchange with Derek, I objected to this scheme because it
seemed odd to have to have so many interfaces just to get a single view
working.  Again, I'm rethinking that, because it would be so useful to
corral Grok developers into naming only once what they will call each
kind of feed on their site.

My big issue at the moment, though, which I guess is reflected in the
big "SIDE QUESTION" up above, is that I have no idea how to make any of
this local.  If the developer runs two Grok apps inside of a single Zope
instance, and one app made the decision that "/atom" is how you ask for
an Atom feed but the other app named its syndication links "/feed"
instead, how do I keep the results of these decisions "local" to each
app?  If "/atom" is registered sitewide through a "provideAdapter()"
call, then I don't see at all how it can affect only the current Grok
app and not others inside of the same instance.

I know it's odd to hear me ask about running multiple Grok apps in the
same instance, because I've complained before that it makes little sense
and that the extra "/app" part of every Grok URL is just an annoyance.
But if we're going to support them, then I need to understand how we
keep them separate from each other's active views; and, at the moment, I
don't see how this is done.

--
Brandon Craig Rhodes   brandon@...   http://rhodesmill.org/brandon
_______________________________________________
Grok-dev mailing list
Grok-dev@...
http://mail.zope.org/mailman/listinfo/grok-dev

Re: the beginnings of megrok.feeds

by Christian Theune-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Sat, 2008-07-19 at 17:36 -0400, Brandon Craig Rhodes wrote:

>  <SIDE QUESTION>
>  Why does the "ViewGrokker" in Grok's "meta.py" call "provideAdapter",
>  which I think is a global registration command, when registering a
>  View?  Shouldn't it instead register the view as a local adapter inside
>  of its particular Grok site?  Imagine that I have a Python module that
>  provides "Foo" objects, and I instantiate two different Grok apps in my
>  database that both use "Foo" objects; to be concrete, imagine that
>  "app1" defines a "/one" view on a "Foo" object and that "app2" defines
>  a "/two" view.  Since the grokker defines each view globally, then it
>  seems that not only would these two desired URLs work:
>
>     http://localhost:8080/app1/foo/one
>     http://localhost:8080/app2/foo/two
>
>  but also the two unwanted URLs:
>
>     http://localhost:8080/app1/foo/two
>     http://localhost:8080/app2/foo/one
>
>  because the global registrations would make each application's views
>  magically appear over in the other application?
>  </SIDE QUESTION>
Only if your 'Foo' objects really refer to the same class objects.

Non-persistent configuration is a good thing if it works for you.
Maintaining component registration in the database can be a huge
drawback WRT to code restructuring/deprecation.

--
Christian Theune · ct@...
gocept gmbh & co. kg · forsterstraße 29 · 06112 halle (saale) · germany
http://gocept.com · tel +49 345 1229889 7 · fax +49 345 1229889 1
Zope and Plone consulting and development



_______________________________________________
Grok-dev mailing list
Grok-dev@...
http://mail.zope.org/mailman/listinfo/grok-dev

signature.asc (196 bytes) Download Attachment

Re: the beginnings of megrok.feeds

by Brandon Craig Rhodes :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Christian Theune <ct@...> writes:

> On Sat, 2008-07-19 at 17:36 -0400, Brandon Craig Rhodes wrote:

>>  Why does the "ViewGrokker" ... call "provideAdapter", which ...  is
>>  a global registration command...?  Shouldn't it instead register the
>>  view as a local adapter inside of its particular Grok site?  Imagine
>>  that ...  I instantiate two different Grok apps in my database that
>>  both use "Foo" objects ...  it seems that ... the global
>>  registrations would make each application's views magically appear
>>  over in the other application?
>
> Only if your 'Foo' objects really refer to the same class objects.

Yes, which is precisely what I am imaging; that two Grok apps, for
example, might both provide views for a single class, like the standard
library class "email.Message".

> Non-persistent configuration is a good thing if it works for you.
> Maintaining component registration in the database can be a huge
> drawback WRT to code restructuring/deprecation.

Thank you, Christian; while puzzling over why Grok uses global
registrations for views that should obviously only exist beneath each
particular Grok app, I forgot that local adapters are currently
implemented using the ZODB.

It is now clear to me that I need to make some proposals.

1. Grok Local Adapters Should Not Live In The Database
------------------------------------------------------

I am beginning to think it is entirely misguided that Grok attaches
local adapters to Application objects through the database.  This seems
to have only bad consequences.  Instead, when Grok code declares a local
adapter and asks that it be installed on a Grok Site, this should be
something done in RAM, at runtime, as part of grokking.  Zope traversal
should be extended, if it does not already support the feature directly,
so that local adapters can get activated as it traverses past an object
of a particular class.

In other words, if I create a local adapter "X" in my "EmailSite" Grok
Application, then at grokking time some Zope registry (which we might
have to create) mapping classes to local adapters should get the
registration:

   "EmailSite class objects, when traversed, activate local adapter X"

Then, when Zope is traversing into our App objects, the correct adapters
get activated.  Beautiful!  This would have the magnificent property
that when someone added a new local adapter to their code and restarted,
it would immediately start working without their having to delete and
re-create their Application object; and, when someone removed a local
adapter, it would immediately start working.

In Grok, we declare things in code.  They should stay there.

2. We Should Rename LocalAdapter to PersistentLocalAdapter
----------------------------------------------------------

We should keep the current local adapters around; I am not suggest that
we delete or remove them!  Someone might have found them useful, and, if
so, they should still be able to use them.  But they should have the
word "Persistent" attached to them so that anyone crazy enough to use
them gets a big, obvious signal that unlike most of the things that they
create in Grok - like Views and Viewlets - PersistentLocalAdapters will
*not* simply work because they exist in the code.  The word "Persistent"
will be a hint that this is a crazy hybrid concept that straddles the
world of code and the world of storage, and that has to exist in *both*
places (both in your code, and also in the database with your
application) before it will work.

3. Views and Viewlets Should Become New-Style Local Adapters
------------------------------------------------------------

Once we have working the concept of lightweight, non-persisted,
traversal-activated adapters working, then all normal Grok adapters like
Views and Viewlets should become new-style local adapters.  If your Grok
app defines an "EmailIndex" view that renders an "email.Message" object
for your site, then the "EmailIndex" should only be active and available
when a user is actually browsing beneath your Grok app.  Other apps
should not have the view available, since this makes it impossible to
install several Grok apps inside of a single ZODB instance without their
views bleeding over and becoming available inside each other.

This will require a small bit of code so that the grokkers will "see"
where your Application object is inside of your Grok application code
base, so that they can make all of your Views these new-style local
adapters.  It might now become an error (I'm not sure it is right now?)
to have two grok.Application objects inside of a Grok application; or we
might allow a single code base to provide multiple Applications so long
as the user could signal which views went with which others.

Anyway, remember that I have always been a bit skeptical of why we
create Application instances in the first place instead of a Grok
Application just being always the root of its site; but if we are going
to support multiple Grok apps in a single ZODB, as we do today, then the
above steps seem to me quite necessary to stop them from trampling all
over each other.

ME GROK WANT APPLICATION ORTHOGONALITY :-)

--
Brandon Craig Rhodes   brandon@...   http://rhodesmill.org/brandon
_______________________________________________
Grok-dev mailing list
Grok-dev@...
http://mail.zope.org/mailman/listinfo/grok-dev

Re: the beginnings of megrok.feeds

by TIm Terlegård-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Jul 21, 2008, at 2:27 PM, Brandon Craig Rhodes wrote:

> Christian Theune <ct@...> writes:
>> On Sat, 2008-07-19 at 17:36 -0400, Brandon Craig Rhodes wrote:
>
>>> Non-persistent configuration is a good thing if it works for you.
>> Maintaining component registration in the database can be a huge
>> drawback WRT to code restructuring/deprecation.
>
> Thank you, Christian; while puzzling over why Grok uses global
> registrations for views that should obviously only exist beneath each
> particular Grok app, I forgot that local adapters are currently
> implemented using the ZODB.
>
> It is now clear to me that I need to make some proposals.
>
> 1. Grok Local Adapters Should Not Live In The Database
> ------------------------------------------------------
>
> I am beginning to think it is entirely misguided that Grok attaches
> local adapters to Application objects through the database.  This  
> seems
> to have only bad consequences.

I think it's more common this happens for utilities. But I agree that  
grok should
not persist utilities or adapters if there are ways not to do that.

I don't have any experience of z3c.baseregistry, but I think it allows  
you to
add local utilities with zcml.

     http://svn.zope.org/z3c.baseregistry/trunk/src/z3c/baseregistry/README.txt?rev=70114&view=auto

snip...


> Anyway, remember that I have always been a bit skeptical of why we
> create Application instances in the first place instead of a Grok
> Application just being always the root of its site

I agree the use of application is a bit weird. It's been discussed  
before,
but it didn't look anyone agreed with me. As it is now, an application  
is
not necessarily the root of the website. Have no idea why anyone would
want to nest grok.Application objects. It just makes stuff more  
complicated,
at least educationally.

But I'm not sure this has to be resolved with traversers. The registries
and their hierarchy will always be the same on every traversal.

/Tim
_______________________________________________
Grok-dev mailing list
Grok-dev@...
http://mail.zope.org/mailman/listinfo/grok-dev

Re: the beginnings of megrok.feeds

by Brandon Craig Rhodes :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Christian Theune <ct@...> writes:

> On Sat, 2008-07-19 at 17:36 -0400, Brandon Craig Rhodes wrote:
>
>>  Imagine that ... I instantiate two different Grok apps in my
>>  database that both use "Foo" objects ...  [will] global
>>  registrations ... make each application's views magically appear
>>  over in the other application?
>
> Only if your 'Foo' objects really refer to the same class objects.

At the very least, think about all of those Viewlets and macros that
seem to get attached to Python classes like "Interface" these days!

If three Grok applications were installed in a single site that all had
views built atop "Interface", then I think that under the current scheme
(which, as outlined in a recent email, I would like to change) there
would be no way from stopping people from trying to invoke each
application's views atop objects from the other applications.

--
Brandon Craig Rhodes   brandon@...   http://rhodesmill.org/brandon
_______________________________________________
Grok-dev mailing list
Grok-dev@...
http://mail.zope.org/mailman/listinfo/grok-dev

local but-non-persistent registration of components

by Martijn Faassen-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hey,

I saw that a discussion on megrok.feeds evolved towards a discussion of
local-but-non-persistent registration of components such as views,
adapters and utilities.

I'd be nice to have this feature. I think we have two areas of discussion:

* how to actually do it technically - how do we make sure these locally
registered components are correctly known as 'registered' in a site when
starting up the application?

* what a nice syntax for this might be to make this work for the various
kinds of components (or what the impact would be to make grok do this
automatically in some cases)

Regards,

Martijn

_______________________________________________
Grok-dev mailing list
Grok-dev@...
http://mail.zope.org/mailman/listinfo/grok-dev