Source

py.js / doc / index.rst

masklinn fcc73c0 


























































































masklinn 1930d5e 
masklinn fcc73c0 
masklinn 1930d5e 
masklinn fcc73c0 




























masklinn 1930d5e 
masklinn fcc73c0 
masklinn 1930d5e 





masklinn fcc73c0 








masklinn 47fed85 
































masklinn fcc73c0 




masklinn 47fed85 









masklinn fcc73c0 
















masklinn 4176934 
masklinn fcc73c0 


masklinn 47fed85 
masklinn 4176934 
masklinn fcc73c0 






















.. py.js documentation master file, created by
   sphinx-quickstart on Sun Sep  9 19:36:23 2012.
   You can adapt this file completely to your liking, but it should at least
   contain the root `toctree` directive.

.. default-domain:: js

.. highlight:: javascript

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
<http://docs.python.org/reference/expressions.html>`_ (along with the
lexical analysis part) as well as the Python builtins.

Usage
-----

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});
    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.

API
---

Core functions
++++++++++++++

.. function:: py.eval(expr[, context])

    "Do everything" function, to use for one-shot evaluation of Python
    expressions. Chains tokenizing, parsing and evaluating the
    expression then :ref:`converts the result back to javascript
    <convert-js>`

    :param expr: Python expression to evaluate
    :type expr: String
    :param context: evaluation context for the expression's free
                    variables
    :type context: Object
    :returns: the expression's result, converted back to javascript

.. function:: py.tokenize(expr)

    Expression tokenizer

    :param expr: Python expression to tokenize
    :type expr: String
    :returns: token stream

.. function:: py.parse(tokens)

    Parses a token stream and returns the corresponding parse tree.

    The parse tree is stateless and can be memoized and reused for
    frequently evaluated expressions.

    :param tokens: token stream from :func:`py.tokenize`
    :returns: parse tree

.. function:: py.evaluate(tree[, context])

    Evaluates the expression represented by the provided parse tree,
    using the provided context for the exprssion's free variables.

    :param tree: parse tree returned by :func:`py.parse`
    :param context: evaluation context
    :returns: the "python object" resulting from the expression's
              evaluation
    :rtype: :class:`py.object`

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_``

.. function:: py.PY_parseArgs(arguments, format)

    Arguments parser converting from the :ref:`user-defined calling
    conventions <calling-conventions-python>` to a JS object mapping
    argument names to values. It serves the same role as
    `PyArg_ParseTupleAndKeywords`_.

    :param arguments: array-like objects holding the args and kwargs
                      passed to the callable, generally the
                      ``arguments`` of the caller.

    :param format: mapping declaration to the actual arguments of the
                   function. A javascript array composed of three
                   possible types of elements:

                   * The literal string ``'*'`` marks all following
                     parameters as keyword-only, regardless of them
                     having a default value or not [#kwonly]_

                   * A string defines a required parameter, accessible
                     positionally or through keyword

                   * A pair of ``[String, py.object]`` defines an
                     optional parameter and its default value.

    :returns: a javascript object mapping argument names to values

    :raises: ``TypeError`` if the provided arguments don't match the
             format

.. class:: py.PY_def(fn)

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

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

Implementation details
----------------------

.. _convert-py:

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:

* Values passed through the context of :func:`py.eval` or
  :func:`py.evaluate`

* Attributes accessed directly on objects

* Values of mappings passed to :class:`py.dict`

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:

* ``null`` is converted to :data:`py.None`

* ``true`` is converted to :data:`py.True`

* ``false`` is converted to :data:`py.False`

* numbers are converted to :class:`py.float`

* strings are converted to :class:`py.str`

* functions are wrapped into :class:`py.PY_dev`

* ``Array`` instances are converted to :class:`py.list`

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

.. _convert-js:

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.

Calling convention
++++++++++++++++++

Because Python supports keyword arguments and javascript does not,
moving arguments from the python domain to the javascript domain is
not completely straightforward.

``py.js`` implements two different conventions for that case (…)

* Dunder methods (pre- and post-fixed with ``__``) of the Python Data
  Model — fully and knowingly called in javascript — receive their
  arguments unwrapped and positionally, as normal arguments to a
  javascript functions. These arguments will still generally be
  :class:`py.object`.

.. _calling-conventions-python:

* Arbitrary user-defined callables receive two parameters ``args`` and
  ``kwargs``, holding respectively the positional and keyword
  arguments passed to the callable from the expression.

  These can be parsed into a JS object via :func:`py.PY_parseArgs`.

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'")``.

.. [#kwonly] 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.

.. _Python Data Model: http://docs.python.org/reference/datamodel.html

.. _PyArg_ParseTupleAndKeywords:
    http://docs.python.org/c-api/arg.html#PyArg_ParseTupleAndKeywords