getitem access

0 views
Skip to first unread message

Remco Boerma

unread,
Jan 4, 2005, 3:16:24 AM1/4/05
to cherryp...@googlegroups.com
Hi all,

eurleif asks in #65 if it is possible to map parameters like /foo/42/bar/43/baz using another scheme as well.

We now use getattr to walk the object path, he sugests using item access as well. So that /foo/42 is mapped to
cpg.root.foo[42] or cpg.root.foo.42, depending on whatever is found first.

I've given a recipe on the ticket to show what (s)he can do about it, to resolve this issue using some object
based on the static parameters list that can be filled when root.foo is called with /foo/bar/34/baz/34/...

Do we want this kind of access in the core, or should it be a user sollution to a user specific problem?

Cheers!

Remco

Carlos Ribeiro

unread,
Jan 4, 2005, 3:36:18 AM1/4/05
to cherryp...@googlegroups.com
It's an interesting generalization. getitem checking also works on
dicts, so /foo/anything could be mapped to cpg.root.foo[anything]
(where foo is a dict). We have to keep in mind that this may also
cause some undesirable side effects as far as the current lookup
works; if we can be sure that no such side effect exists, I'm +1 on
it. If there's any side effect, -1.

(on the other hand, it can be argued that the user himself can convert
the objects published to support getattr; for example, nothing stops a
UserList or UserDict to support getattr with similar results to the
ones achieved by getitem with similar arguments.)

This ticket also raises an interesting discussion: today it's
difficult for a user to override the existing object mapping function.
The current function is inside a module, and the only way to override
it is to do some black magic and rebind the symbol inside the module
to a new function. I guess we could make it a little bit easier to
register such functions. One possibility is to bind such utility
symbols directly to the cpg structure, at its top level; in this way
it would be easier for the user to customize or override it.

Example:

cpg.mapPathToObject = myObjMapperFunction

Please not that I'm not talking about making the mapPathToObject()
function into a "special" function as filters; there should be only
one such function, not one per published object. What I'm proposing is
just to bind the symbol to the cpg structure so it can be easily bound
to another function byt the site programmer.

--
Carlos Ribeiro
Consultoria em Projetos
blog: http://rascunhosrotos.blogspot.com
blog: http://pythonnotes.blogspot.com
mail: carri...@gmail.com
mail: carri...@yahoo.com

Remco Boerma

unread,
Jan 4, 2005, 4:39:12 AM1/4/05
to cherryp...@googlegroups.com
Carlos Ribeiro wrote:
It's an interesting generalization. getitem checking also works on
dicts, so /foo/anything could be mapped to cpg.root.foo[anything]
(where foo is a dict). We have to keep in mind that this may also
cause some undesirable side effects as far as the current lookup
works; if we can be sure that no such side effect exists, I'm +1 on
it. If there's any side effect, -1.

  
Here is some strange behaviour:

>>> d = {}
>>> d.exposed = True
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AttributeError: 'dict' object has no attribute 'exposed'
>>> print getattr(d,'exposed')
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AttributeError: 'dict' object has no attribute 'exposed'
>>>

So checking if there is an exposed, would raise an error itself! (as it should provide None as default)
So we'll have to use other means of checking, or we can't use dictionaries right away. and keeping them all opened, doesn't seem safe to me.

(on the other hand, it can be argued that the user himself can convert
the objects published to support getattr; for example, nothing stops a
UserList or UserDict to support getattr with similar results to the
ones achieved by getitem with similar arguments.)
  
Like i did in the ticket. With full control. We might write a recipe about it, but i don't think it's something
to handle in the core. .
This ticket also raises an interesting discussion: today it's
difficult for a user to override the existing object mapping function.
The current function is inside a module, and the only way to override
it is to do some black magic and rebind the symbol inside the module
to a new function. I guess we could make it a little bit easier to
register such functions. One possibility is to bind such utility
symbols directly to the cpg structure, at its top level; in this way
it would be easier for the user to customize or override it.
  
Do we need to support that? If a user wants this to be changed, why can't he/she change the core code?
It's a python module!! I don't think we need to , unless the need really arises . .
cpg.mapPathToObject = myObjMapperFunction
  
Well, i don't see the need that much, but if we will change the structure for calling, i would be favouring this. . .

But i simply question how many people will be changing this.. Most of it can be done using regular cp2 'pages'.

The ticket gave me another question:

This one bit me not long ago. .i'm trying to reconstruct the problem while i'm at it. So if you don't have much time:
skip the rest of the email.

Summary: it shows some odd behaviour using index, default and regular methods...
<flames state=off>
<start of large post about parameter usage. . if anyone can use this for documentation purposes; go ahead>

What should, and will hapen using the following:
class Root(object);
    def index(self,*p):
          if p:
              print `p`
          else:
              print 'index!'
     index.exposed = True
cpg.root = Root()

Ok. if i go to "http://localhost'"  or http://localhost/" i will see "index!" if i add anything to the location bar, it will fail: http://localhost/bla/pir:
Traceback (most recent call last):
  File "C:\module\cp2\cherrypy\_cphttptools.py", line 206, in doRequest
    handleRequest(wfile)
  File "C:\module\cp2\cherrypy\_cphttptools.py", line 372, in handleRequest
    func, objectPathList, virtualPathList = mapPathToObject()
  File "C:\module\cp2\cherrypy\_cphttptools.py", line 504, in mapPathToObject
    raise cperror.NotFound # We didn't find anything
NotFound
So that doesn't work?!

now i add root.bla similar to index. .
    def bla(self,*p):
        if p:
            return  `p`
        else:
            return 'bla'
    bla.exposed = True

Okay. here goes: http://localhost/bla and http://localhost/bla/ work fine. . it displays "bla". .
and going to /bla/pir shows ('pir',)  .. perfect!! So something is wrong with index?. .

Now.

If if would change the bla, to expect 1 parameter, wich i would like to be defaulted, it's becoming a keyword parameter.
>>> bla()
>>> def bla(first='first',*p):
...    print first,p
...
>>> bla('pir')
pir ()
>>>


that's nice. . (though one might not expect this to happen, as it's a keyword parameter, but i like the behaviour)
So here's my new bla:
    def bla(self,first='first',*p):
        return  `first`,`p`
    bla.exposed = True

/bla returns ; ("'first'", '()')
/bla/pir/feedz/iz/doe returns ("'pir'", "('feedz', 'iz', 'doe')")
exactly what i want it to. .

Back to index.. .

i'll replace my index method with the following;
    def index(self,first='first',*p):
        return  `first`,`p`
    index.exposed = True

http://localhost:9000/index and http://localhost:9000/ both return: ("'first'", '()')
But if i move to /someothername it will crash, telling me:
Traceback (most recent call last):
  File "C:\module\cp2\cherrypy\_cphttptools.py", line 206, in doRequest
    handleRequest(wfile)
  File "C:\module\cp2\cherrypy\_cphttptools.py", line 372, in handleRequest
    func, objectPathList, virtualPathList = mapPathToObject()
  File "C:\module\cp2\cherrypy\_cphttptools.py", line 504, in mapPathToObject
    raise cperror.NotFound # We didn't find anything
NotFound
So we introduce root.default. . . This clearly solves the problem.
    def default(self,first='first',*p):
        return  'default:',`first`,`p`
    default.exposed = True

This solves nearly all of my problems!! now i will just delete the root.index, cause my default is the catch all (i assume)..
Now, all unkown pages, i except to be cought by the default. . . this would be perfect!!  (i was writing a wiki at the time,
so going to /wiki would come up with the wiki's frontpage.. that would be nice. . but. .
no, this doesn't work. . if i go to http://localhost/ and i have no root.index, i'm lost . . It is not caught by the default!!
so default is not run when there is no root.index and the index would be run if it was there...!

Traceback (most recent call last):
  File "C:\module\cp2\cherrypy\_cphttptools.py", line 206, in doRequest
    handleRequest(wfile)
  File "C:\module\cp2\cherrypy\_cphttptools.py", line 372, in handleRequest
    func, objectPathList, virtualPathList = mapPathToObject()
  File "C:\module\cp2\cherrypy\_cphttptools.py", line 504, in mapPathToObject
    raise cperror.NotFound # We didn't find anything
NotFound
so now i need to redirect my root.index to root.default. . .
a. - how do i do it simple, if default would use generators (thus return a generator) ?  cause
      root.index(self): return self.default() would clearly not be a sollution then
b. - can't default become the catch all, even for missing indexes? As i thing this behaviour would be more 'natural' and expected.


</start of large post about parameter usage. . if anyone can use this for documentation purposes; go ahead>
</flames>

I hope this can serve both for documentation purposes, as well as for feature request/bugreport . . .

and (okay, flame me for starting this infamous debate again). . .
if default would become the catch all, even for missing indexes, can't we simply drop default, and have index have the default behaviour as well?
I think it would be much simpler then. .


Cheers!
Remco

Sylvain Hellegouarch

unread,
Jan 4, 2005, 4:39:03 AM1/4/05
to cherryp...@googlegroups.com

I like the idea but on the other hand is there such a real need ?

>
> On Tue, 04 Jan 2005 09:16:24 +0100, Remco Boerma
<remco....@gmail.com> wrote:
> > Hi all,
> >
> > eurleif asks in #65 if it is possible to map parameters like
> > /foo/42/bar/43/baz using another scheme as well.
> >
> > We now use getattr to walk the object path, he sugests using item
access as
> > well. So that /foo/42 is mapped to
> > cpg.root.foo[42] or cpg.root.foo.42, depending on whatever is found
first.
> >
> > I've given a recipe on the ticket to show what (s)he can do about
it, to
> > resolve this issue using some object
> > based on the static parameters list that can be filled when root.foo is
> > called with /foo/bar/34/baz/34/...
> >
> > Do we want this kind of access in the core, or should it be a user
> > sollution to a user specific problem?
>
> It's an interesting generalization. getitem checking also works on
> dicts, so /foo/anything could be mapped to cpg.root.foo[anything]
> (where foo is a dict). We have to keep in mind that this may also
> cause some undesirable side effects as far as the current lookup
> works; if we can be sure that no such side effect exists, I'm +1 on
> it. If there's any side effect, -1.
>
> (on the other hand, it can be argued that the user himself can convert
> the objects published to support getattr; for example, nothing stops a
> UserList or UserDict to support getattr with similar results to the
> ones achieved by getitem with similar arguments.)
>
> This ticket also raises an interesting discussion: today it's
> difficult for a user to override the existing object mapping function.
> The current function is inside a module, and the only way to override
> it is to do some black magic and rebind the symbol inside the module
> to a new function. I guess we could make it a little bit easier to
> register such functions. One possibility is to bind such utility
> symbols directly to the cpg structure, at its top level; in this way
> it would be easier for the user to customize or override it.
>
> Example:
>
> cpg.mapPathToObject = myObjMapperFunction
>
> Please not that I'm not talking about making the mapPathToObject()
> function into a "special" function as filters; there should be only
> one such function, not one per published object. What I'm proposing is
> just to bind the symbol to the cpg structure so it can be easily bound
> to another function byt the site programmer.
>
> --
> Carlos Ribeiro
> Consultoria em Projetos
> blog: http://rascunhosrotos.blogspot.com
> blog: http://pythonnotes.blogspot.com
> mail: carri...@gmail.com
> mail: carri...@yahoo.com
>
>

- Sylvain

Sylvain Hellegouarch

unread,
Jan 4, 2005, 4:41:50 AM1/4/05
to cherryp...@googlegroups.com

> and (okay, flame me for starting this infamous debate again). . .
> _if default would become the catch all, even for missing indexes, can't
> we simply drop default, and have index have the default behaviour as well?
> _I think it would be much simpler then. .

Remi insists to keep both and he has some good points for this so maybe
it's time we stop arguing the case :)

- Sylvain

Remco Boerma

unread,
Jan 4, 2005, 4:50:50 AM1/4/05
to cherryp...@googlegroups.com
Please, continue the docs i started in the mail, and explain how to forward the index to the default if you want that behaviour
without having problems with the generator issue. .

Cheers!
Remco

Remco Boerma

unread,
Jan 4, 2005, 4:53:12 AM1/4/05
to cherryp...@googlegroups.com
Sylvain Hellegouarch wrote:

>I like the idea but on the other hand is there such a real need ?
>
>
Well, actually, i don't like the idea ;)) but the bloke asked. .
I already gave a sollution, but i guess he feels it should be done quite
a bit simpler. . and should
be supported by the core. I wrote in the ticket i would do an oppinion
poll in here, as it is a feature
request.

But i was hoping many would not like it ;)

Cheers!
Remco


Carlos Ribeiro

unread,
Jan 4, 2005, 4:51:54 AM1/4/05
to cherryp...@googlegroups.com
On Tue, 04 Jan 2005 10:39:12 +0100, Remco Boerma <remco....@gmail.com> wrote:
> Carlos Ribeiro wrote:
> It's an interesting generalization. getitem checking also works on dicts,
> so /foo/anything could be mapped to cpg.root.foo[anything] (where foo is a
> dict). We have to keep in mind that this may also cause some undesirable
> side effects as far as the current lookup works; if we can be sure that no
> such side effect exists, I'm +1 on it. If there's any side effect, -1. Here
> is some strange behaviour:
>
> >>> d = {}
> >>> d.exposed = True
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> AttributeError: 'dict' object has no attribute 'exposed'
> >>> print getattr(d,'exposed')
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> AttributeError: 'dict' object has no attribute 'exposed'
> >>>
>
> So checking if there is an exposed, would raise an error itself! (as it
> should provide None as default)
> So we'll have to use other means of checking, or we can't use dictionaries
> right away. and keeping them all opened, doesn't seem safe to me.

For dicts this is not a problem, because I can simply make:

d[exposed] = True

... and if I use the getitem method as a fallback for getattr, I'll
get the expected result.

> (on the other hand, it can be argued that the user himself can convert the
> objects published to support getattr; for example, nothing stops a UserList
> or UserDict to support getattr with similar results to the ones achieved by
> getitem with similar arguments.) Like i did in the ticket. With full
> control. We might write a recipe about it, but i don't think it's something
> to handle in the core. .

Why not provide an "ExposeItems" class, that can take any
getitem-aware class and publish it? It would be a simple wrapper. A
quick hack (using Wiki markup, mind you ;-):

{{{
class ExposeItems:
exposed = True
def __init__(self, obj):
self.obj = obj
def __getattr__(self, key):
return self.obj[key]
}}}

We could provide this code in the CP library, so the use case would be:

{{{
from cherrypy.lib import ExposeItems
...
cpg.root.foo = ExposeItems(mylist)
cpg.root.bar = ExposeItems(mydict)
}}}

Of course, this code assumes that the members of mylist and mydict are
itself exposed objects (it only publishes the *list* or *dict*, not
it's members).

<snipped long discussion about index vs default>

> if default would become the catch all, even for missing indexes, can't we
> simply drop default, and have index have the default behaviour as well?
> I think it would be much simpler then. .

I'm +1 for it. But that's a difficult debate, indeed.

Remco Boerma

unread,
Jan 4, 2005, 5:08:56 AM1/4/05
to cherryp...@googlegroups.com
Carlos Ribeiro wrote:

I like your ExposeItems sollution. it's short and solves all well.  i guess.. but i think it would have to include
some form of default handlers/error handles if the page is not found.
if default would become the catch all, even for missing indexes, can't we
simply drop default, and have index have the default behaviour as well? 
I think it would be much simpler then. . 
    
I'm +1 for it. But that's a difficult debate, indeed.
I know.. but if default, like it's name, would indeed also catch the http://localhost/ problem, i would be fine with it as well.
So let met drop the infamous debate.

Let's discuss, if the default method should be called, when there is a request that would 'normally' map to the index, but will be
mapped to default if no index exists!!

This would allow for the regular default and index usage, but it will also mean default is a catch all sollution.
It would certainly make my life easier ;)

Cheers!
Remco


Sylvain Hellegouarch

unread,
Jan 4, 2005, 6:27:25 AM1/4/05
to cherryp...@googlegroups.com
Well, I haven't really thoroughly thought about it so I don't know
whether or not it would be a good idea :)
- Sylvain

Remi Delon

unread,
Jan 4, 2005, 7:19:10 AM1/4/05
to cherryp...@googlegroups.com
> eurleif asks in #65
> <http://trac.cherrypy.org/cgi-bin/trac.cgi/ticket/65#preview> if it is
I don't want this in the core.
I think that having multiple object-mapping methods will only confuse
people.
The core should provide *one* clear implementation that suits 95% (if
not 99%) of the people.
If some people want to use some other esoteric mapping methods, they can
do so by having an InputFilter that sets cpg.request.objectPath based on
cpg.request.path (no need to override the default mapping function).

Remi.

Remi Delon

unread,
Jan 4, 2005, 7:38:01 AM1/4/05
to cherryp...@googlegroups.com
> What should, and will hapen using the following:
> class Root(object);
> def index(self,*p):
> if p:
> print `p`
> else:
> print 'index!'
> index.exposed = True
> cpg.root = Root()
>
> Ok. if i go to "http://localhost'" or http://localhost/" i will see
> "index!" if i add anything to the location bar, it will fail:
> http://localhost/bla/pir:
>
> Traceback (most recent call last):
> File "C:\module\cp2\cherrypy\_cphttptools.py", line 206, in doRequest
> handleRequest(wfile)
> File "C:\module\cp2\cherrypy\_cphttptools.py", line 372, in handleRequest
> func, objectPathList, virtualPathList = mapPathToObject()
> File "C:\module\cp2\cherrypy\_cphttptools.py", line 504, in mapPathToObject
> raise cperror.NotFound # We didn't find anything
> NotFound
>
> So that doesn't work?!

Right, that's the expected behavior.

> now i add root.bla similar to index. .
> def bla(self,*p):
> if p:
> return `p`
> else:
> return 'bla'
> bla.exposed = True
>
> Okay. here goes: http://localhost/bla and http://localhost/bla/ work
> fine. . it displays "bla". .

Yep, that's the expected behavior as well ...

> and going to /bla/pir shows ('pir',)

Now this is a bug !! You should get a "NotFound" error in this case
I added a ticket (#70) for this.

> .. perfect!! _So something is
> wrong with index?_. .

No, something is wrong with the current implementation of the algorithm.

> and (okay, flame me for starting this infamous debate again). . .
> _if default would become the catch all, even for missing indexes, can't
> we simply drop default, and have index have the default behaviour as well?
> _I think it would be much simpler then. .

Please let's not go over this again ...
If you want to use URLs like "http://domain/page/param1/param2" instead
of keyword arguments, the way to go is to use "default".

Remi.

Carlos Ribeiro

unread,
Jan 4, 2005, 7:55:01 AM1/4/05
to cherryp...@googlegroups.com
I agree with you... and that's why I proposed (and implemented) a
solution that does not mess up with the core, and neither with
objmapping, and it's also reusable in other contexts. It's on the
library (cherrypy.lib). I hope you don't mind... I assumed that the
library was the place for this type of utility code, and also, I
assumed that it was "better to ask for forgiveness than for
permission". :-)

Remco Boerma

unread,
Jan 4, 2005, 9:53:12 AM1/4/05
to cherryp...@googlegroups.com
Remi Delon wrote:

> Right, that's the expected behavior.
>
>> now i add root.bla similar to index. .
>> def bla(self,*p):
>> if p:
>> return `p`
>> else:
>> return 'bla'
>> bla.exposed = True
>>
>> Okay. here goes: http://localhost/bla and http://localhost/bla/ work
>> fine. . it displays "bla". .
>
>
> Yep, that's the expected behavior as well ...

True

>> and going to /bla/pir shows ('pir',)
>
>
> Now this is a bug !! You should get a "NotFound" error in this case
> I added a ticket (#70) for this.

No way. it should, it works perfectly. . .i allow every parameter,
using the positional scheme. . and it only displays the parameter, which
should be 'pir'
and it is!! I'ts perfect!

>
>> .. perfect!! _So something is wrong with index?_. .
>
>
> No, something is wrong with the current implementation of the algorithm.

i don't get it . .

>
>> and (okay, flame me for starting this infamous debate again). . .
>> _if default would become the catch all, even for missing indexes,
>> can't we simply drop default, and have index have the default
>> behaviour as well?
>> _I think it would be much simpler then. .
>
>
> Please let's not go over this again ...

Like i wrote in another mail. . it's fine with me, i rest my case.. .

> If you want to use URLs like "http://domain/page/param1/param2"
> instead of keyword arguments, the way to go is to use "default".

But this will not work if i goto say http://localhost/ and i have no
index. . Can't the default catch this as well? If there is an index: use
it, if there isn't: try default: if there is no default: raise an error??

Example:
/wiki/index and /wiki should all produce the front wiki page (internal
redirect to /wiki/wiki)
/wiki/edit/pagename should edit the page
/wiki/view/pagename or /wiki/pagename should show the page for pagename
(i take care of checking if the pagename is 'view' or 'edit' myself ..
that's my business. .
where /wiki/wiki is a special case, as that's the one redirected to . .

Now i need to add the logic in both index and default, right?

if i could drop the /wiki/index call, and let /wiki/default handle it
all, it would suit me just fine!

Cheers!
Remco

Remi Delon

unread,
Jan 5, 2005, 4:54:19 AM1/5/05
to cherryp...@googlegroups.com
>>> now i add root.bla similar to index. .
>>> def bla(self,*p):
>>> if p:
>>> return `p`
>>> else:
>>> return 'bla'
>>> bla.exposed = True
>>>
>>> Okay. here goes: http://localhost/bla and http://localhost/bla/ work
>>> fine. . it displays "bla". .
>>
>>
>>
>> Yep, that's the expected behavior as well ...
>
>
> True
>
>>> and going to /bla/pir shows ('pir',)
>>
>>
>>
>> Now this is a bug !! You should get a "NotFound" error in this case
>> I added a ticket (#70) for this.
>
>
> No way. it should, it works perfectly.. .i allow every parameter,
> using the positional scheme. . and it only displays the parameter, which
> should be 'pir'
> and it is!! I'ts perfect!

Well, it may be what you want in this specific case, but this creates
other problems ...
This decision was made a while ago: Only "default" can be called with
positional arguments, when the URL includes additional items in the path

So it *is* a bug and the code will be changed so that you get a
"NotFound" error in that case ...

The way to go for what you want to achieve *is* to use "default" ...

Remi.

Remco Boerma

unread,
Jan 5, 2005, 6:16:05 AM1/5/05
to cherryp...@googlegroups.com
Remi Delon wrote:

> Well, it may be what you want in this specific case, but this creates
> other problems ...
> This decision was made a while ago: Only "default" can be called with
> positional arguments, when the URL includes additional items in the path
>
> So it *is* a bug and the code will be changed so that you get a
> "NotFound" error in that case ...
>
> The way to go for what you want to achieve *is* to use "default" ...

I'm fine with that, sure i am. . but this also means that if no index
was found, default was used? That would suite me fine as well. .
(Btw, we do have to check breaking the positional scheme doesn't brake
the entire xmlrpc functionality. you can pass multiple parameters to
whatever function you want of course!)

Cheers!
Remco

Remi Delon

unread,
Jan 9, 2005, 2:09:37 PM1/9/05
to cherryp...@googlegroups.com
I just configured the SVN repository to run behind Apache as opposed to
using svn+ssh.
The new URL is https://svn.cherrypy.org
This means that write accessed is now done with a .htpasswd file.

People who had write access before should give me their htpasswd entry
so I can add it to the file.

People who don't have write access yet but would like to get involved
and contribute code to CherryPy, well, here is your chance :-)

Remi

PS: "htpasswd" is a command line tool that comes with Apache and
generates an encrypted version of your password.
An "htpasswd entry" looks like this: rdelon:MEFxQ1jeucFZI
If you don't have htpasswd on your computer, you can generate the line
online at this URL: http://www.flash.net/cgi-bin/pw.pl

Remi Delon

unread,
Jan 10, 2005, 4:58:38 AM1/10/05
to cherryp...@googlegroups.com
>> This decision was made a while ago: Only "default" can be called with
>> positional arguments, when the URL includes additional items in the path
>>
>> So it *is* a bug and the code will be changed so that you get a
>> "NotFound" error in that case ...

Well, I checked in that fix yesterday.

>> The way to go for what you want to achieve *is* to use "default" ...
>
>
> I'm fine with that, sure i am. . but this also means that if no index
> was found, default was used? That would suite me fine as well. .

Yes, it does.

> (Btw, we do have to check breaking the positional scheme doesn't brake
> the entire xmlrpc functionality. you can pass multiple parameters to
> whatever function you want of course!)

Well, can you check now ?

Remi.

Remco Boerma

unread,
Jan 10, 2005, 12:28:52 PM1/10/05
to cherryp...@googlegroups.com
Remi Delon wrote:
I'm fine with that, sure i am. . but this also means that if no index was found, default was used? That would suite me fine as well .
Yes, it does.
class Root:
##    def index(self):
##        return 'index'
##    index.exposed = True

   
    def bla(self,first='first',*p):
        return  `first`,`p`
    bla.exposed = True

    def default(self,first='first',*p):
        return  'default:',`first`,`p`
    default.exposed = True

I goto http://localhost
Traceback (most recent call last):
  File "C:\module\cp2\cherrypy\_cphttptools.py", line 206, in doRequest
    handleRequest(wfile)
  File "C:\module\cp2\cherrypy\_cphttptools.py", line 372, in handleRequest
    func, objectPathList, virtualPathList = mapPathToObject()
  File "C:\module\cp2\cherrypy\_cphttptools.py", line 511, in mapPathToObject
    raise cperror.NotFound # We didn't find anything
NotFound
Goting to /bla works well, and going to /foo gives me the answer of default (like it should).
But as i have no index, going to root doesn't work well, and does _not_ map to default.
Guess i spotted a bug :)


I've inserted a self.recursive = self in Root.__init__
now.  .(btw, i removed all th :9000 before, but they were there : ) )
1
http://localhost:9000/
Unexpected error
Not Found Error
2
http://localhost:9000/bla
bla: ok
("'first'", '()')
3
http://localhost:9000/bla/holyrabbit bla: ok
('default:', "'bla'", "('holyrabbit',)")
4
http://localhost:9000/bla/sub/holyrabbit
bla: ok
('default:', "'bla'", "('sub', 'holyrabbit')")
5
http://localhost:9000/bla/sub/holyrabbit?bla=pir
bla: ok
TypeError: default() got an unexpected keyword argument 'bla'
But this is ok, i can't handle any
      
6
http://localhost:9000/pir
default: ok
('default:', "'pir'", '()')
7
http://localhost:9000/pir/bla/
default: ok
('default:', "'pir'", "('bla',)")
8
http://localhost:9000/recursive/pir/bla/
default: ok
('default:', "'pir'", "('bla',)")
9
http://localhost:9000/recursive/bla
bla: ok
("'first'", '()')
10
http://localhost:9000/recursive/bla/holyrabit
Default: ERROR
('default:', "'bla'", "('holyrabbit',)")
This should be done by the bla routine
11
http://localhost:9000/recursive/bla/holyrabbit/someval
same
('default:', "'bla'", "('holyrabbit', 'someval')")
Same
12
http://localhost:9000/recursive/pir
default: OK
('default:', "'pir'", '()')
13
http://localhost:9000/recursive/pir/some
default: OK
('default:', "'pir'", "('some',)")
14
http://localhost:9000/recursive/
default: OK but not from the right reference
('default:', "'recursive'", '()')
this ought to be default.

test 1 and 14 have a direct relationship. . In test 1 it fails, because in the _cphttptools.py on line 485 we test on objectPathList not to be empty. . and on line 494 the following block is never executed, because it is the first call. If it is skipped, it will not test for deafault, and after that the list is empty: so it will raise an error. So that explains 1 and 14

10 and 11 are the same error of course. . but i don't get it. Why is 10 not allowed, when 2,3,4 and 9 are all ok? it mapes to root.default insatead of root.recursive.bla

. .  Another bug?

I hope the provided test table gives some support. .
(Btw, we do have to check breaking the positional scheme doesn't brake the entire xmlrpc functionality. you can pass multiple parameters  to whatever function you want of course!)

Well, can you check now ?
Test if the multiple parameters passed are returned well ... ok
Test if positional parameters sever side are no problem ... ok
Test if objects within objects are accepted with positional parameters and parameters given by path. ... ERROR
UNIMPLEMENTED TEST; Test if an invalid request returns with a proper error ... FAIL
SHOULD FAIL; Test if the Generator result is returned as a string ... ERROR
Test if objects within objects are accepted. ... ok
Test if an object returned from the server is a dicationary. ... ok
Test if keyword parameters are not allowed, as they shouldn't be.. ... ok
Test if None is handled properly ... ok
Test if a string is returned succesfully ... ok
Test if two strings are returned succesfully ... ok
UNIMPLEMENTED TEST; Test if the mimetype is set well ... FAIL
Test if the server is running or not and wheter a simple function call is working. ... ok
Test if the failure return as a Fault object is returned and contains the right value. ... ok

It's to bad the third test breaks. . all the other tests seem to go fine. . (they had the same behaviour as before, and i have not implemented all tests as you can see).
The third test is like:
   assertEqual(self.server.a.c.param1.param2('param3'),['param1','param2','param3'])
whitch maps to root.a.c(*p): return p

so now i would have to catch this in root.a.default and map to root.a.c myself, i think it's tolerable. .



Cheers
Remco
Reply all
Reply to author
Forward
0 new messages