1. masklinn
  2. py.js


py.js / doc / index.rst

py.js, a Python expressions parser and evaluator

py.js is a parser and evaluator of Python expressions, written in pure javascript.

py.js is not intended to implement a full Python interpreter, its specification document is the Python 2.7 Expressions spec (along with the lexical analysis part) as well as the Python builtins.


To evaluate a Python expression, simply call :func:`py.eval`. :func:`py.eval` takes a mandatory Python expression parameter, as a string, and an optional evaluation context (namespace for the expression's free variables), and returns a javascript value:

> py.eval("t in ('a', 'b', 'c') and foo", {t: 'c', foo: true});

If the expression needs to be repeatedly evaluated, or the result of the expression is needed in its "python" form without being converted back to javascript, you can use the underlying triplet of functions :func:`py.tokenize`, :func:`py.parse` and :func:`py.evaluate` directly.


Core functions

Utility functions

These are functions provided to implement py objects which can be used within a py.js evaluation, they're essentially py.js's version of the Python C API. They are prefixed with PY_

Type wrapping javascript functions into py.js callables. The wrapped function follows :ref:`the py.js calling conventions <types-methods-python-call>`

param Function fn:
 the javascript function to wrap
returns:a callable py.js object

Implementation details

Conversions from Javascript to Python

py.js will automatically attempt to convert non-:class:`py.object` values into their py.js equivalent in the following situations:

Notably, py.js will not attempt an automatic conversion of values returned by functions or methods, these must be :class:`py.object` instances.

The automatic conversions performed by py.js are the following:

The rest generates an error, except for undefined which specifically generates a NameError.

Conversions from Python to Javascript

py.js types (extensions of :js:class:`py.object`) can be converted back to javascript by calling their :js:func:`py.object.toJSON` method.

The default implementation raises an error, as arbitrary objects can not be converted back to javascript.

Most built-in objects provide a :js:func:`py.object.toJSON` implementation out of the box.

Javascript-level exceptions

Javascript allows throwing arbitrary things, but runtimes don't seem to provide any useful information (when they ever do) if what is thrown isn't a direct instance of Error. As a result, while py.js tries to match the exception-throwing semantics of Python it only ever throws bare Error at the javascript-level. Instead, it prefixes the error message with the name of the Python expression, a colon, a space, and the actual message.

For instance, where Python would throw KeyError("'foo'") when accessing an invalid key on a dict, py.js will throw Error("KeyError: 'foo'").

[1]Python 2, which py.js currently implements, does not support Python-level keyword-only parameters (it can be done through the C-API), but it seemed neat and easy enough so there.