Skip to content

Commit

Permalink
Document sync_main_only flag and use cases.
Browse files Browse the repository at this point in the history
  • Loading branch information
ntoll committed May 13, 2024
1 parent 4422cac commit 86edd34
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 24 deletions.
2 changes: 1 addition & 1 deletion docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ solution. (These requirements are explored
workers are limited to one way calls from the main thread to methods
exposed by workers.

If `sync_main_only = True`, the following caveats apply:
If `sync_main_only = true`, the following caveats apply:

* It is not possible to manipulate the DOM or do anything meaningful on the
main thread **from a worker**. This is because Atomics cannot guarantee
Expand Down
80 changes: 57 additions & 23 deletions docs/user-guide/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ ensure the packages [arrr](https://arrr.readthedocs.io/en/latest/) and
[numberwang](https://numberwang.readthedocs.io/en/latest/) are installed from
PyPI (the [Python Packaging Index](https://pypi.org/)):

```TOML title="Configuration via TOML"
```TOML title="Configuration via TOML."
packages = ["arrr", "numberwang" ]
```

```JSON title="Configuration via JSON"
```JSON title="Configuration via JSON."
{
"packages": ["arrr", "numberwang"]
}
Expand All @@ -56,15 +56,15 @@ reference it from the tag used to specify the Python code:

If you use JSON, you can make it the value of the `config` attribute:

```HTML title="JSON as the value of the config attribute"
```HTML title="JSON as the value of the config attribute."
<script type="mpy" src="main.py" config='{"packages":["arrr", "numberwang"]}'></script>
```

For historical and convenience reasons we still support the inline
specification of configuration information via a _single_ `<py-config>` or
`<mpy-config>` tag in your HTML document:

```HTML title="Inline configuration via the &lt;py-config&gt; tag"
```HTML title="Inline configuration via the &lt;py-config&gt; tag."
<py-config>
{
"packages": ["arrr", "numberwang" ]
Expand All @@ -79,10 +79,10 @@ specification of configuration information via a _single_ `<py-config>` or

## Options

There are four core options ([`interpreter`](#interpreter), [`files`](#files),
[`packages`](#packages), and
[`js_modules`](#javascript-modules)) and an experimental flag
([experimental_create_proxy](#experimental_create_proxy)) that can be used in
There are five core options ([`interpreter`](#interpreter), [`files`](#files),
[`packages`](#packages), [`js_modules`](#javascript-modules) and
[`sync_main_only`](#sync_main_only)) and an experimental flag
([`experimental_create_proxy`](#experimental_create_proxy)) that can be used in
the configuration of PyScript. The user is also free to define
arbitrary additional configuration options that plugins or an app may require
for their own reasons.
Expand All @@ -100,11 +100,11 @@ a custom version of the interpreter.

The following two examples are equivalent:

```TOML title="Specify the interpreter version in TOML"
```TOML title="Specify the interpreter version in TOML."
interpreter = "0.23.4"
```

```JSON title="Specify the interpreter version in JSON"
```JSON title="Specify the interpreter version in JSON."
{
"interpreter": "0.23.4"
}
Expand All @@ -113,7 +113,7 @@ interpreter = "0.23.4"
The following JSON fragment uses a fully qualified URL to point to the same
version of Pyodide as specified in the previous examples:

```JSON title="Specify the interpreter via a fully qualified URL"
```JSON title="Specify the interpreter via a fully qualified URL."
{
"interpreter": "https://cdn.jsdelivr.net/pyodide/v0.23.4/full/pyodide.mjs"
}
Expand All @@ -127,7 +127,7 @@ destination filesystem path.

The following JSON and TOML are equivalent:

```json title="Fetch files onto the filesystem with JSON"
```json title="Fetch files onto the filesystem with JSON."
{
"files": {
"https://example.com/data.csv": "./data.csv",
Expand All @@ -136,7 +136,7 @@ The following JSON and TOML are equivalent:
}
```

```toml title="Fetch files onto the filesystem with TOML"
```toml title="Fetch files onto the filesystem with TOML."
[files]
"https://example.com/data.csv" = "./data.csv"
"/code.py" = "./subdir/code.py"
Expand All @@ -147,7 +147,7 @@ URL becomes the destination filename, in the root of the filesystem, to which
the content is copied. As a result, the `data.csv` entry from the previous
examples could be equivalently re-written as:

```json title="JSON implied filename in the root directory"
```json title="JSON implied filename in the root directory."
{
"files": {
"https://example.com/data.csv": "",
Expand All @@ -156,7 +156,7 @@ examples could be equivalently re-written as:
}
```

```toml title="TOML implied filename in the root directory"
```toml title="TOML implied filename in the root directory."
[files]
"https://example.com/data.csv" = ""
... etc ...
Expand Down Expand Up @@ -202,7 +202,7 @@ their name is replaced with their associated value.

The following JSON and TOML are equivalent:

```json title="Using the template language in JSON"
```json title="Using the template language in JSON."
{
"files": {
"{DOMAIN}": "https://my-server.com",
Expand All @@ -218,7 +218,7 @@ The following JSON and TOML are equivalent:
}
```

```toml title="Using the template language in TOML"
```toml title="Using the template language in TOML."
[files]
"{DOMAIN}" = "https://my-server.com"
"{PATH}" = "a/path"
Expand Down Expand Up @@ -287,11 +287,11 @@ to be installed onto the Python path.

The following two examples are equivalent:

```TOML title="A packages list in TOML"
```TOML title="A packages list in TOML."
packages = ["arrr", "numberwang", "snowballstemmer>=2.2.0" ]
```

```JSON title="A packages list in JSON"
```JSON title="A packages list in JSON."
{
"packages": ["arrr", "numberwang", "snowballstemmer>=2.2.0" ]
}
Expand Down Expand Up @@ -338,13 +338,13 @@ To specify such modules, simply provide a list of source/module name pairs.
For example, to use the excellent [Leaflet](https://leafletjs.com/) JavaScript
module for creating interactive maps you'd add the following lines:

```TOML title="JavaScript main thread modules defined in TOML"
```TOML title="JavaScript main thread modules defined in TOML."
[js_modules.main]
"https://cdn.jsdelivr.net/npm/[email protected]/dist/leaflet-src.esm.js" = "leaflet"
"https://cdn.jsdelivr.net/npm/[email protected]/dist/leaflet.css" = "leaflet" # CSS
```

```JSON title="JavaScript main thread modules defined in JSON"
```JSON title="JavaScript main thread modules defined in JSON."
{
"js_modules": {
"main": {
Expand Down Expand Up @@ -386,12 +386,12 @@ Some JavaScript modules (such as
access to the DOM and, for efficiency reasons, can be included in the worker
context:

```TOML title="A JavaScript worker module defined in TOML"
```TOML title="A JavaScript worker module defined in TOML."
[js_modules.worker]
"https://cdn.jsdelivr.net/npm/html-escaper" = "html_escaper"
```

```JSON title="A JavaScript worker module defined in JSON"
```JSON title="A JavaScript worker module defined in JSON."
{
"js_modules": {
"worker": {
Expand All @@ -404,6 +404,40 @@ context:
However, `from pyscript.js_modules import html_escaper` would then only work
within the context of Python code **running on a worker**.

### sync_main_only

Sometimes you just want to start an expensive computation on a web worker
without the need for the worker to interact with the main thread. You're simply
awaiting the result of a method exposed from a worker.

This has the advantage of not requiring the use of `SharedArrayBuffer` and
[associated CORS related header configuration](../workers/#http-headers).

If the `sync_main_only` flag is set, then **interactions between the main thread
and workers are limited to one way calls from the main thread to methods
exposed by the workers**.

```TOML title="Setting the sync_main_only flag in TOML."
sync_main_only = true
```

```JSON title="Setting the sync_main_only flag in JSON."
{
"sync_main_only": true
}
```

If `sync_main_only` is set, the following caveats apply:

* It is not possible to manipulate the DOM or do anything meaningful on the
main thread **from a worker**. This is because Atomics cannot guarantee
sync-like locks between a worker and the main thread.
* Only a worker's `pyscript.sync` methods are exposed, and **they can only be
awaited from the main thread**.
* The worker can only `await` main thread references one after the other, so
developer experience is degraded when one needs to interact with the
main thread.

### experimental_create_proxy

Knowing when to use the `pyscript.ffi.create_proxy` method when using Pyodide
Expand Down
14 changes: 14 additions & 0 deletions docs/user-guide/workers.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,20 @@ You don't need to know about Atomics to use web workers, but the underlying
[coincident library](http://localhost:8000/user-guide/architecture/#coincident)
uses it under the hood.

!!! info

Sometimes you only need to `await` in the main thread the result of a call
to a method exposed in a worker.

In such a limited case, and on the understanding that **code in the worker
will not be able to reach back into the main thread**, you should
use the [`sync_main_only` flag](../configuration/#sync_main_only) in your
configuration.

While this eliminates the need for the Atomics related header configuration
(see below), the only possible use case is to **return a serialisable
result from the method called on the worker**.

## HTTP headers

For Atomics to work **you must ensure your web server enables the following
Expand Down

0 comments on commit 86edd34

Please sign in to comment.