Re: [Zope3-Users] Specialized URL traversal.. Best way?

2006-01-10 Thread Marius Gedminas
On Tue, Jan 03, 2006 at 05:37:30PM -0500, Wade Leftwich wrote:
> Marius Gedminas wrote:
> > On Thu, Dec 29, 2005 at 11:22:28PM -0700, Jeff Shell wrote:
> >>Again, this is to have URLs like:
> >>
> >>myapp/@@tags/zope/viewlet
> 
> How about this? It gives
> zope.app.publication.publicationtraverse.PublicationTraverse.traverseName()
> some extra work, but it doesn't mess with the request and leaves
> request.URL reflecting the entire "path".
> 
> ###
> class BrowserViewStopTraversal(BrowserView):
> implements(IPublishTraverse)
>
> def __init__(self, context, request):
> self.context = context
> self.request = request
> self.traverse_subpath = []
> 
> def publishTraverse(self, request, name):
> self.traverse_subpath.append(name)
> return self
> 
> def __call__(self):
> """Just for example"""
> return ("traverse_subpath = %s\nrequest.URL = %s" %
> (self.traverse_subpath, self.request.URL))

I like it.
 
Marius Gedminas
-- 
The advertisement is the most truthful part of a newspaper.
-- Thomas Jefferson


signature.asc
Description: Digital signature
___
Zope3-users mailing list
Zope3-users@zope.org
http://mail.zope.org/mailman/listinfo/zope3-users


Re: [Zope3-Users] Specialized URL traversal.. Best way?

2006-01-03 Thread Wade Leftwich
Marius Gedminas wrote:
> On Thu, Dec 29, 2005 at 11:22:28PM -0700, Jeff Shell wrote:
> 
>>Again, this is to have URLs like:
>>
>>myapp/@@tags/zope/viewlet
>>
>>And turn that into a catalog search for anyof {'zope', 'viewlet'}
>>
>>def publishTraverse(self, request, name):
>>namestack = request.getTraversalStack()
>>if name not in namestack:
>>namestack.append(name)
>>namestack.reverse()
>>tags = tuple(namestack)
>>request.setTraversalStack([])
>>
>>results = TaggedArticleFinder(self.__name__,self.__parent__,tags)
>>results.prepareSearch(request)
>>return results
>>
>>The 'TaggedArticleFinder' then provides an interface that a view can
>>be found for that displays the results. So I've got it all working
>>now...
> 
> 
> My coworker Albertas recently implemented something like this in
> SchoolTool (I've CCed him).  Unfortunately it turned out to have some
> unforeseen consequences, for example, request.URL does not contain the
> path elements you "eat" manually, breaking self-posting forms (those
> that use ) and our login
> mechanism.
> 
> 

How about this? It gives
zope.app.publication.publicationtraverse.PublicationTraverse.traverseName()
some extra work, but it doesn't mess with the request and leaves
request.URL reflecting the entire "path".

###
from zope.interface import implements
from zope.publisher.interfaces import IPublishTraverse
from zope.app.publisher.browser import BrowserView

class BrowserViewStopTraversal(BrowserView):
implements(IPublishTraverse)
def __init__(self, context, request):
self.context = context
self.request = request
self.traverse_subpath = []

def publishTraverse(self, request, name):
self.traverse_subpath.append(name)
return self

def __call__(self):
"""Just for example"""
return ("traverse_subpath = %s\nrequest.URL = %s" %
(self.traverse_subpath, self.request.URL))

###
http://namespaces.zope.org/zope";
xmlns:browser="http://namespaces.zope.org/browser";
i18n_domain="travtest"
>
  

###

http://localhost:8080/@@stoptrav/foo/bar/baz  =>
  traverse_subpath = [u'foo', u'bar', u'baz']
  request.URL = http://localhost:8080/@@stoptrav/foo/bar/baz

-- Wade Leftwich
Ithaca, NY



___
Zope3-users mailing list
Zope3-users@zope.org
http://mail.zope.org/mailman/listinfo/zope3-users


Re: [Zope3-Users] Specialized URL traversal.. Best way?

2005-12-31 Thread Jeff Shell
On 12/31/05, Marius Gedminas <[EMAIL PROTECTED]> wrote:
> On Thu, Dec 29, 2005 at 11:22:28PM -0700, Jeff Shell wrote:
> > Again, this is to have URLs like:
> >
> > myapp/@@tags/zope/viewlet
> >
> > And turn that into a catalog search for anyof {'zope', 'viewlet'}
> >
> > def publishTraverse(self, request, name):
> > namestack = request.getTraversalStack()
> > if name not in namestack:
> > namestack.append(name)
> > namestack.reverse()
> > tags = tuple(namestack)
> > request.setTraversalStack([])
> >
> > results = TaggedArticleFinder(self.__name__,self.__parent__,tags)
> > results.prepareSearch(request)
> > return results
>
> My coworker Albertas recently implemented something like this in
> SchoolTool (I've CCed him).  Unfortunately it turned out to have some
> unforeseen consequences, for example, request.URL does not contain the
> path elements you "eat" manually, breaking self-posting forms (those
> that use ) and our login
> mechanism.

Yeah, I know of that problem. Looking back, it looks like there have
been a couple of ways of doing this. In Zope 2, there are a couple of
prominent "cool path tricks" in the core content objects. Python
Scripts allow you to get at the rest of the path. But the resulting
affect is like you describe: the traversal stack is chopped off, and
all URLs are relative to the script. We did a pretty cool ECommerce
store in all Python Scripts and SQL Methods that did this to have URLs
to products and categories, building up queries along the way. We
quickly discovered that relative URLs didn't work in that scenario, so
"./product/${product_id}" wouldn't work. I can see why it does this
though - you didn't actually traverse to an object at that point in
the path, so the request.parents attribute can't really have [, , , , , ] in it, when  just takes the
rest of the path and turns it into various script/object calls and
queries.

Zope 2 SQL Methods, on the other hand, allowed you do to direct
traversal and turn a URL into a query. This may have even existed in
the pre-principia version of Aqueduct. So for a two-category
classified system you can do URLs like:

/categorylist/category1_id/34/category2_id/12/list_ads.dtml

What it does is actually create non-persistent traversable objects
that implement the __bobo_traverse__ method. It accumulates the parts
of the URL and somewhere along the way does the search. Acquisition
binding and all of that still worked since the result was ultimately
an object that was bound to the right parent.

The code (In Zope 2: Shared/DC/ZRDB/DA.py, class Traverse) is rather
old and cryptic, but it does provide an example of the other way of
doing custom maps - traverse each name individually and create new
objects along the way. This way, request.URL is not affected. If you
were trying to make a custom traverser like date based archive
searching and where at 2005/12/ in the url, you could then just have
 to go to the date.

Both situations have their uses. They also have their consequences and
side effects. Playing with the traversalStack seems fine when you
don't need to do anything relative [per say] to the current URL. I
almost always use URL generators, either absolute URL or in the case
of the tags view I made I construct the joined URL in the view, so
this hasn't affected me too much yet.

But I'd certainly like to have the second option. The underlying tools
are there, but knowing which traversal interface / adapter to apply
isn't easy right now... Is __getitem__ enough? No one seems to have a
good answer. IPublishTraverse? ITraversable? It seems like
IPublishTraverse is the best one since it's from zope.publisher and
not zope.app, and is specific to object / URL publishing. But that
comes back to my dilemma:

Is it cool to play with the traversal stack in publishTraverse? Why
isn't 'furtherPath' part of the publishTraverse interface, but part of
zope.app.traversing.interfaces.ITraversable's traverse? Why doesn't
browser traversal seem to use zope.app...ITraversable?

Oh man. Here it is, New Years Eve, I've got errands to run for my dog
that I was going to go do an hour ago, yet here I sit consumed by an
idea that I'd love to try but should put off to some other time.
Basically it would be nice to specify a map... somehow.. for long URLs
that are used to construct queries. A view object could use this map
to match a URL piece by piece by traversing it one by one and making
"proper" objects along the way that are locatable. When it gets to the
end of the match, it could call a provided factory for that particular
Map and pass in the matched URL since the start of the view as a list
or mapping. This suite of tools could provide some map constructors
that allow one to specify repeating path parts. The rest of the URL
would still be in place, and maybe that final object could have more
traversal happen after it, such as view getting. A quick example of
what I'm thinking:

Re: [Zope3-Users] Specialized URL traversal.. Best way?

2005-12-31 Thread Marius Gedminas
On Thu, Dec 29, 2005 at 11:22:28PM -0700, Jeff Shell wrote:
> Again, this is to have URLs like:
> 
> myapp/@@tags/zope/viewlet
> 
> And turn that into a catalog search for anyof {'zope', 'viewlet'}
> 
> def publishTraverse(self, request, name):
> namestack = request.getTraversalStack()
> if name not in namestack:
> namestack.append(name)
> namestack.reverse()
> tags = tuple(namestack)
> request.setTraversalStack([])
> 
> results = TaggedArticleFinder(self.__name__,self.__parent__,tags)
> results.prepareSearch(request)
> return results
> 
> The 'TaggedArticleFinder' then provides an interface that a view can
> be found for that displays the results. So I've got it all working
> now...

My coworker Albertas recently implemented something like this in
SchoolTool (I've CCed him).  Unfortunately it turned out to have some
unforeseen consequences, for example, request.URL does not contain the
path elements you "eat" manually, breaking self-posting forms (those
that use ) and our login
mechanism.

> I was wondering - is this the best way to do this? Is there a better
> recipe floating around out there?

I would also like to know that.

Marius Gedminas
-- 
Any sufficiently advanced Operating System is indistinguishable from Linux.
-- Jim Dennis


signature.asc
Description: Digital signature
___
Zope3-users mailing list
Zope3-users@zope.org
http://mail.zope.org/mailman/listinfo/zope3-users


Re: [Zope3-Users] Specialized URL traversal.. Best way?

2005-12-30 Thread Wade Leftwich
Jeff Shell wrote:
> [snip]
> 
> I was wondering - is this the best way to do this? Is there a better
> recipe floating around out there? I appreciate Zope's direct-to-object
> URL publishing (been using it since '97!), but custom URL maps past a
> certain object like a view seem to be quite tricky, whereas Django and
> generic toolkits like Routes are specializing in ways of managing
> custom URL maps. I know there are a few places where one can take over
> this process, but it's not obvious when and how to use them, or which
> to use. BeforeTraversal event? publishTraverse? ITraversable?
> ITraversing? Ultimately I'd like to put a couple of views into the
> root of my app that can do something akin to Django's url_dispatch:
> 
> http://www.djangoproject.com/documentation/url_dispatch/
> 
> where a set of patterns and a name are used to allow for various
> dynamic queries. The name would be used to look up a component to
> respond to the matched items in the path. It wouldn't interfere with
> any other traversal (ie - wouldn't replace the default way of doing
> it). Doing it from a browser view seems safest, since this is almost
> exclusively about keeping nice URLs for web browsing. I just want to
> know the best place to plug in.

I don't have an answer, but I am also hoping to get some advice on the
best way to get what in a Z2 PythonScript is called 'traverse_subpath'.

 Chris Withers and I were both asking about this back on Dec 15 in the
"What's the rationale of @@?" thread
(http://mail.zope.org/pipermail/zope3-users/2005-December/001684.html),
but I didn't see an answer. Still haven't figured it out for myself,
still hoping for some help.

-- Wade Leftwich
Ithaca, NY

___
Zope3-users mailing list
Zope3-users@zope.org
http://mail.zope.org/mailman/listinfo/zope3-users


[Zope3-Users] Specialized URL traversal.. Best way?

2005-12-29 Thread Jeff Shell
This week I've been revisiting some of my early Zope 3 ideas in a
small new application we plan to use internally. One of the core
concepts of this system is 'tagging', similar to del.icio.us, flickr,
snippets, etc. Old versions that I wrote managed tags manually, with a
'taglib' object and tags being their own indexes that manually tracked
the documents that mentioned them. I wanted to use the catalog, but
the required indexes weren't available or usable by me at the time,
and then other projects came along.

In the last version I wrote prior to now, I wrote a custom Traversable
adapter for this 'taglib', which was BTreeContainer.

zope.app.traversing.interfaces.ITraversable - traverse(name, furtherPath)

I used 'furtherPath' to go along and turn paths like
'zope/enterprise/cms' into tags to search (again, using a manual
system due to lack of catalog). Since this was on a custom container,
it somehow worked.

So today, I thought I could provide a similar adapter, but on a view
object, that could get the rest of the requested path in one swoop
that I could then use to query a SetIndex in the catalog. But no
matter what I did, I couldn't get it to work. It doesn't seem like my
ITraversable gets called at all for my view - even with that view
providing the interface I say I adapt and on and on. I could get my
traversable adapter from the interpreter, but it wasn't ever touched
during the zope.publisher publication process. At best, I figured that
'publishTraverse()' was where I needed to go based on the errors that
I kept having. But publishTraverse() deals with one name at a time...
But it does pass in the request. And at most, I guessed that the
traversal stack was what I needed. Again, this is to have URLs like:

myapp/@@tags/zope/viewlet

And turn that into a catalog search for anyof {'zope', 'viewlet'}

def publishTraverse(self, request, name):
namestack = request.getTraversalStack()
if name not in namestack:
namestack.append(name)
namestack.reverse()
tags = tuple(namestack)
request.setTraversalStack([])

results = TaggedArticleFinder(self.__name__,self.__parent__,tags)
results.prepareSearch(request)
return results

The 'TaggedArticleFinder' then provides an interface that a view can
be found for that displays the results. So I've got it all working
now... But it seems kindof awkward. There are a few different
traversing options, and knowing which one applies when is difficult to
figure out. And monkeying with the traversal stack.. Is that really
what I should be doing here? It seems like the interface for
ITraversable that specified 'furtherPath' is what I'd like to be using
when I'm wanting to play with the whole path from this point on.

I ultimately want to provide a few more options similar to this one
for things like date based filtering (urls like @@bydate/2005/12 or
2005/12/29). None of these are containers or real objects, just URL
segments used to construct a query.

I was wondering - is this the best way to do this? Is there a better
recipe floating around out there? I appreciate Zope's direct-to-object
URL publishing (been using it since '97!), but custom URL maps past a
certain object like a view seem to be quite tricky, whereas Django and
generic toolkits like Routes are specializing in ways of managing
custom URL maps. I know there are a few places where one can take over
this process, but it's not obvious when and how to use them, or which
to use. BeforeTraversal event? publishTraverse? ITraversable?
ITraversing? Ultimately I'd like to put a couple of views into the
root of my app that can do something akin to Django's url_dispatch:

http://www.djangoproject.com/documentation/url_dispatch/

where a set of patterns and a name are used to allow for various
dynamic queries. The name would be used to look up a component to
respond to the matched items in the path. It wouldn't interfere with
any other traversal (ie - wouldn't replace the default way of doing
it). Doing it from a browser view seems safest, since this is almost
exclusively about keeping nice URLs for web browsing. I just want to
know the best place to plug in.
___
Zope3-users mailing list
Zope3-users@zope.org
http://mail.zope.org/mailman/listinfo/zope3-users