
A Python-to-JavaScript Transpiler with BabelJS and SourceMaps - azazel75
https://github.com/azazel75/metapensiero.pj
======
mrharrison
Can all of you python to javascript library creators get together and create
one solid library, or maybe not all of you, because it would be a grid-lock of
decisions. How about half of you with the most similar ideas get together and
do one super solid library, instead of having 20 of these python to javascript
libraries so the community can easily decide on one to use as a standard. This
would be awesome! Thanks!

~~~
mrharrison
Probably need a company to do it. Like Microsoft made Typescript, Facebook
made React, Google made Angular, etc... We need Dropbox to make this, since
they have Guido and he can push this on the python 3 community to make this a
standard library. Dropbox please rescue us and pull the python to javascript
community together. Please!!!

~~~
LyndsySimon
> push this on the python 3 community to make this a standard library

Do you mean "standard" as in "the community's most often used", or as in
"included in the standard library"?

A wise man once told me that "the standard library is where libraries go to
die."

~~~
mrharrison
Well if I suggest standard library to an area that has 20 plus libraries, then
maybe we can get somewhere in the middle :)

------
dangamble
When i ran this on the Django github to create DjangoJS it didn't work, any
ideas?

~~~
tanlermin
Did you really expect that to work?!

~~~
golergka
This comment perfectly sums up my expectations of modern JS libraries.

------
fuhrysteve
I'm a little horrified to suggest this seriously, but this could be a cool way
to accomplish consistent field validation between server and client.

I wrote this little library [https://github.com/fuhrysteve/marshmallow-
jsonschema#complet...](https://github.com/fuhrysteve/marshmallow-
jsonschema#complete-example-flask-application-using-brutisinjson-forms) to
convert marshmallow schemas to a JSON representation with the intention of
passing it to a browser or mobile device for rendering. Imagine if you could
also pass native code to be used by the client for validation. In other words:
write your validator in python and use it server side - but _also_ convert it
to javascript so that the client can attempt to validate it before bothering
to send a web request.

~~~
azazel75
Javascripthon supports converting either a python source file or a python
function object directly, but actually using the embedded js interpreter to do
the transpilation takes some time due to BabelJS code bootstrap time.

Having a "HOT" interpreter with an execution context that is persistent and
can be used to convert code to ES5 on the fly has been already implemented by
duckpy creator and i plan to intergate it very soon.

See
[https://github.com/amol-/dukpy/issues/4](https://github.com/amol-/dukpy/issues/4)

------
okso
Looks interesting, but it has naming incoherences: 'pip install
javascripython' actually installs in site-packages/metapensiero/pj. I don't
get why it does not simply install in site-packages/javascripthon.

------
wuster
If you want to build the web with Python, IMO the emphasis should be bringing
Python to the web. I think a more promising project is
[http://pypyjs.org/](http://pypyjs.org/) \- a Python runtime in your browser
powered by asm.js

Listen to this podcast where the author describes the project:
[https://talkpython.fm/episodes/show/32/pypy.js-pypy-
python-i...](https://talkpython.fm/episodes/show/32/pypy.js-pypy-python-in-
your-browser)

~~~
true_religion
I think it's certainly an interesting project, but the goal of compiling to JS
today is to be able to access the DOM and interface easily with existing JS
infrastructure.

------
orf
This is awesome! One comment, it might be a good idea to make the docstrings
in JS appear above the functions rather than inside them? Chrome refuses to
optimize functions if they are above a certain size in bytes, which includes
comments, so it seems most 'docstrings' are placed above the definition rather
than inside. Also does str(x) convert to x.toString(x)?

I'm going to use this in a project I have in mind :)

~~~
azazel75
Good :-)

Do you have any link for this chrome detail about optimization?

str(x) conversion is missing... i'll will implement it asap

~~~
grayrest
It'd be related to inlining a function since size is a common rule there. Some
searching turns up this[1] article on crankshaft from three years ago, which
lists the restrictions as ">600 source characters including whitespace or 196
AST nodes".

[1] [http://jayconrod.com/posts/54/a-tour-of-v8-crankshaft-the-
op...](http://jayconrod.com/posts/54/a-tour-of-v8-crankshaft-the-optimizing-
compiler)

------
maaaats
So this transpiler makes ES6 code and then Babel makes it runnable on most
browsers, or does it leverage Babel in making JS code in the first place?

~~~
azazel75
The former, it translates Python 3.5 syntax and some of the core semantics to
ES6+ JavaScript and then BabelJS is used to transpile that ES6 JS to ES5. All
this retaining a sourcemap that maps back to the original Python sources.

It does all without the need for nodejs (even if it can be used of course), it
uses an embedded js interpreter.

------
dkopi
For-in array can be implemented using ES6's for-of.
[https://developer.mozilla.org/en/docs/Web/JavaScript/Referen...](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/for...of)

Also, Not sure if it would be correct to implement a python dict using an ES6
map. If the keys are all strings, probably better to stick to a JS object.
Check out the performance difference: [http://jsperf.com/es6-map-vs-object-
properties/73](http://jsperf.com/es6-map-vs-object-properties/73)

~~~
azazel75
For-of only works for iterable sources, it would not be a complete replacement
of for...in, also it seems a bit slower that for...in as of now.. see
[https://kpdecker.github.io/six-speed/](https://kpdecker.github.io/six-speed/)

------
tlrobinson
Python and modern JavaScript seem like fairly similar languages (dynamically
typed, object oriented/functional hybrid, rich ecosystem of packages), the
biggest difference being Python's "batteries included" standard library, which
presumably isn't (all?) available in the browser.

So is the main reason to use this just familiarity with Python, minimal
context switching if your backend is in Python, and the potential for a bit of
code reuse between front/backend?

~~~
azazel75
The main reason is... context switching, also i'm a big fan of python's
standard library, but I have yet to do any complete work just with it.

~~~
tanlermin
Is this supposed to be able to work for really large apps at some point? Some
commenter lamented how it didn't work with django.

~~~
azazel75
It cannot be used to convert python frameworks to javascript, nor Django nor
any other

~~~
civilian
That seems to suggest that this isn't a fully-formed py->js transpiler?

~~~
azazel75
It's in development, as many others software projects are, and is far from
complete. The goal is to translate as much of core semantics as possible, but
i doubt that all the core semantics will be translated. One for all is multi
inheritance which is currently unsupported by current Javascript syntax. Even
more, when you use an object such a list, it's really a JS Array that will be
manipulated in the end, so you will have to use array.push() to add instead of
python's list.append()

But Translating something like Django is out of scope for all the transpilers,
it would mean also converting sql drivers and so on? Does this really make any
sense? Maybe you have a look at emscripten
[https://github.com/kripken/emscripten/wiki](https://github.com/kripken/emscripten/wiki)

~~~
tanlermin
[http://www.transcrypt.org/](http://www.transcrypt.org/)

Does multiple inheritance

~~~
azazel75
I could assure you that even transcrypt cannot transpile Django.

It does multiple inheritance with a polyfill and overally is much more
"fatter" than JavaScripthon.

But with JavaScripthon you can use any tool available in JS land to accomplish
the same goal. Want to use Backbone's extend()? Use it.. want to use react's
createClass() mixin?, the same

------
bildung
How does interfacing with existing JS libraries work? I try to imagine how
using this with a bootstrap theme (=jQuery) would look like.

~~~
azazel75
If jQuery is installed globally, without package management, just use:

from __globals__ import jQuery

....

jQuery('#an_id')...

~~~
bildung
awesome, thanks for the info!

------
amelius
Related:
[https://blog.glyphobet.net/essay/2557](https://blog.glyphobet.net/essay/2557)

By the way, I prefer Javascript's scoping rules over Python's. Also, it is
easier to create a lexical block in Javascript than in Python.

~~~
azazel75
Your post seems quite imprecise about Python's semantics...

~~~
p4wnc6
The part about `lambda` is certainly imprecise. You can use the ternary form
of `a if b else c` and you can use comprehensions and/or functional style with
`map` or `filter` or things from itertools if you want iteration in a
`lambda`. Instead of putting statements inside the `lambda`, you should write
whatever would be a statement as a helper function, and just refactor the
`lambda` so that the sequence of statements you wanted will just be some
expression.

I didn't check in Python 2, but in Python 3 anyway, `type()` of a `lambda` is
definitely `function` and the `lambda` object has a `__code__` attribute with
`co_code` containing the actual bytecode, so it's definitely a function.

For raising errors, once again you can just define a helper that does the
raising -- the limitation here is the use of statements, not anything inherent
to exceptions. For example:

    
    
        In [56]: def r():
           ....:     raise TypeError
           ....: 
    
        In [57]: f = lambda x: x[0] if isinstance(x, list) else r()
    
        In [58]: f([1])
        Out[58]: 1
    
        In [59]: f("hi")
        ---------------------------------------------------------------------------
        TypeError                                 Traceback (most recent call last)
        <ipython-input-59-987cd5963ca4> in <module>()
        ----> 1 f("hi")
    
        <ipython-input-57-b0e388d24fbc> in <lambda>(x)
        ----> 1 f = lambda x: x[0] if isinstance(x, list) else r()
    
        <ipython-input-56-a540441a09db> in r()
              1 def r():
        ----> 2     raise TypeError
              3 
    
        TypeError:
    

The same idea would work with context managers, etc.

FWIW, having used Python for a long time, I see the limitations on `lambda` as
very good things. `lambda` should almost never be used for complex, side-
effectful logic, and instead should be used when a short expression needs to
be encapsulated and it's easier to do so with an anonymous function than a
full function definition, and to a lesser extent sometimes for some tricky
metaprogramming use cases, like dynamically binding functions at run time.

I'm sure that high-quality Javascript style probably implicitly uses these
same kinds of limitations, even if the language itself doesn't make it
mandatory.

------
anaphor
[https://twitter.com/pmrondon/status/648251230804946944](https://twitter.com/pmrondon/status/648251230804946944)

------
amirouche
It's Python with javascript ES6 semantic, there is no support for Python list,
dict or support for Python magic parameters __kwargs. Good work nonetheless.

~~~
azazel75
Python lists are supported:

* as literals;

* in for loops;

Keyword arguments accumulator has no corresponding feature in the ES6 world,
as far as I know....

~~~
coldtea
> _Keyword arguments accumulator has no corresponding feature in the ES6
> world, as far as I know...._

As a feature no, but Python code using that could be easily transpiled to a
function taking a dict with the args...

~~~
azazel75
It's implementable really and it is half-implemented, have a look at the call
conventions... additional keyword arguments can be specified without any
problem

The problem is that there's no __kwargs equivalent in js land.. and probably i
don 't want to wrap any call to make it possible.

------
enitihas
Related:
[https://github.com/atsepkov/RapydScript](https://github.com/atsepkov/RapydScript)

~~~
azazel75
I'm a big fan of RapydScript, unfortunately it requires nodejs and I would
prefer not have to.. but hey, there is a space for everybody ;-)

------
crudbug
Does this support:

1\. CommonJS modules

2\. Static types

3\. Webpack loader

Having CommonJS module support will enable polyglot development where language
syntax live inside a module and everything follows JavaScript semantics.

~~~
azazel75
1) it renders import and from...import statements to equivalent ES6 imports.
If you use something like Webpack down the pipeline you can already mix ES6
imports and CommonJS requires. Also, BabelJS by default transpiles ES6 imports
to CommonJS requires.

2) What do you mean exactly?

3) There's no direct from-python loader, but the compilation can be splitted
in two steps with the BabelJS Webpack loader used for the latter

------
irascible
Either make python a first class web lanGuage (not gonna happen) or just write
in javascript. It's awesome.

------
techdragon
It's an awesome library/tool yay for more Python to JS tools!

------
forgotusername2
have you heard about coffee??? ((:

~~~
azazel75
Yes, I drink it everyday

------
diskcat
Does this actually mean I can now write python code instead of JS for
websites?

~~~
azazel75
Have a look at the example! ;-)

~~~
andybak
I'd love to but

a) make failed b) I didn't really want to build something just to see an
example running ;-) c) you don't have an issues turned on in Github so I
couldn't file a bug.

It would be lovely if you could host the example somewhere and link to it. Or
failing that - have a compiled example in the repo so the idle and curious can
try it out with jumping through any hoops.

~~~
azazel75
ops, sorry for that. Issues are enabled now ;-)

