Great exercise for python expert !

M

manatlan

I'd like to make a "jquery python wrapper" ...

here is my code :
===================================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

class JQueryCaller(object):
def __init__(self,callback):
self.__callback=callback
self._s=[]

def __getattr__(self,name):
def _caller(*args):
sargs=["'%s'"%i for i in args]
self._s.append("%s(%s)"%(name,",".join(sargs)))
return self
return _caller

def __call__(self):
return self.__callback(".".join(self._s))

class MyObject(object):
def __init__(self):
self.js = JQueryCaller(self.__add)

def __add(self,j):
print "Add:"+j

if __name__ == "__main__":
o=MyObject()

o.js.kiki(12).kuku()()
===================================================================
If i run the script : it will display :

Add:kiki('12').kuku()

Because the JQueryCaller caller is called, by the "()" trick at the
end of the last line

I'd like to display the same thing, but without the need to put the
"()" at then end !
(by calling simply : "o.js.kiki(12).kuku()" not "o.js.kiki(12).kuku()
()")
(or how to call the MyObject._add (callback) without using the caller
on my JQueryCaller)

Really needs some help ... and it's a great exercise too ;-)
(3 hours on that, and don't find a way to resolve that, because I
can't find a way to terminate the recursivity in the getattr way)
 
G

George Sakkis

I'd like to make a "jquery python wrapper" ...

here is my code :
===================================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-

class JQueryCaller(object):
    def __init__(self,callback):
        self.__callback=callback
        self._s=[]

    def __getattr__(self,name):
        def _caller(*args):
            sargs=["'%s'"%i for i in args]
            self._s.append("%s(%s)"%(name,",".join(sargs)))
            return self
        return _caller

    def __call__(self):
        return self.__callback(".".join(self._s))

class MyObject(object):
    def __init__(self):
        self.js = JQueryCaller(self.__add)

    def __add(self,j):
        print "Add:"+j

if __name__ == "__main__":
    o=MyObject()

    o.js.kiki(12).kuku()()
===================================================================
If i run the script : it will display :

Add:kiki('12').kuku()

Because the JQueryCaller caller is called, by the "()" trick at the
end of the last line

I'd like to display the same thing, but without the need to put the
"()" at then end !
(by calling simply : "o.js.kiki(12).kuku()" not "o.js.kiki(12).kuku()
()")
(or how to call the MyObject._add (callback) without using the caller
on my JQueryCaller)

Why don't you rename __call__ to __str__ and have MyObject.__add
return a string instead of printing it directly?

class MyObject(object):
def __add(self,j):
return "Add:"+j

if __name__ == "__main__":
o = MyObject()
s = o.js.kiki(12).kuku()
print s


HTH,
George
 
M

manatlan

I'd like to make a "jquery python wrapper" ...
here is my code :
===================================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
class JQueryCaller(object):
    def __init__(self,callback):
        self.__callback=callback
        self._s=[]
    def __getattr__(self,name):
        def _caller(*args):
            sargs=["'%s'"%i for i in args]
            self._s.append("%s(%s)"%(name,",".join(sargs)))
            return self
        return _caller
    def __call__(self):
        return self.__callback(".".join(self._s))
class MyObject(object):
    def __init__(self):
        self.js = JQueryCaller(self.__add)
    def __add(self,j):
        print "Add:"+j
if __name__ == "__main__":
    o=MyObject()
    o.js.kiki(12).kuku()()
===================================================================
If i run the script : it will display :

Because the JQueryCaller caller is called, by the "()" trick at the
end of the last line
I'd like to display the same thing, but without the need to put the
"()" at then end !
(by calling simply : "o.js.kiki(12).kuku()" not "o.js.kiki(12).kuku()
()")
(or how to call the MyObject._add (callback) without using the caller
on my JQueryCaller)

Why don't you rename __call__ to __str__ and have MyObject.__add
return a string instead of printing it directly?

class MyObject(object):
    def __add(self,j):
        return "Add:"+j

if __name__ == "__main__":
    o = MyObject()
    s = o.js.kiki(12).kuku()
    print s

HTH,
George

sure, it works like you said ... but it's not what I want.
by doing that, you create an action ... when you will call "print" it
will call the __str__ (__repr__ is better in that case), which will
call the callback of myobject.
In my preceding post, the action was called by the "()" trick at the
end of line


In fact, MyObject will handle a list of all "js call"
If i do :
o.js.toto()
o.js.toto().titi(12,13)

I'd like my MyObject contains a list like that ["toto()","toto().titi
(12,23)"]

another idea ?
 
M

manatlan

I'd like to make a "jquery python wrapper" ...
here is my code :
===================================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
class JQueryCaller(object):
    def __init__(self,callback):
        self.__callback=callback
        self._s=[]
    def __getattr__(self,name):
        def _caller(*args):
            sargs=["'%s'"%i for i in args]
            self._s.append("%s(%s)"%(name,",".join(sargs)))
            return self
        return _caller
    def __call__(self):
        return self.__callback(".".join(self._s))
class MyObject(object):
    def __init__(self):
        self.js = JQueryCaller(self.__add)
    def __add(self,j):
        print "Add:"+j
if __name__ == "__main__":
    o=MyObject()
    o.js.kiki(12).kuku()()
===================================================================
If i run the script : it will display :
Add:kiki('12').kuku()
Because the JQueryCaller caller is called, by the "()" trick at the
end of the last line
I'd like to display the same thing, but without the need to put the
"()" at then end !
(by calling simply : "o.js.kiki(12).kuku()" not "o.js.kiki(12).kuku()
()")
(or how to call the MyObject._add (callback) without using the caller
on my JQueryCaller)
Why don't you rename __call__ to __str__ and have MyObject.__add
return a string instead of printing it directly?
class MyObject(object):
    def __add(self,j):
        return "Add:"+j
if __name__ == "__main__":
    o = MyObject()
    s = o.js.kiki(12).kuku()
    print s
HTH,
George

sure, it works like you said ... but it's not what I want.
by doing that, you create an action ... when you will call "print" it
will call the __str__ (__repr__ is better in that case), which will
call the callback of myobject.
In my preceding post, the action was called by the "()" trick at the
end of line

In fact, MyObject will handle a list of all "js call"
If i do :
  o.js.toto()
  o.js.toto().titi(12,13)

I'd like my MyObject contains a list like that ["toto()","toto().titi
(12,23)"]

another idea ?

To explain better, here is another code
======================================================================================
class JQueryCaller(object):
def __init__(self,callback):
self.__callback=callback
self._s=[]

def __getattr__(self,name):
def _caller(*args):
sargs=["'%s'"%i for i in args]
self._s.append("%s(%s)"%(name,",".join(sargs)))
return self
return _caller

def __call__(self):
return self.__callback(".".join(self._s))


class MyObject(list):
def __init__(self):
list.__init__([])

js=property(lambda self:JQueryCaller(self.__add))

def __add(self,j):
self.append(j)


if __name__ == "__main__":
o=MyObject()

o.js.kiki(12).kuku()()
o.js.kiki(12).kuku().roro("gfde")()

assert o==["kiki('12').kuku()", "kiki('12').kuku().roro('gfde')"]
======================================================================================

here, it uses the __call__ of JQueryCaller by adding the "()" trick at
the end ...

I'd really like to have the same result, without the "()" trick, like
this:

o=MyObject()

o.js.kiki(12).kuku()
o.js.kiki(12).kuku().roro("gfde")

assert o==["kiki('12').kuku()", "kiki('12').kuku().roro('gfde')"]
 
G

George Sakkis

I'd like to make a "jquery python wrapper" ...
here is my code :
===================================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
class JQueryCaller(object):
    def __init__(self,callback):
        self.__callback=callback
        self._s=[]
    def __getattr__(self,name):
        def _caller(*args):
            sargs=["'%s'"%i for i in args]
            self._s.append("%s(%s)"%(name,",".join(sargs)))
            return self
        return _caller
    def __call__(self):
        return self.__callback(".".join(self._s))
class MyObject(object):
    def __init__(self):
        self.js = JQueryCaller(self.__add)
    def __add(self,j):
        print "Add:"+j
if __name__ == "__main__":
    o=MyObject()
    o.js.kiki(12).kuku()()
===================================================================
If i run the script : it will display :
Add:kiki('12').kuku()
Because the JQueryCaller caller is called, by the "()" trick at the
end of the last line
I'd like to display the same thing, but without the need to put the
"()" at then end !
(by calling simply : "o.js.kiki(12).kuku()" not "o.js.kiki(12).kuku()
()")
(or how to call the MyObject._add (callback) without using the caller
on my JQueryCaller)
Why don't you rename __call__ to __str__ and have MyObject.__add
return a string instead of printing it directly?
class MyObject(object):
    def __add(self,j):
        return "Add:"+j
if __name__ == "__main__":
    o = MyObject()
    s = o.js.kiki(12).kuku()
    print s
HTH,
George

sure, it works like you said ... but it's not what I want.
by doing that, you create an action ... when you will call "print" it
will call the __str__ (__repr__ is better in that case), which will
call the callback of myobject.
In my preceding post, the action was called by the "()" trick at the
end of line

.... which you apparently don't like, and rightly so. __getattr__ and
__call__ do totally different things in your example, why do you want
to conflate them ?
In fact, MyObject will handle a list of all "js call"
If i do :
  o.js.toto()
  o.js.toto().titi(12,13)

I'd like my MyObject contains a list like that ["toto()","toto().titi
(12,23)"]

Of course this still happens when you rename __call__ to __str__.
another idea ?

Yes, put a little more thought on your design and give a more
realistic example of what you're really trying to do; so far it seems
more like a pointless hack.

George
 
S

Steven D'Aprano

I'd like to make a "jquery python wrapper" [...]
here is my code :
[...]

What is the purpose of this code? As near as I can see, it would make an
excellent entry to the Obfuscated Python Competition, except it isn't
clear that it does anything useful.

Frankly, this looks like an pointlessly overly-complicated design to me.
Rather than getting rid of the extra parentheses, I suggest you rethink
your design. Explicit is better that implicit: don't have the one method
do both appending to the object *and* calling the object.
 
M

manatlan

I'd like to make a "jquery python wrapper" ...
here is my code :
===================================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
class JQueryCaller(object):
    def __init__(self,callback):
        self.__callback=callback
        self._s=[]
    def __getattr__(self,name):
        def _caller(*args):
            sargs=["'%s'"%i for i in args]
            self._s.append("%s(%s)"%(name,",".join(sargs)))
            return self
        return _caller
    def __call__(self):
        return self.__callback(".".join(self._s))
class MyObject(object):
    def __init__(self):
        self.js = JQueryCaller(self.__add)
    def __add(self,j):
        print "Add:"+j
if __name__ == "__main__":
    o=MyObject()
    o.js.kiki(12).kuku()()
===================================================================
If i run the script : it will display :
Add:kiki('12').kuku()
Because the JQueryCaller caller is called, by the "()" trick at the
end of the last line
I'd like to display the same thing, but without the need to put the
"()" at then end !
(by calling simply : "o.js.kiki(12).kuku()" not "o.js.kiki(12).kuku()
()")
(or how to call the MyObject._add (callback) without using the caller
on my JQueryCaller)
Why don't you rename __call__ to __str__ and have MyObject.__add
return a string instead of printing it directly?
class MyObject(object):
    def __add(self,j):
        return "Add:"+j
if __name__ == "__main__":
    o = MyObject()
    s = o.js.kiki(12).kuku()
    print s
HTH,
George
sure, it works like you said ... but it's not what I want.
by doing that, you create an action ... when you will call "print" it
will call the __str__ (__repr__ is better in that case), which will
call the callback of myobject.
In my preceding post, the action was called by the "()" trick at the
end of line

... which you apparently don't like, and rightly so. __getattr__ and
__call__ do totally different things in your example, why do you want
to conflate them ?
In fact, MyObject will handle a list of all "js call"
If i do :
  o.js.toto()
  o.js.toto().titi(12,13)
I'd like my MyObject contains a list like that ["toto()","toto().titi
(12,23)"]

Of course this still happens when you rename __call__ to __str__.
another idea ?

Yes, put a little more thought on your design and give a more
realistic example of what you're really trying to do; so far it seems
more like a pointless hack.

George

I just want to make a jquery wrapper, and let people use it to write
jquery call on the server side in a python way ...

o is a object, imagine a widget : like a textarea or input box
"js" is a special attribut of "o", which will let you write javascript
for this object.

o=MyObject()
o.js.toggleClass("clean").hide()

When I will render the object to a http/html output : it will generate
something like (a javascript call): $("#idOfMyObject").toggleClass
("clean").hide();

It's all what I want in the real world.
I wouldn't do something like that (with the "()" tricks at the end on
the chain, because I don't find it really readable/natural)

o=MyObject()
o.js.toggleClass("clean").hide()()

The code I gave before (the JQueryCaller) was just my try to do what I
want ... If there is another way : I take ;-)
 
D

Diez B. Roggisch

I just want to make a jquery wrapper, and let people use it to write
jquery call on the server side in a python way ...

o is a object, imagine a widget : like a textarea or input box
"js" is a special attribut of "o", which will let you write javascript
for this object.

o=MyObject()
o.js.toggleClass("clean").hide()

When I will render the object to a http/html output : it will generate
something like (a javascript call): $("#idOfMyObject").toggleClass
("clean").hide();

It's all what I want in the real world.
I wouldn't do something like that (with the "()" tricks at the end on
the chain, because I don't find it really readable/natural)

o=MyObject()
o.js.toggleClass("clean").hide()()

The code I gave before (the JQueryCaller) was just my try to do what I
want ... If there is another way : I take ;-)

But there must be *something* on this end of the chain, because how is
python otherwise to distinguish betwenn

os.js.toggleClass().hide()
os.js.toggleClass().hide().show()

?

Now the question is if the action that is to take must be on the object
itself. Maybe it works for you to make the assignment to some other object
do the trick, or additon. Something like this:

self.js_calls += os.js.toggleClass().hide()

Then in the __iadd__-method of js_calls you can render the right side.

Diez
 
D

Diez B. Roggisch

Steven said:
I'd like to make a "jquery python wrapper" [...]
here is my code :
[...]

What is the purpose of this code? As near as I can see, it would make an
excellent entry to the Obfuscated Python Competition, except it isn't
clear that it does anything useful.

Frankly, this looks like an pointlessly overly-complicated design to me.
Rather than getting rid of the extra parentheses, I suggest you rethink
your design. Explicit is better that implicit: don't have the one method
do both appending to the object *and* calling the object.

The basic idea isn't so bad. The OP tries to create a syntactic look-alike
to the way the javascript library jQuery works, which does these chained
calls, with the purpose of making the writing of JS serverside (something
you sometimes for dynamic JS) within the same DSL.

If this is nicely integrated, it actually could be neat. OTOH, I go
with """-strings & string interpolation - works good enough for me...

Diez
 
P

Peter Otten

manatlan said:
To explain better, here is another code

class JQueryCaller(object):
    def __init__(self,callback):
        self.__callback=callback
        self._s=[]

    def __getattr__(self,name):
        def _caller(*args):
            sargs=["'%s'"%i for i in args]
            self._s.append("%s(%s)"%(name,",".join(sargs)))
            return self
        return _caller

    def __call__(self):
        return self.__callback(".".join(self._s))


class MyObject(list):
    def __init__(self):
        list.__init__([])

    js=property(lambda self:JQueryCaller(self.__add))

    def __add(self,j):
        self.append(j)


if __name__ == "__main__":
    o=MyObject()

    o.js.kiki(12).kuku()()
    o.js.kiki(12).kuku().roro("gfde")()

    assert o==["kiki('12').kuku()", "kiki('12').kuku().roro('gfde')"]

here, it uses the __call__ of JQueryCaller by adding the "()" trick at
the end ...

I'd really like to have the same result, without the "()" trick, like
this:

    o=MyObject()

    o.js.kiki(12).kuku()
    o.js.kiki(12).kuku().roro("gfde")

    assert o==["kiki('12').kuku()", "kiki('12').kuku().roro('gfde')"]


You could preallocate slots in MyObject:

from functools import partial

class JQueryCaller(object):
def __init__(self,callback):
self.__callback=callback
self._s=[]

def __getattr__(self,name):
def _caller(*args):
sargs=["'%s'"%i for i in args]
self._s.append("%s(%s)"%(name,",".join(sargs)))
self.__callback(".".join(self._s))
return self
return _caller

class MyObject(list):
def __init__(self):
list.__init__([])

@property
def js(self):
n = len(self)
self.append(None)
return JQueryCaller(partial(self._add, n))

def _add(self, i, j):
self = j

if __name__ == "__main__":
o=MyObject()

o.js.kiki(12).kuku()
o.js.kiki(12).kuku().roro("gfde")

assert o==["kiki('12').kuku()", "kiki('12').kuku().roro('gfde')"]

This will course fail if you try things like

a = o.js.kiki
a(1)
a(2)

Peter
 
M

manatlan

manatlan said:
To explain better, here is another code
class JQueryCaller(object):
    def __init__(self,callback):
        self.__callback=callback
        self._s=[]
    def __getattr__(self,name):
        def _caller(*args):
            sargs=["'%s'"%i for i in args]
            self._s.append("%s(%s)"%(name,",".join(sargs)))
            return self
        return _caller
    def __call__(self):
        return self.__callback(".".join(self._s))
class MyObject(list):
    def __init__(self):
        list.__init__([])
    js=property(lambda self:JQueryCaller(self.__add))
    def __add(self,j):
        self.append(j)
if __name__ == "__main__":
    o=MyObject()
    o.js.kiki(12).kuku()()
    o.js.kiki(12).kuku().roro("gfde")()
    assert o==["kiki('12').kuku()", "kiki('12').kuku().roro('gfde')"]
here, it uses the __call__ of JQueryCaller by adding the "()" trick at
the end ...
I'd really like to have the same result, without the "()" trick, like
this:
    o=MyObject()
    o.js.kiki(12).kuku()
    o.js.kiki(12).kuku().roro("gfde")
    assert o==["kiki('12').kuku()", "kiki('12').kuku().roro('gfde')"]

You could preallocate slots in MyObject:

from functools import partial

class JQueryCaller(object):
    def __init__(self,callback):
        self.__callback=callback
        self._s=[]

    def __getattr__(self,name):
        def _caller(*args):
            sargs=["'%s'"%i for i in args]
            self._s.append("%s(%s)"%(name,",".join(sargs)))
            self.__callback(".".join(self._s))
            return self
        return _caller

class MyObject(list):
    def __init__(self):
        list.__init__([])

    @property
    def js(self):
        n = len(self)
        self.append(None)
        return JQueryCaller(partial(self._add, n))

    def _add(self, i, j):
        self = j

if __name__ == "__main__":
    o=MyObject()

    o.js.kiki(12).kuku()
    o.js.kiki(12).kuku().roro("gfde")

    assert o==["kiki('12').kuku()", "kiki('12').kuku().roro('gfde')"]

This will course fail if you try things like

a = o.js.kiki
a(1)
a(2)

Peter


great ! you've found the way !
I don't understant the trick for now, but i will study it !
But it works like expected ! great !
thanks a lot
 
M

manatlan

But there must be *something* on this end of the chain, because how is
python otherwise to distinguish betwenn

os.js.toggleClass().hide()
os.js.toggleClass().hide().show()

?

Now the question is if the action that is to take must be on the object
itself. Maybe it works for you to make the assignment to some other object
do the trick, or additon. Something like this:

self.js_calls += os.js.toggleClass().hide()

Then in the __iadd__-method of js_calls you can render the right side.

Diez

nice idea ...
but you use an action on the "+=" and __add__ ... it makes sense.

but peter has found the way !
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top