Skip to content

Commit dee2add

Browse files
authored
Merge pull request #99 from pyscript/2024-5-2
Update docs to 2024.5.2 version
2 parents 46b0b9b + 0b5c593 commit dee2add

File tree

8 files changed

+179
-43
lines changed

8 files changed

+179
-43
lines changed

README.md

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,27 @@
22

33
Welcome to the PyScript documentation repository.
44

5+
This source code becomes the official PyScript documentation hosted here:
6+
7+
[https://docs.pyscript.net](https://docs.pyscript.net/)
8+
59
Contribute prose and participate in discussions about the written support of
610
PyScript and related topics.
711

812
## Getting started
913

1014
Before you start contributing to the documentation, it's worthwhile to
11-
take a look at the general contributing guidelines for the PyScript project. You can find these guidelines here
15+
take a look at the general contributing guidelines for the PyScript project.
16+
You can find these guidelines here
1217
[Contributing Guidelines](https://github.com/pyscript/pyscript/blob/main/CONTRIBUTING.md)
1318

1419
## Setup
1520

1621
The `docs` directory in the pyscript repository contains a
17-
[Material for MkDocs](https://squidfunk.github.io/mkdocs-material/) documentation project. Material is a system
18-
that takes plaintext files containing documentation written in Markdown, along with
19-
static files like templates and themes, to build the static end result.
22+
[Material for MkDocs](https://squidfunk.github.io/mkdocs-material/)
23+
documentation project. Material is a system that takes plaintext files
24+
containing documentation written in Markdown, along with static files like
25+
templates and themes, to build the static end result.
2026

2127
To setup the documentation development environment simply create a new
2228
virtual environment, then `pip install -r requirements.txt` (from in the root
@@ -35,19 +41,22 @@ Simply run `mkdocs serve` or `./bin/mkdocs serve`.
3541

3642
## Cross-referencing
3743

38-
You can link to other pages in the documentation by using the `{doc}` role. For example, to link to the `docs/README.md` file, you would use:
44+
Link to other pages in the documentation by using the `{doc}` role. For
45+
example, to link to the `docs/README.md` file, you would use:
3946

4047
```markdown
4148
{doc}`docs/README.md`
4249
```
4350

44-
You can also cross-reference the python glossary by using the `{term}` role. For example, to link to the `iterable` term, you would use:
51+
Cross-reference the Python glossary by using the `{term}` role. For example, to
52+
link to the `iterable` term, you would use:
4553

4654
```markdown
4755
{term}`iterable`
4856
```
4957

50-
You can also cross-reference functions, methods or data attributes by using the `{attr}` for example:
58+
Cross-reference functions, methods or data attributes by using the `{attr}` for
59+
example:
5160

5261
```markdown
5362
{py:func}`repr`

docs/beginning-pyscript.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ module in the document's `<head>` tag:
112112
<meta charset="utf-8" />
113113
<meta name="viewport" content="width=device-width,initial-scale=1" />
114114
<title>🦜 Polyglot - Piratical PyScript</title>
115-
<link rel="stylesheet" href="https://pyscript.net/releases/2024.5.1/core.css">
116-
<script type="module" src="https://pyscript.net/releases/2024.5.1/core.js"></script>
115+
<link rel="stylesheet" href="https://pyscript.net/releases/2024.5.2/core.css">
116+
<script type="module" src="https://pyscript.net/releases/2024.5.2/core.js"></script>
117117
</head>
118118
<body>
119119

@@ -163,8 +163,8 @@ In the end, our HTML should look like this:
163163
<meta charset="utf-8" />
164164
<meta name="viewport" content="width=device-width,initial-scale=1" />
165165
<title>🦜 Polyglot - Piratical PyScript</title>
166-
<link rel="stylesheet" href="https://pyscript.net/releases/2024.5.1/core.css">
167-
<script type="module" src="https://pyscript.net/releases/2024.5.1/core.js"></script>
166+
<link rel="stylesheet" href="https://pyscript.net/releases/2024.5.2/core.css">
167+
<script type="module" src="https://pyscript.net/releases/2024.5.2/core.js"></script>
168168
</head>
169169
<body>
170170
<h1>Polyglot 🦜 💬 🇬🇧 ➡️ 🏴‍☠️</h1>

docs/faq.md

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ solution. (These requirements are explored
9191
workers are limited to one way calls from the main thread to methods
9292
exposed by workers.
9393

94-
If `sync_main_only = True`, the following caveats apply:
94+
If `sync_main_only = true`, the following caveats apply:
9595

9696
* It is not possible to manipulate the DOM or do anything meaningful on the
9797
main thread **from a worker**. This is because Atomics cannot guarantee
@@ -376,6 +376,85 @@ obsolete standards.
376376
While such legacy code exists, be aware that JavaScript code may require
377377
special care.
378378

379+
### Possible deadlock
380+
381+
Users may encounter an error message similar to the following:
382+
383+
!!! failure
384+
385+
```
386+
💀🔒 - Possible deadlock if proxy.xyz(...args) is awaited
387+
```
388+
389+
#### When
390+
391+
This error happens when your code on a worker and in the main thread are
392+
[in a deadlock](https://en.wikipedia.org/wiki/Deadlock). Put simply, neither
393+
fragment of code can proceed without waiting for the other.
394+
395+
#### Why
396+
397+
Let's assume a worker script contains the following Python code:
398+
399+
```python title="worker: a deadlock example"
400+
from pyscript import sync
401+
402+
sync.worker_task = lambda: print('🔥 this is fine 🔥')
403+
404+
# deadlock 💀🔒
405+
sync.main_task()
406+
```
407+
408+
On the main thread, let's instead assume this code:
409+
410+
```html title="main: a deadlock example"
411+
<script type="mpy">
412+
from pyscript import PyWorker
413+
414+
def async main_task():
415+
# deadlock 💀🔒
416+
await pw.sync.worker_task()
417+
418+
pw = PyWorker("./worker.py", {"type": "pyodide"})
419+
pw.sync.main_task = main_task
420+
</script>
421+
```
422+
423+
When the worker bootstraps and calls `sync.main_task()` on the main thread, it
424+
blocks until the result of this call is returned. Hence it cannot respond to
425+
anything at all. However, in the code on the main thread, the
426+
`sync.worker_task()` in the worker is called, but the worker is blocked! Now
427+
the code on both the main thread and worker are mutually blocked and waiting
428+
on each other. We are in a classic
429+
[deadlock](https://en.wikipedia.org/wiki/Deadlock) situation.
430+
431+
The moral of the story? Don't create such circular deadlocks!
432+
433+
How?
434+
435+
The mutually blocking calls cause the deadlock, so simply don't block.
436+
437+
For example, on the main thread, let's instead assume this code:
438+
439+
```html title="main: avoiding deadlocks"
440+
<script type="mpy">
441+
from pyscript import window, PyWorker
442+
443+
async def main_task():
444+
# do not await the worker,
445+
# just schedule it for later (as resolved)
446+
window.Promise.resolve(pw.sync.worker_task())
447+
448+
pw = PyWorker("./worker.py", {"type": "pyodide"})
449+
pw.sync.main_task = main_task
450+
</script>
451+
```
452+
453+
By scheduling the call to the worker (rather than awaiting it), it's possible
454+
for the main thread to call functions defined in the worker in a non-blocking
455+
manner, thus allowing the worker to also work in an unblocked manner and react
456+
to such calls. We have resolved the mutual deadlock.
457+
379458
## Helpful hints
380459

381460
This section contains common hacks or hints to make using PyScript easier.

docs/user-guide/configuration.md

Lines changed: 57 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ ensure the packages [arrr](https://arrr.readthedocs.io/en/latest/) and
3535
[numberwang](https://numberwang.readthedocs.io/en/latest/) are installed from
3636
PyPI (the [Python Packaging Index](https://pypi.org/)):
3737

38-
```TOML title="Configuration via TOML"
38+
```TOML title="Configuration via TOML."
3939
packages = ["arrr", "numberwang" ]
4040
```
4141

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

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

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

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

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

8080
## Options
8181

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

101101
The following two examples are equivalent:
102102

103-
```TOML title="Specify the interpreter version in TOML"
103+
```TOML title="Specify the interpreter version in TOML."
104104
interpreter = "0.23.4"
105105
```
106106

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

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

128128
The following JSON and TOML are equivalent:
129129

130-
```json title="Fetch files onto the filesystem with JSON"
130+
```json title="Fetch files onto the filesystem with JSON."
131131
{
132132
"files": {
133133
"https://example.com/data.csv": "./data.csv",
@@ -136,7 +136,7 @@ The following JSON and TOML are equivalent:
136136
}
137137
```
138138

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

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

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

203203
The following JSON and TOML are equivalent:
204204

205-
```json title="Using the template language in JSON"
205+
```json title="Using the template language in JSON."
206206
{
207207
"files": {
208208
"{DOMAIN}": "https://my-server.com",
@@ -218,7 +218,7 @@ The following JSON and TOML are equivalent:
218218
}
219219
```
220220

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

288288
The following two examples are equivalent:
289289

290-
```TOML title="A packages list in TOML"
290+
```TOML title="A packages list in TOML."
291291
packages = ["arrr", "numberwang", "snowballstemmer>=2.2.0" ]
292292
```
293293

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

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

347-
```JSON title="JavaScript main thread modules defined in JSON"
347+
```JSON title="JavaScript main thread modules defined in JSON."
348348
{
349349
"js_modules": {
350350
"main": {
@@ -386,12 +386,12 @@ Some JavaScript modules (such as
386386
access to the DOM and, for efficiency reasons, can be included in the worker
387387
context:
388388

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

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

407+
### sync_main_only
408+
409+
Sometimes you just want to start an expensive computation on a web worker
410+
without the need for the worker to interact with the main thread. You're simply
411+
awaiting the result of a method exposed from a worker.
412+
413+
This has the advantage of not requiring the use of `SharedArrayBuffer` and
414+
[associated CORS related header configuration](../workers/#http-headers).
415+
416+
If the `sync_main_only` flag is set, then **interactions between the main thread
417+
and workers are limited to one way calls from the main thread to methods
418+
exposed by the workers**.
419+
420+
```TOML title="Setting the sync_main_only flag in TOML."
421+
sync_main_only = true
422+
```
423+
424+
```JSON title="Setting the sync_main_only flag in JSON."
425+
{
426+
"sync_main_only": true
427+
}
428+
```
429+
430+
If `sync_main_only` is set, the following caveats apply:
431+
432+
* It is not possible to manipulate the DOM or do anything meaningful on the
433+
main thread **from a worker**. This is because Atomics cannot guarantee
434+
sync-like locks between a worker and the main thread.
435+
* Only a worker's `pyscript.sync` methods are exposed, and **they can only be
436+
awaited from the main thread**.
437+
* The worker can only `await` main thread references one after the other, so
438+
developer experience is degraded when one needs to interact with the
439+
main thread.
440+
407441
### experimental_create_proxy
408442

409443
Knowing when to use the `pyscript.ffi.create_proxy` method when using Pyodide

docs/user-guide/first-steps.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ CSS:
2020
<meta charset="UTF-8">
2121
<meta name="viewport" content="width=device-width,initial-scale=1.0">
2222
<!-- PyScript CSS -->
23-
<link rel="stylesheet" href="https://pyscript.net/releases/2024.5.1/core.css">
23+
<link rel="stylesheet" href="https://pyscript.net/releases/2024.5.2/core.css">
2424
<!-- This script tag bootstraps PyScript -->
25-
<script type="module" src="https://pyscript.net/releases/2024.5.1/core.js"></script>
25+
<script type="module" src="https://pyscript.net/releases/2024.5.2/core.js"></script>
2626
</head>
2727
<body>
2828
<!-- your code goes here... -->

0 commit comments

Comments
 (0)