Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ bin
lib
lib64
pyvenv.cfg
*.swp
55 changes: 55 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1100,6 +1100,61 @@ PyWorker("worker.py", type="micropython")
<div id="output"></div> <!-- The display target -->
```

!!! info

Sometimes code running on a worker gets stuck in an infinite loop and
becomes unresponsive. There are many complicated reasons why this might
happen, but when it does happen you likely want to break out of this
loop. This is where the `isStuck` and `notStuck` features come into play.

If you have code in the worker that could end up in an unresponsive
infinite loop, for example:

```python
import time

while True:
time.sleep(1)
print("Stuck in a loop")
```

...then you only need wrap this code in the worker like this:

```python
import time
from pyscript import sync
is_stuck = sync.isStuck
break_loop = sync.notStuck

def is_not_stuck(condition):
if not condition and is_stuck():
# this is a must to reset the "stuck" state
break_loop()
# throw an error to get out of the loop
raise RuntimeError('Worker was stuck, but now it is unstuck')
return condition

while is_not_stuck(True):
time.sleep(1)
print("Stuck in a loop")
```

From your code on the main thread you may have something like this:

```python
from pyscript import PyWorker

w = PyWorker("sticky_code.py", type="micropython")

@when("click", "unstick_button")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unstick ? 😁

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, buttons can be sticky. 😛

def handle_unstick():
w.unstuck()
```

This starts the worker with you code that could get into an infinite loop,
then defines a function that calls the `unstuck()` function on the worker
when a button on the UI is clicked.

### `pyscript.workers`

The `pyscript.workers` reference allows Python code in the main thread to
Expand Down
49 changes: 45 additions & 4 deletions docs/beginning-pyscript.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ module in the document's `<head>` tag:
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>🦜 Polyglot - Piratical PyScript</title>
<link rel="stylesheet" href="https://pyscript.net/releases/2025.11.1/core.css">
<script type="module" src="https://pyscript.net/releases/2025.11.1/core.js"></script>
<link rel="stylesheet" href="https://pyscript.net/releases/2025.11.2/core.css">
<script type="module" src="https://pyscript.net/releases/2025.11.2/core.js"></script>
</head>
<body>

Expand Down Expand Up @@ -168,8 +168,8 @@ In the end, our HTML should look like this:
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>🦜 Polyglot - Piratical PyScript</title>
<link rel="stylesheet" href="https://pyscript.net/releases/2025.11.1/core.css">
<script type="module" src="https://pyscript.net/releases/2025.11.1/core.js"></script>
<link rel="stylesheet" href="https://pyscript.net/releases/2025.11.2/core.css">
<script type="module" src="https://pyscript.net/releases/2025.11.2/core.js"></script>
</head>
<body>
<h1>Polyglot 🦜 💬 🇬🇧 ➡️ 🏴‍☠️</h1>
Expand Down Expand Up @@ -231,6 +231,41 @@ points to the `div` element with the id "output". Finally, we assign the

That's it!

## Editing you app

If you use an IDE (like VSCode or PyCharm) then you'll probably want them to
auto-suggest and introspect aspects of the Python code you're writing. The
problem is that the `pyscript` namespace *we provide* isn't installed anywhere
(because it's in your browser, not your IDE's context) so such information
isn't, by default, picked up.

Thankfully Python stubs come to the rescue.

Members of our community have
[created Python stub files for PyScript](https://github.com/pyscript/pyscript-stubs).
You should clone the linked-to repository and configure your IDE to consume the
stub files.

For example, let's say you
[cloned the repository](https://github.com/pyscript/pyscript-stubs) into:
`~/src/stubs/pyscript-stubs`, then in VSCode, you'd create, in your PyScript
project, a file called `.vscode/settings.json` and add the following:

```js
{
"python.analysis.stubPath": "~/src/stubs/pyscript-stubs/src/pyscript-stubs"
}
```

Then restart the Python language server in VSCode (Press `Ctrl+Shift+P` (or
`Cmd+Shift+P` on Mac) to open the Command Palette and type:
`Python: Restart Language Server`.

!!! note

The stubs themselves are found within the `src/pyscript-stubs` directory
in the git repository, hence the longer path in the configuration file.

## Sharing your app

### PyScript.com
Expand Down Expand Up @@ -263,6 +298,12 @@ To run PyScript offline, without the need of a CDN or internet connection, read
the [Run PyScript Offline](user-guide/offline.md) section of the user
guide.

We also provide an `offline.zip` file with
[each release](https://pyscript.net/releases/2025.11.2/). This file contains
everything you need for an offline version of PyScript: PyScript itself,
versions of Pyodide and MicroPython, and an index.html page from which you
could create your offline-first PyScript work.

## Conclusion

Congratulations!
Expand Down
4 changes: 2 additions & 2 deletions docs/user-guide/first-steps.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ CSS:
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<!-- PyScript CSS -->
<link rel="stylesheet" href="https://pyscript.net/releases/2025.11.1/core.css">
<link rel="stylesheet" href="https://pyscript.net/releases/2025.11.2/core.css">
<!-- This script tag bootstraps PyScript -->
<script type="module" src="https://pyscript.net/releases/2025.11.1/core.js"></script>
<script type="module" src="https://pyscript.net/releases/2025.11.2/core.js"></script>
</head>
<body>
<!-- your code goes here... -->
Expand Down
10 changes: 5 additions & 5 deletions docs/user-guide/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ For example, this will work because all references are contained within the
registered function:

```js
import { hooks } from "https://pyscript.net/releases/2025.11.1/core.js";
import { hooks } from "https://pyscript.net/releases/2025.11.2/core.js";

hooks.worker.onReady.add(() => {
// NOT suggested, just an example!
Expand All @@ -114,7 +114,7 @@ hooks.worker.onReady.add(() => {
However, due to the outer reference to the variable `i`, this will fail:

```js
import { hooks } from "https://pyscript.net/releases/2025.11.1/core.js";
import { hooks } from "https://pyscript.net/releases/2025.11.2/core.js";

// NO NO NO NO NO! ☠️
let i = 0;
Expand Down Expand Up @@ -147,7 +147,7 @@ the page.

```js title="log.js - a plugin that simply logs to the console."
// import the hooks from PyScript first...
import { hooks } from "https://pyscript.net/releases/2025.11.1/core.js";
import { hooks } from "https://pyscript.net/releases/2025.11.2/core.js";

// The `hooks.main` attribute defines plugins that run on the main thread.
hooks.main.onReady.add((wrap, element) => {
Expand Down Expand Up @@ -197,8 +197,8 @@ hooks.worker.onAfterRun.add(() => {
<!-- JS plugins should be available before PyScript bootstraps -->
<script type="module" src="./log.js"></script>
<!-- PyScript -->
<link rel="stylesheet" href="https://pyscript.net/releases/2025.11.1/core.css">
<script type="module" src="https://pyscript.net/releases/2025.11.1/core.js"></script>
<link rel="stylesheet" href="https://pyscript.net/releases/2025.11.2/core.css">
<script type="module" src="https://pyscript.net/releases/2025.11.2/core.js"></script>
</head>
<body>
<script type="mpy">
Expand Down
4 changes: 2 additions & 2 deletions docs/user-guide/pygame-ce.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ will be placed. Make sure to update the pyscript release to the latest version.
<title>PyScript Pygame-CE Quickstart</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="stylesheet" href="https://pyscript.net/releases/2025.11.1/core.css">
<script type="module" src="https://pyscript.net/releases/2025.11.1/core.js"></script>
<link rel="stylesheet" href="https://pyscript.net/releases/2025.11.2/core.css">
<script type="module" src="https://pyscript.net/releases/2025.11.2/core.js"></script>
</head>
<body>
<canvas id="canvas" style="image-rendering: pixelated"></canvas>
Expand Down
4 changes: 2 additions & 2 deletions docs/user-guide/workers.md
Original file line number Diff line number Diff line change
Expand Up @@ -286,9 +286,9 @@ Here's how:
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<!-- PyScript CSS -->
<link rel="stylesheet" href="https://pyscript.net/releases/2025.11.1/core.css">
<link rel="stylesheet" href="https://pyscript.net/releases/2025.11.2/core.css">
<!-- This script tag bootstraps PyScript -->
<script type="module" src="https://pyscript.net/releases/2025.11.1/core.js"></script>
<script type="module" src="https://pyscript.net/releases/2025.11.2/core.js"></script>
<title>PyWorker - mpy bootstrapping pyodide example</title>
<script type="mpy" src="main.py"></script>
</head>
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
mkdocs-material==9.3.1
mike==1.1.2
setuptools
2 changes: 1 addition & 1 deletion version.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"version": "2025.11.1"
"version": "2025.11.2"
}