Javascript API

Backward compatibility of the API is not guaranteed at this point.

Globals

pyodide

PyProxy

A PyProxy is an object that allows idiomatic use of a Python object from Javascript. See Proxying from Python into Javascript.

Attributes:

length

The length of the object.

type

The name of the type of the object.

Functions:

[Symbol.iterator]()

This translates to the Python code iter(obj).

callKwargs(jsargs)

Call the function with key word arguments.

catch(onRejected)

Runs asyncio.ensure_future(awaitable) and executes onRejected(error) if the future fails.

clone()

Make a new PyProxy pointing to the same Python object.

delete(key)

This translates to the Python code del obj[key].

destroy(destroyed_msg)

Destroy the PyProxy.

finally(onFinally)

Runs asyncio.ensure_future(awaitable) and executes onFinally(error) when the future resolves.

get(key)

This translates to the Python code obj[key].

getBuffer(type)

Get a view of the buffer data which is usable from Javascript.

has(key)

This translates to the Python code key in obj.

next(value)

This translates to the Python code next(obj).

set(key, value)

This translates to the Python code obj[key] = value.

then(onFulfilled, onRejected)

Runs asyncio.ensure_future(awaitable), executes onFulfilled(result) when the Future resolves successfully, executes onRejected(error) when the Future fails.

toJs(depth)

Converts the PyProxy into a Javascript object as best as possible.

Classes:

PyBuffer

A class to allow access to a Python data buffers from Javascript.

PyProxy.length

The length of the object.

Present only if the proxied Python object has a __len__ method.

PyProxy.type

The name of the type of the object.

Usually the value is "module.name" but for builtins or interpreter-defined types it is just "name". As pseudocode this is:

ty = type(x)
if ty.__module__ == 'builtins' or ty.__module__ == "__main__":
    return ty.__name__
else:
    ty.__module__ + "." + ty.__name__
[Symbol.iterator]()

This translates to the Python code iter(obj). Return an iterator associated to the proxy. See the documentation for Symbol.iterator.

Present only if the proxied Python object is iterable (i.e., has an __iter__ method).

This will be used implicitly by for(let x of proxy){}.

Returns

Iterator – An iterator for the proxied Python object.

PyProxy.callKwargs(jsargs)

Call the function with key word arguments. The last argument must be an object with the keyword arguments.

PyProxy.catch(onRejected)

Runs asyncio.ensure_future(awaitable) and executes onRejected(error) if the future fails.

See the documentation for Promise.catch.

Present only if the proxied Python object is awaitable.

Arguments
  • onRejected (function) – A handler called with the error as an argument if the awaitable fails.

Returns

Promise – The resulting Promise.

PyProxy.clone()

Make a new PyProxy pointing to the same Python object. Useful if the PyProxy is destroyed somewhere else.

PyProxy.delete(key)

This translates to the Python code del obj[key].

Present only if the proxied Python object has a __delitem__ method.

Arguments
  • key (any) – The key to delete.

PyProxy.destroy(destroyed_msg)

Destroy the PyProxy. This will release the memory. Any further attempt to use the object will raise an error.

In a browser supporting FinalizationRegistry Pyodide will automatically destroy the PyProxy when it is garbage collected, however there is no guarantee that the finalizer will be run in a timely manner so it is better to destory the proxy explicitly.

Arguments
  • destroyed_msg (string) – The error message to print if use is attempted after destroying. Defaults to “Object has already been destroyed”.

PyProxy.finally(onFinally)

Runs asyncio.ensure_future(awaitable) and executes onFinally(error) when the future resolves.

See the documentation for Promise.finally.

Present only if the proxied Python object is awaitable.

Arguments
  • onFinally (function) – A handler that is called with zero arguments when the awaitable resolves.

Returns

Promise – A Promise that resolves or rejects with the same result as the original Promise, but only after executing the onFinally handler.

PyProxy.get(key)

This translates to the Python code obj[key].

Present only if the proxied Python object has a __getitem__ method.

Arguments
  • key (any) – The key to look up.

Returns

The corresponding value.

PyProxy.getBuffer(type)

Get a view of the buffer data which is usable from Javascript. No copy is ever performed.

Present only if the proxied Python object supports the Python Buffer Protocol.

We do not support suboffsets, if the buffer requires suboffsets we will throw an error. Javascript nd array libraries can’t handle suboffsets anyways. In this case, you should use the toJs api or copy the buffer to one that doesn’t use suboffets (using e.g., numpy.ascontiguousarray).

If the buffer stores big endian data or half floats, this function will fail without an explicit type argument. For big endian data you can use toJs. DataViews have support for big endian data, so you might want to pass 'dataview' as the type argument in that case.

Arguments
  • type (string) – The type of PyBuffer.data field in the output. Should be one of: "i8", "u8", "u8clamped", "i16", "u16", "i32", "u32", "i32", "u32", "i64", "u64", "f32", "f64, or "dataview". This argument is optional, if absent getBuffer will try to determine the appropriate output type based on the buffer format string.

Returns

PyBuffer

PyProxy.has(key)

This translates to the Python code key in obj.

Present only if the proxied Python object has a __contains__ method.

Arguments
  • key (*) – The key to check for.

Returns

bool – Is key present?

PyProxy.next(value)

This translates to the Python code next(obj). Returns the next value of the generator. See the documentation for Generator.prototype.next. The argument will be sent to the Python generator.

This will be used implicitly by for(let x of proxy){}.

Present only if the proxied Python object is a generator or iterator (i.e., has a send or __next__ method).

Arguments
  • value (*) – The value to send to the generator. The value will be assigned as a result of a yield expression.

Returns

Object – An Object with two properties: done and value. When the generator yields some_value, next returns {done : false, value : some_value}. When the generator raises a StopIteration(result_value) exception, next returns {done : true, value : result_value}.

PyProxy.set(key, value)

This translates to the Python code obj[key] = value.

Present only if the proxied Python object has a __setitem__ method.

Arguments
  • key (any) – The key to set.

  • value (any) – The value to set it to.

PyProxy.then(onFulfilled, onRejected)

Runs asyncio.ensure_future(awaitable), executes onFulfilled(result) when the Future resolves successfully, executes onRejected(error) when the Future fails. Will be used implictly by await obj.

See the documentation for Promise.then

Present only if the proxied Python object is awaitable.

Arguments
  • onFulfilled (function) – A handler called with the result as an argument if the awaitable succeeds.

  • onRejected (function) – A handler called with the error as an argument if the awaitable fails.

Returns

Promise – The resulting Promise.

PyProxy.toJs(depth)

Converts the PyProxy into a Javascript object as best as possible. By default does a deep conversion, if a shallow conversion is desired, you can use proxy.toJs(1). See Explicit Conversion of PyProxy for more info.

Arguments
  • depth (number) – How many layers deep to perform the conversion. Defaults to infinite.

Returns

The Javascript object resulting from the conversion.

class PyProxy.PyBuffer()

A class to allow access to a Python data buffers from Javascript. These are produced by PyProxy.getBuffer and cannot be constructed directly. When you are done, release it with the release method. See Python buffer protocol documentation for more information.

To find the element x[a_1, ..., a_n], you could use the following code:

function multiIndexToIndex(pybuff, multiIndex){
   if(multindex.length !==pybuff.ndim){
      throw new Error("Wrong length index");
   }
   let idx = pybuff.offset;
   for(let i = 0; i < pybuff.ndim; i++){
      if(multiIndex[i] < 0){
         multiIndex[i] = pybuff.shape[i] - multiIndex[i];
      }
      if(multiIndex[i] < 0 || multiIndex[i] >= pybuff.shape[i]){
         throw new Error("Index out of range");
      }
      idx += multiIndex[i] * pybuff.stride[i];
   }
   return idx;
}
console.log("entry is", pybuff.data[multiIndexToIndex(pybuff, [2, 0, -1])]);

Contiguity

If the buffer is not contiguous, the data TypedArray will contain data that is not part of the buffer. Modifying this data may lead to undefined behavior.

Readonly buffers

If buffer.readonly is true, you should not modify the buffer. Modifying a readonly buffer may lead to undefined behavior.

Converting between TypedArray types

The following naive code to change the type of a typed array does not work:

// Incorrectly convert a TypedArray.
// Produces a Uint16Array that points to the entire WASM memory!
let myarray = new Uint16Array(buffer.data.buffer);

Instead, if you want to convert the output TypedArray, you need to say:

// Correctly convert a TypedArray.
let myarray = new Uint16Array(
    buffer.data.buffer,
    buffer.data.byteOffset,
    buffer.data.byteLength
);
PyBuffer.c_contiguous

type: boolean

Is it C contiguous?

PyBuffer.data

type: TypedArray

The actual data. A typed array of an appropriate size backed by a segment of the WASM memory.

The type argument of getBuffer determines which sort of TypedArray this is, by default getBuffer will look at the format string to determine the most appropriate option.

PyBuffer.f_contiguous

type: boolean

Is it Fortran contiguous?

PyBuffer.format

type: string

The format string for the buffer. See the Python documentation on format strings.

PyBuffer.itemsize

type: number

How large is each entry (in bytes)?

PyBuffer.nbytes

type: number

The total number of bytes the buffer takes up. This is equal to buff.data.byteLength.

PyBuffer.ndim

type: number

The number of dimensions of the buffer. If ndim is 0, the buffer represents a single scalar or struct. Otherwise, it represents an array.

PyBuffer.offset

type: number

The offset of the first entry of the array. For instance if our array is 3d, then you will find array[0,0,0] at pybuf.data[pybuf.offset]

PyBuffer.readonly

type: boolean

If the data is readonly, you should not modify it. There is no way for us to enforce this, but it may cause very weird behavior.

PyBuffer.shape

type: number[]

The shape of the buffer, that is how long it is in each dimension. The length will be equal to ndim. For instance, a 2x3x4 array would have shape [2, 3, 4].

PyBuffer.strides

type: number[]

An array of of length ndim giving the number of elements to skip to get to a new element in each dimension. See the example definition of a multiIndexToIndex function above.

PyBuffer.release()

Release the buffer. This allows the memory to be reclaimed.