1. masklinn
  2. py.js


py.js / doc / types.rst

Implementing a custom type

To implement a custom python-level type, one can use the :func:`py.type` builtin. At the JS-level, it is a function with the same signature as the :py:class:`type` builtin [1]. It returns a child type of its one base (or :class:`py.object` if no base is provided).

The dict parameter to :func:`py.type` can contain any attribute, javascript-level or python-level: the default __getattribute__ implementation will ensure they are converted to Python-level attributes if needed. Most methods are also wrapped and converted to :ref:`types-methods-python`, although there are a number of special cases:

Python-level callable

Wrapped javascript function or the :js:func:`__call__` method itself follow the :ref:`types-methods-python-call`. As a result, they can't (easily) be called directly from javascript code. Because :js:func:`__new__` and :js:func:`__init__` follow from :js:func:`__call__`, they also follow the :ref:`types-methods-python-call`.

:func:`py.PY_call` should be used when interacting with them from javascript is necessary.

Because __call__ follows the :ref:`types-methods-python-call`, instantiating a py.js type from javascript requires using :func:`py.PY_call`.

Python calling conventions

The python-level arguments should be considered completely opaque, they should be interacted with through :func:`py.PY_parseArgs` (to extract python-level arguments to javascript implementation code) and :func:`py.PY_call` (to call :ref:`types-methods-python` from javascript code).

A callable following the :ref:`types-methods-python-call` must return a py.js object, an error will be generated when failing to do so.

Magic methods

py.js doesn't support calling magic ("dunder") methods of the datamodel from Python code, and these methods remain javascript-level (they don't follow the :ref:`types-methods-python-call`).

Here is a list of the understood datamodel methods, refer to the relevant Python documentation for their roles.

Basic customization

Customizing attribute access

Implementing descriptors

Emulating Numeric Types

  • Non-in-place binary numeric methods (e.g. __add__, __mul__, ...) should all be supported including reversed calls (in case the primary call is not available or returns :js:data:`py.NotImplemented`). They take a single :class:`py.object` parameter and return a single :class:`py.object` parameter.
  • Unary operator numeric methods are all supported:
  • For non-operator numeric methods, support is contingent on the corresponding :ref:`builtin` being implemented

Emulating container types

[1]with the limitation that, because :ref:`py.js builds its object model on top of javascript's <details-object-model>`, only one base is allowed.