Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

javascript to python

2 views
Skip to first unread message

Joe Hrbek

unread,
Oct 2, 2008, 1:54:07 PM10/2/08
to
Could someone help me translate to something that would close to it in
python? The anonymous functions are giving me problems.

var dataListener = {
data : "",
onStartRequest: function(request, context){},
onStopRequest: function(request, context, status){
instream.close();
outstream.close();
listener.finished(this.data);
},
onDataAvailable: function(request, context, inputStream, offset,
count){
this.data += instream.read(count);
},
};

lkcl

unread,
Oct 2, 2008, 2:07:19 PM10/2/08
to

On Oct 2, 5:54 pm, Joe Hrbek <joe.hr...@gmail.com> wrote:
> Could someone help me translate to something that would close to it in
> python? The anonymous functions are giving me problems.


class dataListener:
def __init__(self):
data = ""
def onStartRequest(self, request, context):
pass
def onStopRequest(self, request, context, status):

# TODO: pass these three in to dataListener as
# params to the constructor, so it's
# def __init__(self, instream, outstream, listener)
# and do self.instream = instream

global instream
global outstream
global listener

instream.close()
outstream.close()
listener.finished(self.data)

def onDataAvailable(self, request, context, inputStream,
offset, count):

global instream

self.data += instream.read(count)


question.

why are request and context being ignored?
why is there an inputStream argument to onDataAvailable, yet
there's a global variable (in the javascript) called
instream? is it the same?

all this, and more, thanks to the awfulness that is javascript :)

for fits and giggles, compile the above python using
pyjs.py, the python-to-javascript compiler
(see http://pyjamas.sf.net) and compare the
resultant javascript to your original code-fragment.

l.

Bruno Desthuilliers

unread,
Oct 2, 2008, 12:16:30 PM10/2/08
to
Joe Hrbek a �crit :


class DataListener(object):
def __init__(self):
self.data = ''
def on_start_request(self, request, context):
pass
def on_stop_request(self, request, context, status):
instream.close()
oustream.close()
listener.finished(self.data)
def on_data_available(self, request, context,
input_stream, offset, count):
self.data += instream.read(count)

data_listener = DataListener()


Or if you want a more straightforward (but less pythonic) translation:


class dataListener(object):
data = ''

@classmethod
def onStartRequest(this, request, context):
pass

@classmethod
def onStopRequest(this, request, context, status):
instream.close()
oustream.close()
listener.finished(this.data)

@classmethod
def onDataAvailable(this, request, context,

Bruno Desthuilliers

unread,
Oct 2, 2008, 3:42:35 PM10/2/08
to
lkcl a �crit :

> On Oct 2, 5:54 pm, Joe Hrbek <joe.hr...@gmail.com> wrote:
>> Could someone help me translate to something that would close to it in
>> python? The anonymous functions are giving me problems.
>
>
> class dataListener:
> def __init__(self):
> data = ""
> def onStartRequest(self, request, context):
> pass
> def onStopRequest(self, request, context, status):
>
> # TODO: pass these three in to dataListener as
> # params to the constructor, so it's
> # def __init__(self, instream, outstream, listener)
> # and do self.instream = instream
>
> global instream
> global outstream
> global listener

Since you don't rebind them, you don't need the global statement for
these three identifiers

> instream.close()
> outstream.close()
> listener.finished(self.data)
>
> def onDataAvailable(self, request, context, inputStream,
> offset, count):
>
> global instream

idem

> self.data += instream.read(count)
>

And then you have a class. Calling instance methods on the class won't
work. Looks like there's something missing...

> question.
>
> why are request and context being ignored?
> why is there an inputStream argument to onDataAvailable, yet
> there's a global variable (in the javascript) called
> instream? is it the same?
>
> all this, and more, thanks to the awfulness that is javascript :)

None of "this, and more" is because of javascript. You'll find bad code
in every language (and without more context, you can't tell if it's bad
code - might as well be the right thing to do).

FWIW, javascript is a very interesting and powerful language.

> for fits and giggles, compile the above python using
> pyjs.py, the python-to-javascript compiler
> (see http://pyjamas.sf.net) and compare the
> resultant javascript to your original code-fragment.
>
> l.

I did. Here's the result:

function __dataListener() {
}
function dataListener() {
var instance = new __dataListener();
if(instance.__init__) instance.__init__.apply(instance, arguments);
return instance;
}


function __dataListener_initialize() {
if(__dataListener.__was_initialized__) return;
__dataListener.__was_initialized__ = true;
pyjs_extend(__dataListener, __pyjslib_Object);
__dataListener.prototype.__class__.__new__ = dataListener;
__dataListener.prototype.__init__ = function() {
var data = '';
};
__dataListener.prototype.__class__.__init__ = function() {
return
__dataListener.prototype.__init__.call.apply(__dataListener.prototype.__init__,
arguments);
};
__dataListener.prototype.__class__.__init__.unbound_method = true;
__dataListener.prototype.__init__.instance_method = true;
__dataListener.prototype.onStartRequest = function(request, context) {
};
__dataListener.prototype.__class__.onStartRequest = function() {
return
__dataListener.prototype.onStartRequest.call.apply(__dataListener.prototype.onStartRequest,
arguments);
};
__dataListener.prototype.__class__.onStartRequest.unbound_method =
true;
__dataListener.prototype.onStartRequest.instance_method = true;
__dataListener.prototype.onStopRequest = function(request, context,
status) {
instream.close();
outstream.close();
listener.finished(this.data);
};
__dataListener.prototype.__class__.onStopRequest = function() {
return
__dataListener.prototype.onStopRequest.call.apply(__dataListener.prototype.onStopRequest,
arguments);
};
__dataListener.prototype.__class__.onStopRequest.unbound_method = true;
__dataListener.prototype.onStopRequest.instance_method = true;
__dataListener.prototype.onDataAvailable = function(request,

context, inputStream, offset, count) {
this.data += instream.read(count);

};
__dataListener.prototype.__class__.onDataAvailable = function() {
return
__dataListener.prototype.onDataAvailable.call.apply(__dataListener.prototype.onDataAvailable,
arguments);
};
__dataListener.prototype.__class__.onDataAvailable.unbound_method =
true;
__dataListener.prototype.onDataAvailable.instance_method = true;
}
__dataListener_initialize();


All this, and more, thanks to the strange idea that it would be better
to write javascript in Python instead of writing it in javascript !-)

lkcl

unread,
Oct 3, 2008, 4:56:49 AM10/3/08
to
On Oct 2, 7:42 pm, Bruno Desthuilliers
<bdesth.quelquech...@free.quelquepart.fr> wrote:
> lkcl a écrit :
> > (seehttp://pyjamas.sf.net) and compare the

> > resultant javascript to your original code-fragment.
>
> > l.
>
> I did. Here's the result:

ok - these are the "important" bits. notice that the pyjamas
compiler is doing a little bit more than your original code: it's
overriding the "prototype" of dataListener, making it a true "class"
object.

this is where there's a key departure from the original code and the
translation to python: the original code isn't actually a class, at
all - it's more like a.... c struct that has function pointers in it.

by declaring a python "class", the javascript equivalent is to add to
"prototypes".


> __dataListener.prototype.__init__ = function() {
> var data = '';
> };

[ ... so for example here, now when you declare _any number_ of
"dataListener"s, each and every one will have its __init__ function
called. in your original example, you're effectively making one and
only one "dataListener". you're kinda... it's a bit like having a
lambda-class (nameless class) and declaring one and only one instance
of that python class... ]


> __dataListener.prototype.onStopRequest = function(request, context,
> status) {
> instream.close();
> outstream.close();
> listener.finished(this.data);
> };

> __dataListener.prototype.onDataAvailable = function(request,


> context, inputStream, offset, count) {
> this.data += instream.read(count);
> };

so - yeah, you can see that (apart from the .prototype, which is
necessary to make a "class a la javascript") it's a pretty accurate
translation back to the original javascript.


> All this, and more, thanks to the strange idea that it would be better
> to write javascript in Python instead of writing it in javascript !-)

*lol* :) fortunately, pyjs.py does that translation for you ha
ha. like they say on brainiac, "STOP! we do these experiments, so
you don't have to".

yes - it's because in the translated python, dataListener was
declared as a class, whereas in the original javascript, the
corresponding concept (prototypes) are not made use of.

if you wanted to experiment, you could try this:

def onStartRequest(this, request, context):
pass

def onStopRequest(this, request, context, status):
instream.close()
oustream.close()
listener.finished(this.data)

def onDataAvailable(this, request, context,
inputStream, offset, count):
this.data += instream.read(count)

class dataListener:
def __init__(self):
self.data = ''
self.onStartRequest = onStartRequest
self.onStopRequest = onStopRequest
self.onDataAvailable = onDataAvailable

which you will find to be more accurately representative of the
original javascript, conceptually. i.e taking into account that in
the _original_ javascript, you don't have any "prototypes".

but - i don't believe it to be what you actually want, even though
it's "a slightly more accurate representation".

l.

Bruno Desthuilliers

unread,
Oct 3, 2008, 6:29:17 AM10/3/08
to
lkcl a �crit :

> On Oct 2, 7:42 pm, Bruno Desthuilliers
> <bdesth.quelquech...@free.quelquepart.fr> wrote:
>> lkcl a �crit :
(snip)

>>> for fits and giggles, compile the above python using
>>> pyjs.py, the python-to-javascript compiler
>>> (seehttp://pyjamas.sf.net) and compare the
>>> resultant javascript to your original code-fragment.
>>> l.
>> I did. Here's the result:
>
> ok - these are the "important" bits. notice that the pyjamas
> compiler is doing a little bit more than your original code:

Not 'mine' - I'm not the OP. And as far as I'm concerned, the point is
exactly here : it's doing "a little bit more" than the original code.
This "little bit" requires 6 times the original code (cf below), and is
actually useless for the OP's use case (else the OP's code wouldn't use
litteral object notation but a full-blown prototype).

> it's
> overriding the "prototype" of dataListener, making it a true "class"
> object.

There's nothing like a notion of "class" in javascript - as you of
course already know.

> this is where there's a key departure from the original code and the
> translation to python: the original code isn't actually a class, at
> all

Indeed. Why would it need to be ?

> - it's more like a.... c struct that has function pointers in it.

It's an object. What's wrong with objects ?

> by declaring a python "class", the javascript equivalent is to add to
> "prototypes".

Indeed. But the point is that Python - while close to a prototype-based
language in many aspects - is still class-based. The closer Python
translation of the OP's javascript snippet is probably the one I gave
using a 'class singleton' - that is, using the class itself as an
object. But retranslating this to javascript using a
python-source-to-javascript-source tool like pyjamas won't give you back
the original javascript snippet (which is by no mean a criticism of
pyjamas - it would just be way too complicated to automatize such a
translation).

>
>> __dataListener.prototype.__init__ = function() {
>> var data = '';
>> };
>
> [ ... so for example here, now when you declare _any number_ of
> "dataListener"s,

What for ? In the original snippet, there's clearly only a need for a
single one - and that's a *very* common pattern in browser-side
javascript scripting. The original snippet is 12 lines, 29 words, 369
bytes long (according to wc). The pyjamas translation of the Python
translation of the original javascript snippet is 49 lines, 126 words,
2285 bytes long. That's 6 times more code (to download and parse) - for
an unneeded feature. Often, less is better.

> each and every one will have its __init__ function
> called. in your original example,

"my" ? I repeat : I'm *not* the OP.

> you're effectively making one and
> only one "dataListener".

s/you/the OP/

And yes, indeed, there's only one dataListener object. What makes you
think there's a need for more than one ?

> you're kinda... it's a bit like having a
> lambda-class (nameless class) and declaring one and only one instance
> of that python class... ]

It's like having an object. period. While most OOPLs are class-based,
classes are by no mean a requirement of OO.

> so - yeah, you can see that (apart from the .prototype, which is
> necessary to make a "class a la javascript") it's a pretty accurate
> translation back to the original javascript.

I don't mean it's not working. I mean that it's a lot of unnecessary
code for an unnecessary feature. Believe me, 6 times more code makes a
*huge* difference when it comes to browser-side scripting and
user-experience.

Also and IMHO, it's trying to forcefit alien idioms in javascript. Being
prototype-based is by design - it's not a shortcoming.

>
>> All this, and more, thanks to the strange idea that it would be better
>> to write javascript in Python instead of writing it in javascript !-)
>
> *lol* :) fortunately, pyjs.py does that translation for you ha
> ha. like they say on brainiac, "STOP! we do these experiments, so
> you don't have to".

"fortunately" is judgement call. As far as I'm concerned, and despite a
couple warts (but hey, no language is wart-free, and Python has it's own
share, isn't it ?), I like javascript as a language, and enjoy coding in
javascript almost as much as I enjoy coding in Python.

> yes - it's because in the translated python, dataListener was
> declared as a class, whereas in the original javascript, the
> corresponding concept (prototypes) are not made use of.

There's probably a reason why the OP didn't use a full blown prototype,
isn't it ?-)

> if you wanted to experiment, you could try this:
>
> def onStartRequest(this, request, context):
> pass
>
> def onStopRequest(this, request, context, status):
> instream.close()
> oustream.close()
> listener.finished(this.data)
>
> def onDataAvailable(this, request, context,
> inputStream, offset, count):
> this.data += instream.read(count)
>
> class dataListener:
> def __init__(self):
> self.data = ''
> self.onStartRequest = onStartRequest
> self.onStopRequest = onStopRequest
> self.onDataAvailable = onDataAvailable
>
> which you will find to be more accurately representative of the
> original javascript, conceptually.

Nope. You defined functions outside the object's scope, and you still
have to instanciate dataListener. Also, this above code just won't work
- unless you explicitely pass the dataListener instance to the
functions, ie:

d = dataListener()
d.onDataAvailable(d, ...)

If you want per-instance methods, you have to invoke the descriptor
protocol by yourself, ie:

class dataListener:
def __init__(self):
self.data = ''

self.onStartRequest = onStartRequest.__get__(self, type(self))
self.onStopRequest = onStopRequest.__get__(self, type(self))
self.onDataAvailable = onDataAvailable.__get__(self, type(self))


But that's still not close to the OP's javascript code, and it's not
pythonic no more.

> i.e taking into account that in
> the _original_ javascript, you don't have any "prototypes".
> but - i don't believe it to be what you actually want, even though
> it's "a slightly more accurate representation".
>

It seem you didn't read my other translation proprosal, so I repost it here:

class dataListener(object):
data = ''

@classmethod


def onStartRequest(this, request, context):
pass

@classmethod


def onStopRequest(this, request, context, status):
instream.close()
oustream.close()
listener.finished(this.data)

@classmethod


def onDataAvailable(this, request, context,
inputStream, offset, count):
this.data += instream.read(count)


This is probably the closest Python translation one can come with
(javascript's 'this' semantics set aside) - even if it's not idiomatic
Python.


As you may have guess by now, I'm more than a bit skeptical about
'language XXX to javascript source' translations[1] - the target is a
too hi-level language IMHO. I don't mean that everyone should learn and
love javascript, but I think that targeting VM specific byte-code is a
way better approach.

[1] which is not a criticism of pyjamas, pypy's python2js compiler etc
effort - only my very humble opinion.

My 2 cents...

lkcl

unread,
Oct 3, 2008, 7:16:34 AM10/3/08
to
On Oct 3, 10:29 am, Bruno Desthuilliers <bruno.
42.desthuilli...@websiteburo.invalid> wrote:
> lkcl a écrit :> On Oct 2, 7:42 pm, Bruno Desthuilliers
> > <bdesth.quelquech...@free.quelquepart.fr> wrote:
> >> lkcl a écrit :

> Not 'mine' - I'm not the OP.

whoops, yes - i missed that. sorry!

> And as far as I'm concerned, the point is
> exactly here : it's doing "a little bit more" than the original code.

yeah, i know. and that "bit more" gets you a proper representation
of the python "class" concept.

i was merely pointing out that if you want to _really_ translate the
original code into python - _really_ strictly - it's not actually
possible. because python doesn't have the concept of non-prototyping
(but... see below: i believe i may stand corrected on that)


> [..snip..] and is


> actually useless for the OP's use case (else the OP's code wouldn't use
> litteral object notation but a full-blown prototype).

i know :)

> > it's
> > overriding the "prototype" of dataListener, making it a true "class"
> > object.
>
> There's nothing like a notion of "class" in javascript - as you of
> course already know.

okay,okay :) class-like :)


> Indeed. But the point is that Python - while close to a prototype-based
> language in many aspects - is still class-based. The closer Python
> translation of the OP's javascript snippet is probably the one I gave
> using a 'class singleton' - that is, using the class itself as an
> object.

oh is _that_ how you do it. thanks. i always wondered how you did
class singletons in python.

> python-source-to-javascript-source tool like pyjamas won't give you back
> the original javascript snippet (which is by no mean a criticism of
> pyjamas - it would just be way too complicated to automatize such a
> translation).

well... you _say_ that... but... actually, if that's the real way to
represent class singletons, and it's an accurate representation of the
OP's javascript, and a good example, then _yes_, pyjs should
definitely have that added as a feature - to understand that a class
singleton _can_ get mapped to the much more efficient javascript
example you gave.

not that many people would _want_ to do that, so it goes onto the
"diminishing returns TODO list", but...

> Nope. You defined functions outside the object's scope, and you still
> have to instanciate dataListener. Also, this above code just won't work
> - unless you explicitely pass the dataListener instance to the
> functions, ie:
>
> d = dataListener()
> d.onDataAvailable(d, ...)

yeah - i didn't realise what the python class singleton thing was.


> It seem you didn't read my other translation proprosal, so I repost it here:

> class dataListener(object):
> data = ''

i did - i just didn't understand its significance.

so - to get this straight: when you do class clsname(object), and you
have the indentation and declaration of variables (e.g. data, above)
at the same level as the functions, it means that there's only one of
them? (i.e. a singleton)?

so, if i do this:

d = dataListener()
e = dataListener()

d.data = "fred"

print f.data

will return "fred"?

l.

lkcl

unread,
Oct 3, 2008, 10:02:40 AM10/3/08
to
> so, if i do this:
>
> d = dataListener()
> e = dataListener()
>
> d.data = "fred"
>
> print f.data

duh, duh - that should be print e.data :)

Bruno Desthuilliers

unread,
Oct 3, 2008, 2:38:11 PM10/3/08
to
lkcl a �crit :

> On Oct 3, 10:29 am, Bruno Desthuilliers <bruno.
> 42.desthuilli...@websiteburo.invalid> wrote:
>> lkcl a �crit :> On Oct 2, 7:42 pm, Bruno Desthuilliers
>>> <bdesth.quelquech...@free.quelquepart.fr> wrote:
>>>> lkcl a �crit :

>
>> And as far as I'm concerned, the point is
>> exactly here : it's doing "a little bit more" than the original code.
>
> yeah, i know. and that "bit more" gets you a proper representation
> of the python "class" concept.

Except that in most cases - at least when it comes to browser
scripting[1] - this concept is just useless. IOW, that's quite a lot of
code for something you just don't need.

[1] but ask yourself how many times you end up having only one single
instance of a given class in a python utility script...

> i was merely pointing out that if you want to _really_ translate the
> original code into python - _really_ strictly - it's not actually
> possible.

"really strictly", nope. But mainly because there's nothing in Python
that behave like the 'this' javascript object (and it doesn't matter in
the OP snippet). But you can have something quite close, using the class
as an object (which it is anyway).

> because python doesn't have the concept of non-prototyping
> (but... see below: i believe i may stand corrected on that)

!-)

>> Indeed. But the point is that Python - while close to a prototype-based
>> language in many aspects - is still class-based. The closer Python
>> translation of the OP's javascript snippet is probably the one I gave
>> using a 'class singleton' - that is, using the class itself as an
>> object.
>
> oh is _that_ how you do it. thanks. i always wondered how you did
> class singletons in python.

Note that this not really idiomatic Python - partly for cultural
reasons, and mostly because use case and constraint differs (class
singleton would surely become idiomatic if Python was used as
browser-scripting language the way js is, because you then have to avoid
any useless code to keep the site responsive).

Anyway, that's still IMHO the pythonic way to translate a litteral
javascript object - I fail to see anything closer in Python (if there's
some guru around ?)

>> python-source-to-javascript-source tool like pyjamas won't give you back
>> the original javascript snippet (which is by no mean a criticism of
>> pyjamas - it would just be way too complicated to automatize such a
>> translation).
>
> well... you _say_ that... but... actually, if that's the real way to
> represent class singletons, and it's an accurate representation of the
> OP's javascript, and a good example, then _yes_, pyjs should
> definitely have that added as a feature - to understand that a class
> singleton _can_ get mapped to the much more efficient javascript
> example you gave.

I'm afraid it's going to be quite complicated. You'd have to make sure
the class only has classmethods - including inherited methods (and
exception made of methods inherited from object). And FWIW, even such a
class may be a base class for 'normal' python classes, so there's just
no reliable semantic way to make sure the class is really a class
singleton that should map to a litteral js object.

See, the problem here is that we have two high level, highly dynamic
languages, that are quite close on quite a lot of things but are based
on two really different object models. So quite often, the best
translation is obvious for a programmer with a decent knowledge of both
languages, but almost impossible for a program because there are way too
much imply stuff (like, for the python class singleton, the fact that
the class is not meant to be instanciated is totally implicit).

> not that many people would _want_ to do that,

Err... Do you have much experience in browser scripting ??? That's a
*very* common js idiom.

> so it goes onto the
> "diminishing returns TODO list", but...
>
>> Nope. You defined functions outside the object's scope, and you still
>> have to instanciate dataListener. Also, this above code just won't work
>> - unless you explicitely pass the dataListener instance to the
>> functions, ie:
>>
>> d = dataListener()
>> d.onDataAvailable(d, ...)
>
> yeah - i didn't realise what the python class singleton thing was.

In this case, the problem I pointed out was that Python's functions
needs to be class instances to yield instancemethods when looked up on
an instance or class. If you set a function as an instance attribute,
the descriptor protocol is not invoked, and you just have a plain
function (note that this is by design).

>> It seem you didn't read my other translation proprosal, so I repost it here:
>
>> class dataListener(object):
>> data = ''
>
> i did - i just didn't understand its significance.
>
> so - to get this straight: when you do class clsname(object), and you
> have the indentation and declaration of variables (e.g. data, above)
> at the same level as the functions, it means that there's only one of
> them? (i.e. a singleton)?

Nope. Whatever is declared within the class statement becomes a class
attribute - that is, an attribute of the class object, shared by all
instances. But that doesn't prevent you from instanciating the class and
set an instance attribute by that name, in which case it will shadow the
class attribute.

> so, if i do this:
>
> d = dataListener()
> e = dataListener()
>
> d.data = "fred"
>
> print f.data
>
> will return "fred"?
>

Nope. The lookup rules for "reading" are:
- first check if the class (or it's bases, following mro) has a
__getattribute__ method. If yes, call it, and stop here whatever the result.
- else check if there's a descriptor by that name in the class
(including bases etc)
- if not, check if the instance has a non-descriptor attribute by that
name in it's dict
- else check if the class (and it's bases etc) has a non-descriptor by
that name
- else lookup if the class (etc...) have a callable __getattr__
attribute and if yes call it with the looked up name
- else (if nothing matched so far) raise an attribute error

When it comes to 'writing', it's much more simple:
- first check if the class (and it's bases...) have a __setattr__
method. If yes, call it with the name and value and stop here whatever
happens.
- else check if the class (and it's bases etc...) have a descriptor by
that name _with binding behaviour_ (IOW : with a __set__ method). If
yes, call the descriptor's __set__ method with instance, name and value.
- else just set the instance's __dict__ with the name and value.

NB : I didn't mention slots, but they are rarely used. I leave it up to
you to read the relevant doc for more detailed informations.

To make a long story short, in your above snippet, the d.data = "fred"
statement ends up being a shortcut for d.__dict__['data'] = "fred". To
have the class singleton working as an object, you must not instanciate
it - just use the class object directly, ie:

class dataListener(object):
data = ""

dataListener.data = "fred"
print dataListener.data

If you really want to prevent dataListener from being instanciated,
you'd have to provide a __new__ method preventing instanciation, ie:

class dataListener(object):
def __new__(cls):
raise TypeError("class %s is a class singleton" % cls)

HTH

0 new messages