Toggle navigation

Implementing a custom type

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

The dict parameter to 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 Python-level callable, although there are a number of special cases:

Python-level callable

Wrapped javascript function or the __call__() method itself follow the Python calling conventions. As a result, they can’t (easily) be called directly from javascript code. Because __new__() and __init__() follow from __call__(), they also follow the Python calling conventions.

py.PY_call() should be used when interacting with them from javascript is necessary.

Because __call__ follows the Python calling conventions, instantiating a py.js type from javascript requires using py.PY_call().

Python calling conventions

The python-level arguments should be considered completely opaque, they should be interacted with through py.PY_parseArgs() (to extract python-level arguments to javascript implementation code) and py.PY_call() (to call Python-level callable from javascript code).

A callable following the Python calling conventions 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 Python calling conventions).

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

Basic customization

__hash__()
Returns
String
__eq__(other)

The default implementation tests for identity

Parameters
otherpy.object to compare this object with
Returns
__ne__(other)

The default implementation calls __eq__() and reverses its result.

Parameters
otherpy.object to compare this object with
Returns
__lt__(other)

The default implementation simply returns py.NotImplemented.

Parameters
otherpy.object to compare this object with
Returns
__le__(other)

The default implementation simply returns py.NotImplemented.

Parameters
otherpy.object to compare this object with
Returns
__ge__(other)

The default implementation simply returns py.NotImplemented.

Parameters
otherpy.object to compare this object with
Returns
__gt__(other)

The default implementation simply returns py.NotImplemented.

Parameters
otherpy.object to compare this object with
Returns
__str__()

Simply calls __unicode__(). This method should not be overridden, __unicode__() should be overridden instead.

Returns
__unicode__()
Returns
__nonzero__()

The default implementation always returns py.True

Returns

Customizing attribute access

__getattribute__(name)
Parameters
name (String) – name of the attribute, as a javascript string
Returns
__getattr__(name)
Parameters
name (String) – name of the attribute, as a javascript string
Returns
__setattr__(name, value)
Parameters
  • name (String) – name of the attribute, as a javascript string
  • valuepy.object

Implementing descriptors

__get__(instance)
Parameters
instancepy.object
Returns
__set__(instance, value)
Parameters

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 py.NotImplemented). They take a single py.object parameter and return a single py.object parameter.
  • Unary operator numeric methods are all supported:

    __pos__()
    Returns
    __neg__()
    Returns
    __invert__()
    Returns
  • For non-operator numeric methods, support is contingent on the corresponding builtins being implemented

Emulating container types

__len__()
Returns
py.int
__getitem__(name)
Parameters
namepy.object
Returns
__setitem__(name, value)
Parameters
__iter__()
Returns
__reversed__()
Returns
__contains__(other)
Parameters
otherpy.object
Returns
[1] with the limitation that, because py.js builds its object model on top of javascript’s, only one base is allowed.