Traverser, Request and URL mess

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

Traverser, Request and URL mess

by Souheil CHELFOUH :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hello Grokkers !

I'm currently working on grokui.base and grokui.admin
With Uli, we decided to use a namespace for the views, to get a cleaner base.

Everything is working nicely. The views are registered for a skin
layer, the skin is applied on traversal by a namespace traverser,
++grokui++. However, when an application is created, we'd like to be
able to acces its URL without having the traverser ++grokui++ added in
the request. I couldn't find an easy way to do that without
duplicating the request and modifying the _app_names. I found 2
solutions for that :

# This is totaly ugly, but it works without much effort :)
url = absoluteURL(application, request).replace('/++grokui++', '')


# This is nicer, but maybe there's another solution :
class GrokUINamespace(grok.MultiAdapter):
    grok.name('grokui')
    grok.provides(ITraversable)
    grok.adapts(IRootFolder, browser.IBrowserRequest)

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

        annotations = IAnnotations(request)
        grokui_info = annotations.get('grokui', None)
        if grokui_info is None:
            grokui_info = annotations['grokui'] = {}
        # we get the root url before the ++grokui++ is shifted
        # and use this URL to compute the application one
        grokui_info['root_url'] = request.getApplicationURL()

        applySkin(self.request, GrokUISkin)
        request.shiftNameToApplication()

    def traverse(self, name, ignore):
        return self.context


Anyone could help me, with any kind of trick/tip/opinion ?
The second solution works and is much nicer than the first one, but it
looks a bit hackish.
_______________________________________________
Grok-dev mailing list
Grok-dev@...
https://mail.zope.org/mailman/listinfo/grok-dev

Re: Traverser, Request and URL mess

by Martijn Faassen-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hey Souheil,

Souheil CHELFOUH wrote:

> I'm currently working on grokui.base and grokui.admin
> With Uli, we decided to use a namespace for the views, to get a cleaner base.

Thanks very much for doing this work!

> Everything is working nicely. The views are registered for a skin
> layer, the skin is applied on traversal by a namespace traverser,
> ++grokui++.

> However, when an application is created, we'd like to be
> able to acces its URL without having the traverser ++grokui++ added in
> the request. I couldn't find an easy way to do that without
> duplicating the request and modifying the _app_names.

We're talking about the ability to generate a URL to something in
another skin, correct? I.e. to generate a link to the application's URL,
and the application is *not* in the admin UI skin of course. The other
situation where this happens would be if you would want the root of the
site to redirect to the admin UI (which is in the ++grokui++ skin). But
we have the added complexity that ++grokui++ is its own namespace here,
instead of ++skin++grokui.

> I found 2
> solutions for that :
>
> # This is totaly ugly, but it works without much effort :)
> url = absoluteURL(application, request).replace('/++grokui++', '')

I think this is safe enough. It's ugly, but it has the virtue of being
short.

> # This is nicer, but maybe there's another solution :
> class GrokUINamespace(grok.MultiAdapter):
>     grok.name('grokui')
>     grok.provides(ITraversable)
>     grok.adapts(IRootFolder, browser.IBrowserRequest)
>
>     def __init__(self, context, request):
>         self.context = context
>
>         annotations = IAnnotations(request)
>         grokui_info = annotations.get('grokui', None)
>         if grokui_info is None:
>             grokui_info = annotations['grokui'] = {}
>         # we get the root url before the ++grokui++ is shifted
>         # and use this URL to compute the application one
>         grokui_info['root_url'] = request.getApplicationURL()
>
>         applySkin(self.request, GrokUISkin)
>         request.shiftNameToApplication()
>
>     def traverse(self, name, ignore):
>         return self.context

> Anyone could help me, with any kind of trick/tip/opinion ?
> The second solution works and is much nicer than the first one, but it
> looks a bit hackish.

Could you explain to me why you think the second solution is nicer? I
have a hard time even understand what could possibly be going on...
I don't think this is nicer, as it's totally complicated and it's hard
for me to understand what is going on. :) What *is* this doing?

If the problem indeed is about the ability to generate URLs to other
skins, this is a long-standing discussion with no conclusion. The story
appears to me that:

* we keep running into it

* it appears hard to devise a general solution

Since we keep runnign into it, perhaps we can come up with a more
limited solution, where it's at least possible to create URLs *without*
any ++skin++ bit in it, or to at least add ++skin++foo easily to an
existing URL (somewhere in the beginning). That won't cover all cases
(virtual hosts, namespaces not appearing at the root of the URL, other
things?) but it would cover a lot of them. We also need to make sure we
can handle your case, where instead of ++skin++foo, you just want ++foo++.

Perhaps we need an API like this:

self.url(..., namespace=('skin', 'foo')

to go to ++skin++foo

and:

self.url(..., namespace=('grokui',None)

to go to ++grokui++

and:

self.url(..., namespace=(None, None))

to have no special namespace.

the default would have namespace be None and it'd always generate URLs
within the same namespace then. This is what it does already.

I think it would probably simplest to make this work by simple but
well-tested string rewriting.

Regards,

Martijn

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

Re: Traverser, Request and URL mess

by Souheil CHELFOUH :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hello,

2009/10/10 Martijn Faassen <faassen@...>:
> Hey Souheil,
>
[SNIP !]

>
>> I found 2
>> solutions for that :
>>
>> # This is totaly ugly, but it works without much effort :)
>> url = absoluteURL(application, request).replace('/++grokui++', '')
>
> I think this is safe enough. It's ugly, but it has the virtue of being
> short.
>

Yes, I like short and easy solutions. The con was that I was looking
for a generic solution.


>> # This is nicer, but maybe there's another solution :
>> class GrokUINamespace(grok.MultiAdapter):
>>     grok.name('grokui')
>>     grok.provides(ITraversable)
>>     grok.adapts(IRootFolder, browser.IBrowserRequest)
>>
>>     def __init__(self, context, request):
>>         self.context = context
>>
>>         annotations = IAnnotations(request)
>>         grokui_info = annotations.get('grokui', None)
>>         if grokui_info is None:
>>             grokui_info = annotations['grokui'] = {}
>>         # we get the root url before the ++grokui++ is shifted
>>         # and use this URL to compute the application one
>>         grokui_info['root_url'] = request.getApplicationURL()
>>
>>         applySkin(self.request, GrokUISkin)
>>         request.shiftNameToApplication()
>>
>>     def traverse(self, name, ignore):
>>         return self.context
>

This is the declaration of our traverser ++grokui++
In here, I do adapt the request to IAnnotations, so I can annotate it.
Here, I use the "grokui" key to store the root URL of our zope BEFORE
we actually shift the grokui name into the request.
It is more generic and we keep the namespace handling in the namespace
declaration.

[cut cut cut]

> Since we keep runnign into it, perhaps we can come up with a more
> limited solution, where it's at least possible to create URLs *without*
> any ++skin++ bit in it, or to at least add ++skin++foo easily to an
> existing URL (somewhere in the beginning). That won't cover all cases
> (virtual hosts, namespaces not appearing at the root of the URL, other
> things?) but it would cover a lot of them. We also need to make sure we
> can handle your case, where instead of ++skin++foo, you just want ++foo++.
[cut more]

This is what I wanted to acheive. The problem is, the request is the
base of the URL generation and there's no way we can get it to return
the URL with one or more namespace ignore.
The mehod 'getApplicationURL' or 'getURL' are both using the
'_app_names', which contains all the shifted namespaces and there's no
way we can strip it off when computing an URL.
This is very annoying, it doesn't allow flexible URL computation. I
don't really know what would be a proper way to implement what you
propose and what I thought of. If anyone has experience in
manipulating the request for such purposes, please, enlight us ! :)

Thank you Martijn for your time

>
> Regards,
>
> Martijn
>
> _______________________________________________
> Grok-dev mailing list
> Grok-dev@...
> https://mail.zope.org/mailman/listinfo/grok-dev
>
_______________________________________________
Grok-dev mailing list
Grok-dev@...
https://mail.zope.org/mailman/listinfo/grok-dev

Re: Traverser, Request and URL mess

by Jan-Wijbrand Kolman-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Martijn Faassen wrote:
snip

> If the problem indeed is about the ability to generate URLs to other
> skins, this is a long-standing discussion with no conclusion. The story
> appears to me that:
>
> * we keep running into it
>
> * it appears hard to devise a general solution
>
> Since we keep runnign into it, perhaps we can come up with a more
> limited solution, where it's at least possible to create URLs *without*
> any ++skin++ bit in it, or to at least add ++skin++foo easily to an
> existing URL (somewhere in the beginning). That won't cover all cases
> (virtual hosts, namespaces not appearing at the root of the URL, other
> things?) but it would cover a lot of them. We also need to make sure we
> can handle your case, where instead of ++skin++foo, you just want ++foo++.

Right, this is something I run into as well every now and then.

> Perhaps we need an API like this:
>
> self.url(..., namespace=('skin', 'foo')
>
> to go to ++skin++foo
>
> and:
>
> self.url(..., namespace=('grokui',None)
>
> to go to ++grokui++
>
> and:
>
> self.url(..., namespace=(None, None))
>
> to have no special namespace.
>
> the default would have namespace be None and it'd always generate URLs
> within the same namespace then. This is what it does already.
>
> I think it would probably simplest to make this work by simple but
> well-tested string rewriting.

The problem is tough: there's really not an easy __generic__ solution
for this problem for the reasons you describe. As such, I think I like
your idea: to at least formalize the string rewriting.

Maybe the skin name in ``namespace=('skin', 'MySkinName')`` could even
be, optionally, derived from the skin component itself!

+1 for such an addition to the ``self.url()`` method.

regards,
jw

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

Re: Traverser, Request and URL mess

by Martijn Faassen-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Souheil CHELFOUH wrote:
[snip]

> This is what I wanted to acheive. The problem is, the request is the
> base of the URL generation and there's no way we can get it to return
> the URL with one or more namespace ignore.
> The mehod 'getApplicationURL' or 'getURL' are both using the
> '_app_names', which contains all the shifted namespaces and there's no
> way we can strip it off when computing an URL.
> This is very annoying, it doesn't allow flexible URL computation. I
> don't really know what would be a proper way to implement what you
> propose and what I thought of. If anyone has experience in
> manipulating the request for such purposes, please, enlight us ! :)

I think parsing the generated URL and messing around with the ++..++
bits might be all right in this case. Manipulating the request seems
scary to me as it might break subsequent URL generations.

Or is there a problem I don't see? I thought we could do this within
view.url() and grok.url().

Regards,

Martijn

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

Re: Traverser, Request and URL mess

by Leonardo Rochael Almeida :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Wed, Oct 14, 2009 at 17:39, Martijn Faassen <faassen@...> wrote:
> [...] Manipulating the request seems
> scary to me as it might break subsequent URL generations.

I'm not against manipulating strings, but just to answer the above
comment, we could always copy the request object and manipulate a copy
if we're afraid of messing with the original request.
_______________________________________________
Grok-dev mailing list
Grok-dev@...
https://mail.zope.org/mailman/listinfo/grok-dev