From 35ede4e4e8ecc6224ac94696d9db82f5f92a07ff Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Thu, 21 Sep 2023 16:52:05 +0100 Subject: [PATCH 001/201] First draft of mostly complete user guide. TODO: finish this. --- docs/assets/images/micropython.png | Bin 0 -> 13955 bytes docs/assets/images/pyodide.png | Bin 0 -> 11750 bytes docs/beginning-pyscript.md | 9 +- docs/user-guide.md | 856 +++++++++++++++++++++++++++++ docs/user-guide/code.md | 1 - docs/user-guide/configuration.md | 1 - docs/user-guide/dom.md | 2 - docs/user-guide/ffi.md | 1 - docs/user-guide/index.md | 485 ---------------- docs/user-guide/interpreters.md | 1 - docs/user-guide/plugins.md | 2 - docs/user-guide/workers.md | 1 - 12 files changed, 864 insertions(+), 495 deletions(-) create mode 100644 docs/assets/images/micropython.png create mode 100644 docs/assets/images/pyodide.png create mode 100644 docs/user-guide.md delete mode 100644 docs/user-guide/code.md delete mode 100644 docs/user-guide/configuration.md delete mode 100644 docs/user-guide/dom.md delete mode 100644 docs/user-guide/ffi.md delete mode 100644 docs/user-guide/index.md delete mode 100644 docs/user-guide/interpreters.md delete mode 100644 docs/user-guide/plugins.md delete mode 100644 docs/user-guide/workers.md diff --git a/docs/assets/images/micropython.png b/docs/assets/images/micropython.png new file mode 100644 index 0000000000000000000000000000000000000000..239471506388c827a203b9fe552d7e9d6d174fd0 GIT binary patch literal 13955 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 ZVlylJ=w|1n805$RNQ%mdR0|md{Vxw6BJcnJ literal 0 HcmV?d00001 diff --git a/docs/assets/images/pyodide.png b/docs/assets/images/pyodide.png new file mode 100644 index 0000000000000000000000000000000000000000..587a2d82657721057a63a2222307b5b5b537fb51 GIT binary patch literal 11750 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 yg3Z>z02I;CRrn1*0Osob5U@Y!=m*PhP}Ttl9&R +
All the web
+
+

Pyscript gives you full access to the DOM and all + the web + APIs implemented by your browser.

+ +

Thanks to the foreign + function interface (FFI), it is easy for Python to work within your + browser, including with third party JavaScript libraries that may be + included in the page.

+ +

The FFI is bi-directional ~ it also enables JavaScript to access the + power of PyScript.

+ +
All of Python
+
+

PyScript brings you two Python interpreters:

+
    +
  1. Pyodide - the original standard + CPython interpreter you know and love, but compiled to web + assembly.
  2. +
  3. MicroPython - a lean and + efficient reimplementation of Python3 that includes a comprehensive + subset of the standard library, compiled to web assembly.
  4. +
+
+

Warning

+

Currently, only Pyodide is enabled in PyScript.

+

This will change very soon once we complete our integration testing and + evaluation steps for MicroPython. However, the documentation relating + to MicroPython is currently correct and is included to indicate what + you have to look forward to.

+
+

Because it is just regular CPython, Pyodide puts Python's deep and + diverse ecosystem of libraries, frameworks + and modules at your disposal. If you find yourself encountering some sort + of computing problem, there's probably a Python library to help you with + it. If you use a favourite library in Python, now you can use it in your + browser and share your work with ease via a URL.

+

MicroPython, because of its small size (170k) and speed, is especially + suited to running on more constrained browsers, such as those on mobile + or tablet devices. It includes a powerful sub-set of the Python standard + library and efficiently exposes the expressiveness of Python to the + browser.

+

Both Python interpreters supported by PyScript implement the same + FFI to bridge the gap between the worlds of Python and the browser.

+
+ +
AI and Data science built in
+
Python is famous for its extraordinary usefulness in artificial + intelligence and data science. The Pyodide interpreter comes with many of + the libraries you need for this sort of work already baked in.
+ +
Mobile friendly MicroPython
+
+

Thanks to MicroPython in PyScript, there is a compelling story for + Python on mobile.

+ +

MicroPython is small and fast enough that your app will start quickly + on first load, and almost instantly (due to the cache) on subsequent + runs.

+ +
Parallel execution
+
Thanks to a browser technology called + web workers + expensive and blocking computation can run somewhere other than the main + application thread that controls the user interface. When such work is done + on the main thread, the browser appears frozen. Web workers ensure + expensive blocking computation happens elsewhere. Think of workers as + independent subprocesses in your web page.
+ +
Rich and powerful plugins
+
+

As you'll see, PyScript has a small, efficient yet powerful core called + PolyScript.

+

Most of the functionality of PyScript is actually implemented through + PolyScript's plugin system.

+ +

This approach means we get a clear separation of concerns: PolyScript + can focus on being small, efficient and powerful, whereas the PyScript + related plugins allow us to build upon the generic features provided by + PolyScript.

+

More importantly, because there is a plugin system, folks + independent of the PyScript core team have a way to create their + own plugins so we get a rich ecosystem of functionality that reflects the + unique and diverse needs of PyScript's users.

+
+ + +## First steps + +It's simple: + +* tell your browser to use PyScript, then, +* tell PyScript how to run your Python code. + +For the browser to use PyScript, simply add a ` + + + + + +``` + +There are two ways to tell PyScript how to find your code. + +* With a standard HTML ` +``` + +...and here's the `` tag with inline Python code. + +```html title="Using the py-script tag with inline code" + +import sys +from pyscript import display + + +display(sys.version) + +``` + +The browser's tab displaying the website running PyScript is an isolated +computing sandbox. Define the Python environment in which your code will +run with [configuration options](#configuration) (discussed later in this +document). + +The ` + + ``` + + Notice how different interpreters can be used in different contexts. + +## Architecture + +There are two important aspects of PyScript's architecture: + +1. A small, efficient and powerful kernel called + [PolyScript](https://github.com/pyscript/polyscript) is the foundation + upon which PyScript and plugins are built. +2. The PyScript [stack](https://en.wikipedia.org/wiki/Solution_stack) inside + the browser is relatively simple and easy to understand. + +### PolyScript + +[PolyScript](https://github.com/pyscript/polyscript) is the core of PyScript. + +!!! info + + Unless you are an advanced user, you probably don't need to know much more + than PolyScript exists, and it can be safely ignored. + +PolyScript's purpose is to bootstrap the platform and provide all the necessary +core capabilities. Setting aside PyScript for a moment, to use +*just PolyScript* requires a ` + + + + + + +``` + +PolyScript's capabilities, upon which PyScript is built, can be summarised as: + +* Evaluation of code via [` +``` + +If you use JSON, you can make it the value of the `config` attribute: + +```HTML title="JSON as the value of the config attribute" + +``` + +For historical and convenience reasons we still support the inline +specification of configuration information via a _single_ `` tag in +your HTML document: + +```HTML title="Inline configuration via the <py-config> tag" + +{ + "packages": ["arrr", "numberwang" ] +} + +``` + +!!! warning + + Should you use ``, **there must be only one of these tags on the + page**. + +### Options + +There are three core options, and the user is free to define arbitrary +additional configuration options that plugins or an app may require for their +own reasons. + +#### Fetch + +The `fetch` option fetches files from URLs onto the filesystem emulated by the +browser. + +**TODO: Fix this.** + +#### Packages + +The `packages` option defines a list of Python `packages` to be installed from +[PyPI](https://pypi.org/) onto the filesystem by Pyodide's +[micropip](https://micropip.pyodide.org/en/stable/index.html) package +installer. + +The following two examples are equivalent: + +```TOML title="A packages list in TOML" +packages = ["arrr", "numberwang", "snowballstemmer>=2.2.0" ] +``` + +```JSON title="A packages list in JSON" +{ + "packages": ["arrr", "numberwang", "snowballstemmer>=2.2.0" ] +} +``` + +!!! warning + + Because `micropip` is a Pyodide-only feature, and MicroPython doesn't + support code packaged on PyPI, **the `packages` option is only available + if you use Pyodide as your interpreter**. + +The names in the list of `packages` can be any of the following valid forms: + +* A name of a package on PyPI: `"snowballstemmer"` +* A name for a package on PyPI with additional constraints: `"snowballstemmer>=2.2.0"` +* An arbitrary URL to a Python package: `"https://.../package.whl"` +* A file copied onto the browser based file system: `"emfs://.../package.whl"` + +#### Plugins + +The `plugins` enumerate plugins enabled by PyScript to add extra functionality +to the platform. + +Each plugin should be included on the web page, as described in the +[plugins](#plugins) section below. Then the plugin's name should be listed. + +```TOML title="A list of plugins in TOML" +plugins = ["custom_plugin", "!error"] +``` + +```JSON title="A list of plugins in JSON" +{ + "plugins": ["custom_plugin", "!error"] +} +``` + +!!! info + + The `"!error"` syntax is a way to turn off a plugin built into PyScript + that is enabled by default. + + Currently, the only built-in plugin is the `error` plugin (which displays a + stack trace and error messages in the DOM). More may be added at a later + date. + +#### Custom + +Sometimes plugins or apps need bespoke configuration options. + +So long as you don't cause a name collision with the built-in option names then +you are free to use any valid data structure that works with both TOML and JSON +to express your configuration needs. + +**TODO: explain how to programmatically get access to an object representing +the config.** + +## The DOM + +The DOM +([document object model](https://developer.mozilla.org/en-US/docs/Web/API/Document_object_model)) +refers to a tree like data structure that represents the web page in the +browser. PyScript needs to be able to interact with the DOM in order to change +the user interface and react to things happening in the browser. + +There are currently two ways to interact with the DOM: + +1. Through the foreign function interface (FFI) and by directly interacting + with the objects found in the browser's `globalThis` object. +2. Through the `pydom` module that comes as standard with PyScript. + +### FFI + +The foreign function interface (FFI) gives Python access to all the +[standard web capabilities and features](https://developer.mozilla.org/en-US/docs/Web), +such as the browser's built-in +[web APIs](https://developer.mozilla.org/en-US/docs/Web/API). + +This is available via the `pyscript.window` module which is a proxy for +JavaScript's `globalThis` object, or `pyscript.document` which is a proxy for +the `document` object in JavaScript: + +```Python title="Accessing the window and document objects in Python" +from pyscript import window, document + + +my_element = document.querySelector("#my-id") +my_element.innerText = window.location.hostname +``` + +### PyDom + +The built in Python module `pydom` wraps many (although not all) the features +available via the FFI in a more idiomatically Pythonic library. + + +The PyDom API is extensively described and demonstrated +[on this PyScript page](https://fpliger.pyscriptapps.com/pyweb/latest/pydom.html). + +!!! warning + + PyDom is currently a work in progress. + + We welcome feedback and suggestions. + +## Workers + +Workers allow you to run code in a way that won't block the "main thread" that +controls the user interface. If you block the main thread, your web page +becomes annoyingly unresponsive. You should never block the main thread. + +Happily, PyScript makes it very easy to use workers. To make this happen +PyScript uses a feature recently added to web standards called +[Atomics](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics). + +### HTTP headers + +In order for Atomics to work **you must ensure your web server should enable +the following headers** (this is the default behaviour for +[pyscript.com](pyscript.com)): + +``` +Cross-Origin-Opener-Policy: same-origin +Cross-Origin-Embedder-Policy: require-corp +Cross-Origin-Resource-Policy: cross-origin +``` + +If you are not able to configure your server's headers, you could try to use +the [mini-coi](https://github.com/WebReflection/mini-coi#readme) project to +achieve the same end. + +### Start working + +To start your code in a worker, simply ensure the ` +``` + +Of course, code running in the worker needs to be able to access the web page +running in the main thread. This is achieved via some builtin helper utilities +described in the next section. + +!!! note + + The worker related functionality in PyScript is, for the sake of ease of + use, a simpler presentation of more sophisticated and powerful behaviour + available via PolyScript. + + Please [consult the XWorker](https://pyscript.github.io/polyscript/#xworker) + related documentation from the PolyScript project for how to make use of + these features. + +## Builtin helpers + +PyScript makes available various convenience objects and functions inside +Python. This is done via the `pyscript` module: + +```python title="Accessing the document object via the pyscript module" +from pyscript import document +``` + +### Common features + +These objects / functions are available in both the main thread and in code +running on a web worker: + +#### `pyscript.window` + +This object is a proxy for the web page's +[global window context](https://developer.mozilla.org/en-US/docs/Web/API/Window). + +!!! warning + + Please note that in workers, this is still the main window, not the + worker's own global context. A worker's global context is reachable instead + via `import js` (the `js` object being a proxy for `globalThis`). + +#### `pyscript.document` + +This object is a proxy for the the web page's +[document object](https://developer.mozilla.org/en-US/docs/Web/API/Document). +The `document` is a representation of the +[DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_object_model/Using_the_Document_Object_Model) +and can be used to manipulate the content of the web page. + +#### `pyscript.display` + +A function used to display content. The function is intelligent enough to +introspect the object[s] it is passed and work out how to correctly display the +object[s] in the web page. + +The `display` function takes a list of `*values` as its first argument, and has +two optional named arguments: + +* `target=None` - the DOM element into which the content should be placed. +* `append=False` - a flag to indicate if the output is going to be appended to + the `target`. + +There are some caveats: + +* When used in the main thread, the `display` function automatically uses + the current ` - - - - - - -``` - -PolyScript provides a -[small yet powerful set of capabilities](https://pyscript.github.io/polyscript/) -upon which PyScript itself is built. - -These can be summarised as: - -* Evaluation of code via ` - - - - - -``` - -There are two ways to tell PyScript where to find your code. - -* With a standard HTML ` -``` - -...and here's the `` tag with inline Python code. - -```html title="Using the py-script tag with inline code" - -import sys - - -print(sys.version) - -``` - -Both tags accept various attributes to control their behaviour. More detailed -information can be found on the [page about code](code). - -### Interpreters - -Python is an interpreted language, and thus needs an interpreter to work. - -PyScript currently supports two versions of the Python interpreter that have -been compiled to WASM: Pyodide and MicroPython. You should select which one to -use depending on your use case and acceptable trade-offs. - -Both interpreters make use of [emscripten](https://emscripten.org/), a compiler -toolchain (using LLVM), for emitting WASM assets for the browser. Emscripten -also provides APIs so operating-system level features such as a sandboxed file -system (**not** the user's local machine's filesystem), IO (`stdin`, `stdout`, -`stderr` etc,) and networking are available within the context of a browser. - -#### Pyodide - -[Pyodide](https://pyodide.org/) is a version of the standard -[CPython](https://python.org/) interpreter, patched to compile to WASM and -work in the browser. - -It is a mature and stable build of the CPython interpreter and includes many -useful features: - -* A robust [Python](https://pyodide.org/en/stable/usage/api/python-api.html) - ⟺ [JavaScript](https://pyodide.org/en/stable/usage/api/js-api.html) foreign - function interface (FFI). This bridges the gap between the browser and Python - worlds. -* The installation of pure Python packages from [PyPI](https://pypi.org/) via - the [micropip](https://micropip.pyodide.org/en/stable/index.html) package - installer. Some packages with C extensions have versions compiled for WASM - and these can also be installed with `micropip`. There are plans afoot to - make WASM a target in PyPI so packages with C extenions can be automatically - compiled to WASM. -* An active, friendly and technically outstanding team of volunteer - contributors (some of whom have been supported by the PyScript project). -* Extensive official - [documentation](https://micropip.pyodide.org/en/stable/index.html), and many - tutorials found online. -* Builds of Pyodide that include popular packages for data science like - [Numpy](https://numpy.org/), [Scipy](https://scipy.org/) and - [Pandas](https://pandas.pydata.org/). - -#### MicroPython - -[MicroPython](https://micropython.org/) is a lean and efficient implementation -of the Python 3 programming language that includes a small subset of the Python -standard library and is optimised to run on microcontrollers and in constrained -environments (like the browser). - -Everything needed to view a web page in a browser needs to be delivered -over the network. The smaller the asset to be delivered can be, the better. -MicroPython, when compressed for delivery to the browser, is only around -170k in size - smaller than most images you find on most websites. - -This makes MicroPython particularly suited to browsers running in a more -constrained environment such as on a mobile or tablet based device. Browsing -with these devices usually uses (slower) mobile internet connections. -Furthermore, because MicroPython is lean and efficient it still performs -exceptionally well on these relatively underpowered devices. - -Thanks to collaboration between the MicroPython and PyScript projects, there is -a foreign function interface for MicroPython. The MicroPython FFI deliberately -copies the API of the FFI originally written for Pyodide - meaning it is -relatively easy to migrate between the two supported interpreters. - -Further details and more in-depth discussion of the interpreters supported by -PyScript can be found on [the interpreters page](interpreters). - -### The DOM - -The DOM -([document object model](https://developer.mozilla.org/en-US/docs/Web/API/Document_object_model)) -refers to a tree like data structure that represents the web page in the -browser. PyScript needs to be able to interact with the DOM in order to change -the user interface and react to things happening in the browser. - -There are currently two ways to interact with the DOM: - -1. Through the FFI and by directly interacting with the objects found in the - `globalThis` object. -2. Through the `pydom` module that comes as standard with PyScript. - -The first option gives you access to all the [standard web capabilities and -features](https://developer.mozilla.org/en-US/docs/Web), such as the browser's -built-in [web APIs](https://developer.mozilla.org/en-US/docs/Web/API), and the -`document` object at the root of the [DOM tree](https://developer.mozilla.org/en-US/docs/Web/API/Document_object_model/Using_the_Document_Object_Model#what_is_a_dom_tree). - -The second is a Python module called `pydom` that wraps many (although not all) -the features available via the FFI in a more idiomatically Pythonic library... -**TODO: Fabio to finish this bit...** - -Explore the PyScript story of working with the DOM in [the DOM page](dom). - -### Configuration - -Sometimes we need to tell PyScript about how we want our Python environment to -be configured. To this end there are three core options: - -* `fetch` files from URLs onto the filesystem emulated by the browser for your - web page. -* A list of Python `packages` to be installed from [PyPI](https://pypi.org/) - onto the filesystem by Pyodide's - [micropip](https://micropip.pyodide.org/en/stable/index.html) package - installer. -* A list of `plugins` to be enabled by PyScript to add extra functionality to - the platform. - -!!! warning - - Because `micropip` is a Pyodide-only feature, and MicroPython doesn't - support code packaged on PyPI, **the `packages` option is only available - if you use Pyodide as your interpreter**. - -#### TOML or JSON - -Configuration can be expressed in two formats: - -* [TOML](https://toml.io/en/) is the configuration file format most often used - by folks in the Python community. -* [JSON](https://www.json.org/json-en.html) is a data format most often used - by folks in the web community. - -Since PyScript is the marriage of Python and the web, we support both. - -However, because JSON is built into all browsers by default and TOML requires -an additional download of a specialist parser before PyScript can work, the -use of JSON is more efficient from a performance point of view. - -The following two configurations are equivalent, and simply tell PyScript to -ensure the packages `arrr` and `numberwang` are installed from PyPI - -```TOML title="Configuration via TOML" -packages = ["arrr", "numberwang" ] -``` - -```JSON title="Configuration via JSON" -{ - "packages": ["arrr", "numberwang"] -} -``` - -#### File based or inline configuration - -The recommended way to write configurations is via a separate file and -referencing it from the tag used to specify the Python code: - -```HTML title="Reference a configuration file" - -``` - -For historical and convenience reasons we still support the inline -specification of configuration information via the `` tag used -in your HTML document: - -```HTML title="Inline configuration via the <py-config> tag" - -{ - "packages": ["arrr", "numberwang" ] -} - -``` - -Fully worked out examples of how to configure each of the `fetch`, `packages` -and `plugins` options, along with details of how to define arbitrary -additional configuration options (that plugins may require) can be found on -[the configuration page](configuration). - -### Workers - -### Plugins - -### FFI - -## Examples - -### Lots of DOM manipulation - -### Data science-y - -### Graphical - -### Blocking with workers - -### Calling an API diff --git a/docs/user-guide/interpreters.md b/docs/user-guide/interpreters.md deleted file mode 100644 index bbc42d0..0000000 --- a/docs/user-guide/interpreters.md +++ /dev/null @@ -1 +0,0 @@ -# Python Interpreters diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md deleted file mode 100644 index dd95e28..0000000 --- a/docs/user-guide/plugins.md +++ /dev/null @@ -1,2 +0,0 @@ -# PyScript Plugins - diff --git a/docs/user-guide/workers.md b/docs/user-guide/workers.md deleted file mode 100644 index 1df2378..0000000 --- a/docs/user-guide/workers.md +++ /dev/null @@ -1 +0,0 @@ -# Web Workers From 0430a25bfe9644696daa598ee04a3b89c05fb667 Mon Sep 17 00:00:00 2001 From: Nicholas Tollervey Date: Thu, 21 Sep 2023 17:32:16 +0100 Subject: [PATCH 002/201] Update docs/user-guide.md Co-authored-by: Antonio Cuni --- docs/user-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user-guide.md b/docs/user-guide.md index ddd7c0a..756ff19 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -49,7 +49,7 @@ planet. If [the web](https://en.wikipedia.org/wiki/World_Wide_Web) and Python had a baby, you'd get PyScript. PyScript works because modern browsers support -[web assembly](https://webassembly.org/) (abbreviated to WASM) - an +[WebAssembly](https://webassembly.org/) (abbreviated to WASM) - an [instruction set](https://en.wikipedia.org/wiki/Instruction_set_architecture) for a [virtual machine](https://en.wikipedia.org/wiki/Virtual_machine) with an open specification and near native performance. PyScript takes From 6ad164ce33fdabe2d3f00dd4c24a3260e53f15f9 Mon Sep 17 00:00:00 2001 From: Nicholas Tollervey Date: Thu, 21 Sep 2023 17:33:49 +0100 Subject: [PATCH 003/201] Update docs/user-guide.md Co-authored-by: Antonio Cuni --- docs/user-guide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/user-guide.md b/docs/user-guide.md index 756ff19..753d835 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -93,8 +93,8 @@ the planet who use computers.

PyScript brings you two Python interpreters:

  1. Pyodide - the original standard - CPython interpreter you know and love, but compiled to web - assembly.
  2. + CPython interpreter you know and love, but compiled to WebAssembly. +
  3. MicroPython - a lean and efficient reimplementation of Python3 that includes a comprehensive subset of the standard library, compiled to web assembly.
  4. From d23166c1f31efac4075914b950707a7da12aab88 Mon Sep 17 00:00:00 2001 From: Nicholas Tollervey Date: Thu, 21 Sep 2023 17:34:04 +0100 Subject: [PATCH 004/201] Update docs/user-guide.md Co-authored-by: Antonio Cuni --- docs/user-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user-guide.md b/docs/user-guide.md index 753d835..b9f3cb2 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -97,7 +97,7 @@ the planet who use computers.
  5. MicroPython - a lean and efficient reimplementation of Python3 that includes a comprehensive - subset of the standard library, compiled to web assembly.
  6. + subset of the standard library, compiled to WebAssembly.

Warning

From ef028fd28325d9842770c057b36b4fe75a00f2da Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Thu, 21 Sep 2023 17:48:20 +0100 Subject: [PATCH 005/201] Corrections. --- docs/user-guide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/user-guide.md b/docs/user-guide.md index b9f3cb2..cc8e0b8 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -658,8 +658,8 @@ such as the browser's built-in [web APIs](https://developer.mozilla.org/en-US/docs/Web/API). This is available via the `pyscript.window` module which is a proxy for -JavaScript's `globalThis` object, or `pyscript.document` which is a proxy for -the `document` object in JavaScript: +the main thread's `globalThis` object, or `pyscript.document` which is a proxy +for the `document` object in JavaScript: ```Python title="Accessing the window and document objects in Python" from pyscript import window, document From ccb852fab397d3c018772d757485887c42f38ea4 Mon Sep 17 00:00:00 2001 From: Ted Patrick Date: Thu, 21 Sep 2023 12:53:12 -0500 Subject: [PATCH 006/201] Deploy docs --- .github/workflows/publish_docs.yml | 27 +++++++++++++++++++++++++++ .github/workflows/update_docs.yml | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/publish_docs.yml diff --git a/.github/workflows/publish_docs.yml b/.github/workflows/publish_docs.yml new file mode 100644 index 0000000..d61b366 --- /dev/null +++ b/.github/workflows/publish_docs.yml @@ -0,0 +1,27 @@ +name: "Update Docs" + +on: + workflow_dispatch: + +jobs: + publish-docs: + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: gh-pages + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-region: ${{ secrets.AWS_REGION }} + role-to-assume: ${{ secrets.AWS_OIDC_RUNNER_ROLE }} + + - name: Copy to docs + run: > + aws s3 rm --recursive s3://docs.pyscript.net/ + aws s3 sync . s3://docs.pyscript.net/ diff --git a/.github/workflows/update_docs.yml b/.github/workflows/update_docs.yml index b6a3c98..90bc44f 100644 --- a/.github/workflows/update_docs.yml +++ b/.github/workflows/update_docs.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup uses: conda-incubator/setup-miniconda@v2 From b4d663a66a41cede46762d46377a335a3b3be3d0 Mon Sep 17 00:00:00 2001 From: Ted Patrick Date: Thu, 21 Sep 2023 12:55:16 -0500 Subject: [PATCH 007/201] naming --- .github/workflows/publish_docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish_docs.yml b/.github/workflows/publish_docs.yml index d61b366..c73f7ab 100644 --- a/.github/workflows/publish_docs.yml +++ b/.github/workflows/publish_docs.yml @@ -1,4 +1,4 @@ -name: "Update Docs" +name: "Publish Docs" on: workflow_dispatch: From f324f0a92c912f8e80f3901399b8540f99212719 Mon Sep 17 00:00:00 2001 From: Ted Patrick Date: Thu, 21 Sep 2023 13:18:27 -0500 Subject: [PATCH 008/201] Fix for Publish docs --- .github/workflows/publish_docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish_docs.yml b/.github/workflows/publish_docs.yml index c73f7ab..6437ee2 100644 --- a/.github/workflows/publish_docs.yml +++ b/.github/workflows/publish_docs.yml @@ -22,6 +22,6 @@ jobs: role-to-assume: ${{ secrets.AWS_OIDC_RUNNER_ROLE }} - name: Copy to docs - run: > + run: | aws s3 rm --recursive s3://docs.pyscript.net/ aws s3 sync . s3://docs.pyscript.net/ From d69fd4c525dcef0b14bc0674eca60c7e0a0d6784 Mon Sep 17 00:00:00 2001 From: Ted Patrick Date: Thu, 21 Sep 2023 13:31:06 -0500 Subject: [PATCH 009/201] CDN to pyscript.net snapshot --- docs/beginning-pyscript.md | 4 ++-- docs/user-guide.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/beginning-pyscript.md b/docs/beginning-pyscript.md index bbde6e5..1040517 100644 --- a/docs/beginning-pyscript.md +++ b/docs/beginning-pyscript.md @@ -104,7 +104,7 @@ module in the document's `` tag: Codestin Search App - + @@ -154,7 +154,7 @@ In the end, our HTML should look like this: Codestin Search App - +

Arrr

diff --git a/docs/user-guide.md b/docs/user-guide.md index cc8e0b8..7d5379c 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -184,9 +184,9 @@ attribute references a CDN url for `pyscript.core`, to your HTML document's - + - + @@ -289,7 +289,7 @@ core capabilities. Setting aside PyScript for a moment, to use - + - - + + - + @@ -197,10 +191,10 @@ attribute references a CDN url for `pyscript.core`, to your HTML document's There are two ways to tell PyScript how to find your code. * With a standard HTML ` ``` -...and here's the `` tag with inline Python code. +...and here's a `` tag with inline Python code. -```html title="Using the py-script tag with inline code" +```html title="Using a py-script tag with inline code" import sys from pyscript import display @@ -228,12 +222,7 @@ display(sys.version) ``` -The browser's tab displaying the website running PyScript is an isolated -computing sandbox. Define the Python environment in which your code will -run with [configuration options](#configuration) (discussed later in this -document). - -The ` + ``` - Notice how different interpreters can be used in different contexts. + Notice how different interpreters can be used with different + configurations. ## Architecture -There are two important aspects of PyScript's architecture: +PyScript's architecture has two core concepts: 1. A small, efficient and powerful kernel called [PolyScript](https://github.com/pyscript/polyscript) is the foundation upon which PyScript and plugins are built. 2. The PyScript [stack](https://en.wikipedia.org/wiki/Solution_stack) inside - the browser is easy to understand. + the browser is simple and clearly defined. ### PolyScript @@ -358,8 +370,8 @@ application relate to each other: !!! failure - Python solely running in the browser is an unfamiliar concept that some - fail to remember. + PyScript is simply Python running in the browser. It is an unfamiliar + concept that some fail to remember. * PyScript isn't running on a server hosted in the cloud. * PyScript doesn't use the version of Python running natively on the user's @@ -395,9 +407,9 @@ Here's how PyScript unfolds through time: the HTML is fully parsed. * The PyScript module does broadly six things: 1. Discover Python code referenced in the page. - 2. Evaluate any [configuration](#configuration) on the page (either via a - single `` tag or the `config` attribute of a ` ``` -Of course, code running in the worker needs to be able to access the web page -running in the main thread. This is achieved via some builtin helper utilities -described in the next section. +Code running in the worker needs to be able to access the web page running in +the main thread. This is achieved via builtin helper utilities described in the +next section. !!! note - The worker related functionality in PyScript is, for the sake of ease of - use, a simpler presentation of more sophisticated and powerful behaviour + For ease of use, the worker related functionality in PyScript is + a simpler presentation of more sophisticated and powerful behaviour available via PolyScript. - Please [consult the XWorker](https://pyscript.github.io/polyscript/#xworker) + **If you are a confident advanced user**, please + [consult the XWorker](https://pyscript.github.io/polyscript/#xworker) related documentation from the PolyScript project for how to make use of these features. ## Builtin helpers -PyScript makes available various convenience objects and functions inside +PyScript makes available convenience objects and functions inside Python. This is done via the `pyscript` module: ```python title="Accessing the document object via the pyscript module" @@ -921,7 +1009,8 @@ This object is a proxy for the web page's Please note that in workers, this is still the main window, not the worker's own global context. A worker's global context is reachable instead - via `import js` (the `js` object being a proxy for `globalThis`). + via `import js` (the `js` object being a proxy for the worker's + `globalThis`). #### `pyscript.document` @@ -941,7 +1030,7 @@ The `display` function takes a list of `*values` as its first argument, and has two optional named arguments: * `target=None` - the DOM element into which the content should be placed. -* `append=False` - a flag to indicate if the output is going to be appended to +* `append=True` - a flag to indicate if the output is going to be appended to the `target`. There are some caveats: @@ -949,12 +1038,50 @@ There are some caveats: * When used in the main thread, the `display` function automatically uses the current ` + From c07ddf4113c82716b6fc2c48ada8a8fe1069b218 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Wed, 1 Nov 2023 10:44:07 +0000 Subject: [PATCH 035/201] Use piratical app running RC3. --- docs/beginning-pyscript.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/beginning-pyscript.md b/docs/beginning-pyscript.md index 5e1b585..0a4f28a 100644 --- a/docs/beginning-pyscript.md +++ b/docs/beginning-pyscript.md @@ -70,7 +70,7 @@ level. You can see this application embedded into the page below: - + Let's explore each of the three files that make this app work. @@ -226,7 +226,7 @@ and click the "run" button. Assuming you've copied the code properly, you should have a fine old time using "Polyglot 🦜" to translate English to Pirate-ish. -Alternatively, [click here to see a working example of this app](https://ntoll.pyscriptapps.com/piratical/latest/). +Alternatively, [click here to see a working example of this app](https://ntoll.pyscriptapps.com/piratical/v2). Notice that the bottom right hand corner contains a link to view the code on [pyscript.com](https://pyscript.com). Why not explore the code, copy it to your own account and change it to your satisfaction. From 64cf8ef3af95f2ac4088792ac109e351a99e0f84 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Wed, 1 Nov 2023 18:04:58 +0000 Subject: [PATCH 036/201] Add terminal section, minor edits, and split user guide into separate pages. --- docs/assets/images/py-terminal.gif | Bin 0 -> 139521 bytes docs/assets/images/pyterm1.png | Bin 0 -> 8542 bytes docs/assets/images/pyterm2.gif | Bin 0 -> 66505 bytes docs/user-guide.md | 1147 ---------------------------- docs/user-guide/architecture.md | 251 ++++++ docs/user-guide/builtins.md | 142 ++++ docs/user-guide/configuration.md | 322 ++++++++ docs/user-guide/dom.md | 87 +++ docs/user-guide/examples.md | 3 + docs/user-guide/features.md | 87 +++ docs/user-guide/first-steps.md | 141 ++++ docs/user-guide/index.md | 41 + docs/user-guide/plugins.md | 3 + docs/user-guide/terminal.md | 54 ++ docs/user-guide/what.md | 32 + docs/user-guide/workers.md | 52 ++ mkdocs.yml | 21 + 17 files changed, 1236 insertions(+), 1147 deletions(-) create mode 100644 docs/assets/images/py-terminal.gif create mode 100644 docs/assets/images/pyterm1.png create mode 100644 docs/assets/images/pyterm2.gif delete mode 100644 docs/user-guide.md create mode 100644 docs/user-guide/architecture.md create mode 100644 docs/user-guide/builtins.md create mode 100644 docs/user-guide/configuration.md create mode 100644 docs/user-guide/dom.md create mode 100644 docs/user-guide/examples.md create mode 100644 docs/user-guide/features.md create mode 100644 docs/user-guide/first-steps.md create mode 100644 docs/user-guide/index.md create mode 100644 docs/user-guide/plugins.md create mode 100644 docs/user-guide/terminal.md create mode 100644 docs/user-guide/what.md create mode 100644 docs/user-guide/workers.md diff --git a/docs/assets/images/py-terminal.gif b/docs/assets/images/py-terminal.gif new file mode 100644 index 0000000000000000000000000000000000000000..8eaf0b51d2ae9c5a2eecbfcf9b54f753273fbef7 GIT binary patch literal 139521 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 literal 0 HcmV?d00001 diff --git a/docs/assets/images/pyterm1.png b/docs/assets/images/pyterm1.png new file mode 100644 index 0000000000000000000000000000000000000000..440797cafa629e0c1cb00bea6ffd239c77078e86 GIT binary patch literal 8542 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∈fqcZw~RyHHDbQ4GNzexYhi> zt`h(d{}4Td9e&GjJr(2U%rj2yx1=$9GhE=WVBjj6UM6TwVv_sl?R*7VxaQiY&DZ~I zmLD5BWW2P=LB@2LrkghL0|?5kE@vMMl>rn*cHzBneL0~4zWuZuD1Z3>$q^=CvaE;CDKnq7y_?7_JEk zou{d}0QeSQ2~RUq^;?UFU_?MKzMs-6Fk=lM>_D9w;JF*v=7yvjl zSBnikJlq4=&++wIfo&~!EhJ3K1|!U2r3*=M^wdX#!p)jPH(|sC$B~e7idI6#4Oq?z z`vnNs5Dq%=R*s!NzD|DC8>zt(sNWju=I>M?uuR^sFN-bWFzh7oWixbJ)l$E!G{YxX z{gGg{P6+JqPmfChy(Zef=@2ll&`f`)SID$U#XL(hqs}oc?VjyQf&fS zuv6(EwY*>P>Xoltw^RQ1lpc-%PYSu@5nbR_Aotq%^-&j%0>QjC(2y;6*BCG~38HhF zbW9C&JYc`~fB_@^qW?5K%!#Hor*u*E>*xO`f>vmd^ra(jUGJ){oF?X;LG;-`Z2EX73F<3FU8G9k*t!Ly6Z@SznKn%{ zoOHk_`bp6W8Uin0J`KD4#w3->^!v@%E*y&0=Xn@2)7}m!y&6K!STafqs0Rvsj~DnA z05QflgIX2yiATtZ{c+)+A5NcMHcmS+k(K%;Z3|XzWy7q!ycXV#h?(bk%&dw}H6i-n zxPA9?s!}<7G`!Y^;VQ4&6a=qLq9G^@#|d@*F=r^dT5d9MHxLu6Sy~b38NYU|VAWX; z0)V;G=$rn~s5x*0ecfd+TG6x`^FLCPlr8?qcY@P^M4q1wJvgxtsZX<-H>foEW;7fR zHZhhjj4()J8+YAEk_tE@kJjdVP2GMeco|}sWA?3EzCelGnaxiX8M}D)`}8UP64!YO zot{4A>GtX_gP1mI5B$%IeSg5H--qo2@)^-Ib%`=?lxNl$a+24$Mis2FN}*wcUE3Sn zi=mmd3bbT5rA9qbM88?pm^W!RqY(1wqhGqbZ#HkcQKc%}hT+q<(bm|WC>L^hq zgMq(aeeQr3b*I;Gd7e4G=C1M!y}$nP2>~RqeG+F9p@$ELIxKhTbTV~~*Bv|fRD<|$ zzV~uuGEK{d?>kOEwYjt=0(Qlz%=DF^Z4PsNpa@_w+*Lo{zRUS#tb@0#Cpm``~+AV2n)@c+Fpor#ureT2P4scR80av@-w# z?~@03>uy>X!_OK%i=w$fdYjwY#eV&&~}49%*k@z{FcD?KfL zf2nwj@?^Jgs%#LGa^QsaF?b2&nyECK=d=giwuxqHH>@pE^BP)8KqfQI3Ndh!w{yvb zCcjglgaZP!j$b=ez6NK6&F6lown8$%kg3P^v7gxht2;ir0g~92k&4+M!V}gU-vO6dUi(v2gf?Z(qG^~P$0~%Dy4u6M8<4OW~Np6z% zvE8?^d83)8wuMu$bhR3edoVx^$#i?Dx>e(ta;>s_KFlki;QiK8a@ERMV1?}Bc5+;f z_2D=$fXgbFuqKd*CG+0~L-0bRpWUSezO|Al=iX&)hq>QU*Jq&kMN4|&Xf`r?I`CSkQP-{n(q zJXNK-8eEn{?!WJXAtQvk#)?MIgmbRIO4^q#4w|QbSl>A9nRrv8M_oDxJ8YeC#NK1Q zdl7TRpB~bN>fGWPowAMB{KZIh67ipF_GjB3-gdk=9CydLd+y;KR|Wo26cTzrjnr@w z_nTNgbbQcAiL(Q*eGlgE!}a5FBrWd#2FU)bt~x90Yqx17RCZ850|RO8 zEKx!BFXp-Fj-k=ykFxxoiM(!yU)AUPHqOhxwr^^kx!7{;lT+^1OvVY<)^#>TPTwICu~CEo{1qAVEAtHmh%zGvGg7n6Q|&{)e?s7)3YwDxBD6E3qzasE`kZ;X|Htn z!h>Uix1~5744`uh0X4bQTb8B!un~@^H*0B%a1Tu;{|#B)UW!m6^umJ`N4z+}IU(yd zor(ii^hGc=Jt)^ojl8$2r0dS2hMI{@G2)%c!gEItKwmk%?jvbJ2s z!i~-+?)jyhvXa)u7oO_#@>A~Imwe13(=}t)>)yIZKjr%~$JJTk0i^mOkEJ8;S9HBG ze8`%vNt?cvt-bfvBSeN#N`Xh^z?#hMg@U23(EXS7mNH6oXTXsMm@^Th@)XVugRx`z z_mR-2z3&s&41ayFYW@GdJ>B-|fB%sW)vVIU9&ht_yHdFNUdT+7JZ6mn0Uy&Uh5gkS zAw}JAK1+0nEjfP&Hl@xi$!MTdPYa-&I*S2@lZ@;Wv7sTSuKhk`^Ur%Dy~M|^!amgQ zS@I1h_qE;YXc@_1BEmI+1>)u;B7F#lrjdY9N`K+ga=_Nl%flIbmx+E_?o@{c&gDe$ z)Vi3)B|N*UDwB>3q?;Uz|b7Nv={ zb@&d?_brKk;p4fG#v|o`d#rZxbpKlUxg~T^C+VLtJcRue&WLFUm#w44+8iE^gC(o_ z9O_u6rHR7`908HvCa|3B7z~)bsGZcr4*nFW-UwTCAS|?FopoL__C2zaGk?;uvMns| zXLFUs!UOTxKE<6sv_Qeg9ivSGBEY3pC61`}wak_oJ`{w9xPMvOBW$sW=rB-sL%1>1 z5qf`Jx|M7zg+Jm5NoStIHcm7no|GJzzLybRje!E)+N$?+3mtObL=?L450r@4TB>nQ zrVN6@u*g_%+>Nmlo6Hg!|%M;3cTdU;hkus|mEU;;- zW7v?)LVBU$#=fl=_q|B1&RF{Sy~U?Nd+*8}v#Xm;*PM-6bLQtX95n`L+mwV?{Mh%X zY16ms=q`}+CqOD4&bA9q3UjdIqHN;XrJJLh*PBel>#n#gc$0Y6wVMlKX>18xU!{F} zhF4<@IQsrU8J;I7(m>inQtC&RvGh>jw+LS>_e;JZdA5u|n+irrlP(KO2uoEHSC2+KuS z*NTMOcb2D(EV(15X^2m;_pLfXAud|lb>*(JdYAC?mw)OM`FJC;mWy^}kpjJ4- zEnBX!{F26B+kQGMDQ`RUQ*IkoHn?&L4GBXO$={yv0q^}Ixahv;q@6F=mr_;q?+0m$(;!heTc2TMmlwwBcJZA@IzO{#n!5i3)VJR>iZ7NR@y)va^Q%Em&c3wh zbO~UruoBd0xBFZx&`r%cV_UM z2pP!e^7$+8Z+qr?W&~A#hWVVZNpwkNYMHqWA#-?|o=s0kxSSBr9DuJE{&opFF&@0V zYYLe=W3B!3<51Yolv8~ZDDv7FltVEv=MWFqIWza;{+pdZv))l9Y)IjgKo-`$Qxm=< zyl@t$DxEaRr$|w6>%0$H&B4t4?Z68Eu-tr zH{%(=Rh$&r2APGX`9bi+f)wOJT09t#wOgHBwmxg(UNM)c!osKXbatZfn=sXsR^l^%2e1Mm0?-)#!)#o z68Js)8gPNI9gxvhdhWAR;37b5Qs~aIwc^t)S?T`~7?wXCSUv|y$b3GYkNv*g5!W&EsN70lk2KLQz7I4N`Yr8EhSsKFxIG0s>+-L6IIwx0MV3(qg-6P z;O=-Oe;WqE&dG@^g?XNiQ4!tJTY*#q!3CRpvcX2S(L=gHUK}CD!)uQKOgw1X z)U5mSqW*WDUNX<%r3&Lt!^)Zs+TP|&%Zcm_Ha!w;8EEE|t~E6_#=VwcJKI!-k$8NeUl5Tc$614)3+XgBbx<~ z2`afxBd7-bod4|z2k6ASNyCEe{=Is&ekyDN z*U3w_JVAHBs<6eA2Dep6oE$ey#+Ovl{m9iZfWDG$&X^>Alj}`@rV{C!n-__t@#at6 zRy9BxN~!bTD14=(-7#Q8;}?53lxB&_eRM{Ni#Gxzp-?@Vkb9-d{P+Z(bmjJ&G@z^ zc|g#$!ByM;u?RtcoJp+qyay%S;%#%&r{>x@h50p7AfIOXiD$9@Y_0KG%WU4A(`P}o zgu(+5G&ilWbn~BNlf*n7C1^R$1}h-qTZI8T)`3eiZIWZ1(oL7<=;j&e8YecO|0bD_ zfpzik)_zZ?7j1JyKuCvllj&x2ZnM@_x!m(YdFB>u(4^T^v$?QY_XKGXS_xoiT3egV zrWWe7v-=#-a(ccx=TV|NH@QEs`e+@ zfO4<}L&KNFSzO~8;X!PwJY72j@Pr68WDDV>PNqtK^&MOy-F#GGs8S`rXSgF&*bI8w z^=7?7X+_UwjJqO-slWYHYoLx@%YW1K?9GE@mA0_i zeB`la8kF$DHe#n!aqJMMr(o22fJX zCLXbox6Sg-X3!a4ve1xOUU$tSFYvp?P#wA_-C}4m$(e4Vn_$o-CsQsqNR$K_0#L-AjeF961q4IPFFUqQ>$ zs=gi;;0LXL%u93RWtntF4(z}NPnyk5noW0k?4)RR)>^VWP>mWUaT_g1cfn3osFGKAWdwr_d>DHlG96XM#x-`2x-vU_iu zA2_>~{n#Q@fqbbA^sx)x?b?inAsWN9g5)}N>1jpklRsI9&j9>rIyL07BV>I)?%nXQ z%*SBXn!2nVYv4Q6El$^&3*|^0NoPQ@wrUdbJuddWZ2!l_{k=jkzAAsg82BA(s$xaO zU9m~q6uDDNLz53?xJRinaBoj|)qIpZ5t)(&F1R8IHtF$0^dlSJDBM%Yqm2ju(Ezgd z?eR-;>_QyUR>G16;7{X#c$2!nTMjWd+hiP;M41GXaqF(?MH$W=+Bj9yYg6ZzRJ;BM zNvhQl*lp9r*wb}Fva~}ChE6pYBpp~+RDZUmA?fhpi-#kJvP~ZXj;yDfU#>cQFv-ED z=$(VA;j`@MiyucPyMwy;r9YgHeK>ir{@dBYez&>qi9Jq z6gNNhZMHp`q{tO*{ZV2l2N?TWrU7E76mQgX^8djQek~!-qPmn)du3dx->Eglr;>X1 z1VI{8Qd84O&2~1b*ko_MG<=Ap>B1vAP3}$hYgLDH%X?a{{H?K1+Nu9pGn;*)>gU;J zzjMF3F*17M7rNyL33@8pPg898+HAg`Oo)-6J=N28_h;LK;ua$|LY!W(+g4ZT`uCgS z3-6Q9A=p58k!We}%<3m+Y*B1r=ZyPwL)(X*cFkYyI?tblM~)Q_eb@bUk?h}LySu}_ zx5N2YhnxQ;uick?doKn4x=He^=J-uH4?P zEx)?9`(N3y`$|#ol|8?%@cd<^yJh9QGWBQppnrGm?(W0A-A8|QukSr^#foWT&2-9g z{NslRmT&29>8;r;BJPgriRz@V9skUqezaT}?#ncm12hQc5-z>?9LQOWw2E%oE56@p zqfGT>8mho9r}{@>J=Rc|2^V%os$#(6tkw zn-?Xw`ftJ%ERp>1 zBiZ5_@Lh}XWm=)fY8t8{-l}c7b+qq>4@4-TTd=+xYbg+hCYQ2~j%{y>$~7J+_{_H5MjOBndW}f+Iya z(E4=>0dd8Me%Bhq(~wzNt!857o`IticgD6K69~vqSXehN( z0EI)BmD&}&6}Q;hQ|SbkY|Wa<=kH~eKVP6K_FCe2DLo(cViaUmAk1b15JWbbn0odo zm$EoX6sibg%@!3}&f^=GHyLSOqoq6`+kfjlp2F7!-cA04=oQG#?JV3QGWz=HI4ZDc zo~={7L$4Ar83Qd_<${Q7IIF+DIIb`6+~Vjom~1u68ddy=Pdno+H^P7$uMd2C1Afms z{{8(TXh=)c*^20xw0POPMt>gc%ILVw{+^uy@Kt7jGOj`&z?lY!Db31KyqRA~1B+H$ z_@VMC$zbdHW*)&L=xkZ2I_Ifv2w~jP8H2S>DLo}i*n&3@=@mk^GHITUiaVVt11KOI zuHN!w8n}st@33&OqQ$p6KHZ12kR)HN@H(Gx9zUb%nas%k|H?c8@`}7Mb{W9w>s+}| zR~0fjf6@NPSNbxR>)vclseOG#4b>pv^{zY=v7$PUkZlHx1{AD59j>?Wv)l8#jwXPY zL!DE388W}-P=+#?32q;|>lhDTOWheti_iLCcpwrqF}nL|e&{BrY4XZ_yF|y%9@*94|7oIUSJ)s?Z#ca2>%s?1=L4P! zbpV$7>|H9-{e|yioxMxuVm9Br{NOE3dtt(oA-lBo6e$WRmEZNN9_5$^u@=8WX(c~O z4cPqL@4BFDUQYv^k|`GHT%p$u1w6t$V7g5Wl`0Ai{)8tJHvH&f<(@g!^~~UXOMj?l zqfnqluo#v-E;ZRYJ}LSH9%ga+n-?W;qs9C|4ckNmT9waR*-6d7{3N!){zj)JBVr8LVbl)` z{rd?n)OlW>n*6C=rrNe)m4%0KM|8l)`Dzi~wn?8>y}c!7!*Qq^8xa3 z_uT-70Bbv(@=sgmvx@Tl=SboWm%58pAgR#T*!<2H_W!Z>-ce1x zYufNmPe=%%cL=?R5IWKfy<_O8prNQBh%_YvVj2*7K-7qUp@^WMK~O+YLlHqy!HR+y z1QoFXih_+d{?3`1^R1b4zB#kboLTdI@85f6W$k_4&)uH;zAozrD5_XBj~U6NoeRx$ z5UxZ3*C=?A_@O%GzDB6&B`$c|`q8LVD_7eKGAOlr;p(PbSX;I9di{N~z-F$yUE<@C z>F{ERON2W}f(P}^)KHlxxwucgrpj1Bg2&i2L?5xB`N}j*`5jWyOkBhu@P*>*Mkm-j z9+R>*;)v8ChJy@o@WEk-VhxdwzTC+-h-RtQ2>C`na0~a3JE9GRtLWHKn#@(6ym6(P z_YVX=RCqNc-U!xmoMvkG)GBw-8LcWaZ3mhm)V^D}7F4Ri{5}D8DsB*8$nT~5-AU%$ zS9)#xnyy2tmGYO1lE2FtG{3YM?%n7-^mMGy^Rob!Gf6cHGcC!2`XziM_E%fwKz29R zsVuYZl}jWKXd1TWZ8E5ZO8AL5Wb$!O`f{|m_%eFz?&{am51wry<|Y)rKxAF3q*L88dqf(EYvv9{7oi)<8lZL(zkMS!q87Hn~4YTjH zf2J4gG>F0_$_-eKCNcMBpM|y0<>-GQA>5puRE6@#7X-^3*pE-#(im3@{hHhyd$U?0 z9Tt8?4Jk1M$fci9*acmH9_Z z*iq^YtE(h%jY6QZi`{O2Ws$LCb^yGblB?1n5YFsVQTcc`wfNCq&@3LEiBwR#x0t^n zP+jH3_})%Z)9%1FqPbp<4&gYjyp*$>0Vcw=jKz0k$Vnb?6<*8 z!%dMPqV^Qkk0f$YZ0at|bR$e)k)p)TFR$0Ob4PChVf{uxSo)eETR7}1^3j_N=ne@- ze?bV7_Bz=N+<@ioU>Zt^D=GkTH0F7^{_h|P?!<71d?81CD7~f?r)#wHtDKB24HIXT z`$0R1DjwD=GLCae%zew0Y~^g}w9)>3(5u zw1Glb(``c~a2(sdk290dnxKAA4QLN9S1XLr#Q5BVdF;#r%XsHRG{1m(I#!2t5mzW9~VIb!&DI>*L>0TnNP(r_Myiah!CYCUr#^@=(33vnpn2 zv3=YK|1r@w?q~h(?Y%S$$PV>M8%&E@g{_EQU;kpw(U8qbo$RYE7F@R{O@qE#@j+g^ zK7A&Q8AOeeNJ-RH6ue{WP#sm~`Ga`3q?zhuVvpiyxM`)%2bB)!o|tAbWyOXV}r z@t>uOX~R3c8MyeJLPl9CsN>7#b5xnsBQ{IXCe8Ce81Gs=Og$vx>D2y?0t-jIPxX3dS#AKu#b_0c<21G%=vW(*tt>FHxW9FVM! zKs&Whh>wpBUNk1t4sCG|e>KEVV8+1-)R%Zf3?O-KG~0_3kPGnJ8#cU;C3PcU<$PB& zN-M^J-FxaC)sZxpmpVT#skY0wde79_%iMshw|;l{h2pv-f{N{otkNtI_yLqynr48) z65$&0qqD`%0??tv95Ht;C^GehH@qg;Dq1MqB3%8xvjQnYODOH}29=1i7`A;Ru)@`K zgjGZ2!xmqfh?Mi&up1g;6XMw@3Lx3hXqB3@P-G`0b`s2eOl^Ku?A9#IpAYbn-hQI` z5BLERx;e&?)}T%M_)^cu9d@hiEj%k+BP{>;4V0KzWYbCBBg@Oy`5cDZUOFT5j?X|? zEl|~P4%Ki_2}MEzSocl?=j@RO-QrNfY*~+-U4Sbz>jN7roe=oMl2X#l_H0`Lq{Hg^ z1xBK10v>#=b^o5P`;#o!((+P7Zc(9HBqd2Q?4dxUJwORX01qXiS9mB*K1h5N>`w%# zEkP%FsA4}QAvxR)B4pVTFrbRI5+JE=`|pm5CezeQYB4|kcHEdo=a9kAcj634qD71H z01h!ph5B4dtFcT!wF_)8h-=@K(Rn(f=XFNojQqw?(SATIfv4k1g}B|25Eq!9<$=)z z=zAiZw;wlkT30CNm|^UJq@|y^kq!vbc{&;D?sV-?oNgn1`Lsk3pcTjm$?*==6Va9g zl^bK|hD1n48Q??4rr^Lvk{|;T<}w*7O(H0Bot?Q6Fh6PnA}!f1Ems0VdZ4l^o!mn-^I0M#OcWT-F=KB)gIP9{e5N+Q${2mA}Cp7@2YuBW+} zEdna;FeqzObT4i%zyoY(=mos@_gt7NZhOU0UUevryCPcK8L?hGmrKY^I}8z!v3m(B zi>HM=ZJOros>yggWruC!3nC`7dT0WeOU00gPBJW-!VpabNgrw~9B~)}(T4c&4-l}LaDR|1$z!98 zxn|eZj9;@6Ish2P7INA$8ruMbU=4QrWv*%$XoGv%(hG0lDleoQcYFnNE)lZ$usD^M z3}57wqQHlbAKLx+_({EhT91l`H`~P*#77A*eSs_*2ig>?CW-^A6LxcyQyVs>rUYXY!Is07m39?natuk^tP&x&Ke(ZMSyf#1oa!&TvNdr$_hZ57V&|Xen6dE+6*dq z+E_Awvdpt7_y`V_2oiGqX~yd5HsPAb%8a^*L%FBZzX6%^r*G{)993Z_N7#LgFA^wI zzE~mcv^niJbsXF5MKWT5FI9XR^oWa09IjC$Vh#~-+eo5`iOIS;VG(T6vNmb^Gfm=r zWD8G8W&tSRp?C6lm~~s~uOHKSq4CXF6yy~HjpJPv(GfC$Qbvye3!viH-iPqKdfi4o zS4T7M0wPHX_Et4W549*I-^H!J^afkYvi;s)cWo8k;+`+VMs07+a(bbHA}d^;cMaLP zR<)=PQ27`mGU$HmewoDTcd?==TyRqit_+6F3@+8{9KZ!rF;H`5U?=uG8O0#O9r46~G*BlSwf7dUZwG3eU{^`gHJWIN zOvKs)=VXRdyEPi4JbRQ|8}&$FFb^4q0HpblV~RjIUfMCChc3*Ek_pYfo}N|q>qt`+PhDt9V-?1nUAweX5q{6>$|D=l zlkVJ?-=M8HgD+&Zkc{upF5JXZ@pbb22T?skURpQLGAunrzD4aQB%(D9&g)?m9Mu&P z=YU|osJDgD01mOc?wa*b+sj+X*bL=+X0}ODVqf?^cP`3&a__T@Z8cl~WT@h%pZb$i z#FmL-w_g|%%`dRk5p?vKW?sMkEiIe*cA6)Chy$l99s^52dMd6n8~VX-8~v8n3;f{E zSFU^zlxUJJW%g}EmR|9S+mXj(Wr_xt7~tr==p~H| z#D(a)Ud_pJX8~YP(i0EC50{5|CZ!DDz~upaK(4X?biwig1BfOfPw~<7II+f2h(nF) z5FYDmU`fgp62;!GR6Cts)|<)|T}QPNd5UJ@JGZsg5X7(C-+G18&3_sv(lkn`&A6z^ zb=*3FY%IVDsY7oV+?g%x!irz}!W#PJeXVY#G}M;8X%QnSA+FpUQ;Zp2uH^47y_>ND zD#u|j;gN~FoyA;iC24HekE__4UPBKpF!#>8AH74MyLtk>!-PJ`xIW$HK8N=bpVM*r zCTR6hn|IWneJH(ra=+>U&^j%!772DYQONkThSL|nwK-xyvK!ez+!2RB@)p3MRS%VS zTt_VG0^c7L%RXcf9vX^UkLw-Xa7H@lO_6To8JkrQyE_x1W|#?J?AU{A^ACo;JxUS< zux!X9GGb<($Z766anMz3ToK9YKt^-)-37Suf*c|dI6jKLH7R58PVvEkq2&T8>;e!i z4^|uHY*hma2^goRokTy{Z$8mPaL~?+k49nl(Ahr~Hz6XL3zcqK72@hAg=-phQbbUF zCunjdv?*Gu@x@~wnQ_LmXm4CbPmg@XM4kFl-637k1Mf95eopjO6^TxdjP$hVw*qiJ zNQwaJe+KK1%gPQA}lwWurt|wUVnz~l_w5K2ZaukL;H@N;iZs7e1k_SSl zS8rDb)?0nU9Vc(6wNvk$@)_DwbFsGnKC}i;SOEtC}9VGtI%VI$E!5OufW> zTnNvS`nqlC%$|#16~Vi0X14t>q$a)}-#OV$u+f;7y7P2Qb>l2Pe6}L-0maPdDz8np z`7%!YzQA))=8&b_`L)GR-`328wy>=Oe^saXB>2rj|~*$o!b62tt97+*iFI$CLJeoEwRR4LVe)Jyb84rc9>nQ z3QftY8#xMu5V0Cf;LA5ezHmp3amEJmCcU~qNZe}t6YyjFFIWViD1aL_eUVp!%HLC5 z6~h70HLRv^GOL#+X3y`-c7`FaVk)T|=3bEjn3zQ2!lhTvc_PwQWc(20#3^YtM`u}Cl7tB^} zqSer;R*Ur<-I`B)R#Z=PIZii1_Pny1bKsTTgJa2kPtdN#ID{N~P<;c^UU#k3*V0m* zm>8OfM|b)eo=JW^NtFEa=mU1^9+1w`h=lB84Kh|jFJ^L zlvfZn%kI_c$pvH%MS)75TB;zz+mDxSBhU2gk|$5hyLHPPX8R@(dJ$K>29Gr;p|?CT;q?Pt_L`>CdW zQPUxQWYCbhoI3izOrvXA#xRQxp%uQ=sM?PAsFTpU1ri24Jj>## z{484XOfny|vD4#J$p*~oKxIlL(97_pZQZ3D6)ynxuH`%~W5GhdIPAchd|7}hMNW}= zAy|``7x`u*egmTBLxd=V@a~qHm%@AFESA4<*j3romlI3VqEBBewzHph72jHRfbj{D zIHz7<@M!2&ndJka(-qTA)CaFSvwDhc4(*CoI4B^rt@G*YMM&EXvHK+xGN;!sv|D|V zi!SxB*sKHVnxhx*R`95xjPNa4r)mo9t>2tdo8T50&R(~mm?TEPy&=?oytZ-vW=xdA z_pmwFkjwW^eSpe`I;ykBa`onBK^qpF%ta!YYM@+|r6Cvm(5S(#Mkf(#2^J74>~Yqs z<8F5|O?$GqR;rh-#=qiN`pwUXn!=>t>_K zoocaL`QB&S8T56b2_jlZwuMlM54*rsU{UEXZ9K^TU6c%+%23aYz-|~PZ?RPX%U&2o z2REw4I^)Uc?Q;F{)B)`PahQoUm`L`xt zKRi%nVY0+M1HQ33@u$P7*o_A2t!br^-b#Bt2**S3$A&sClvj$<=J}ouN zcQy-NgsYjs01@i-4Hm6%I~-kl373OWI1VyQjM!Fam8)pB3$D%_V7UjXOI9IW^n4q( zK7Sev(|p}xIY~Bw);L+cTk9R+>Jo>4)EH`=MRx-oRgvI|y@Flz*$ z3W|l7;^7;f8W-9&ll`$ny_)4}CHsZCraN(Oh^UIu%vmSZT*6_wd#$7_=RR+rnLeFL z+P$d2NHiYLl9Regs-Jff+j+B5$>Ql)NlvQ&iEj>8U)0bKyFPOvNkmEQX-q~YL$-;*ZZTinQT%%Mbyl;qqR_brxa>h9S_*_Y z(5N93Gm5jDqvcCU2_%+v&m}2-D>i!Pj<1h^ShAHI4x$CZD}eG=>sX?~JwLIWK`GuBA~PNRHi(yhqOAQE9U;;&0O$agja>R=-hj?VNGP3E=1eiVlnM z8d9bCqVXDqrns3fiA)36#tNHw9|Q%IA662kcwqx3qvVCUbQja-Q^mxOost6w?(9_P zo19N74vO!Eux`IeSLvoX|7cepLuM=35}c*mI4W7U5gUVB0{|ZMR$0)EquuXZ>I?%_ ztzQBnji9#&%9URup3Ri#3mactjNV@{V1N_+&LX8!WqZGBkZ+5oU$NWB6ou?vR zfBTe+2NA3k)v#Cf^AuIw0r|)@NhEM`93b!`uz(z^Lt*AygH;VOtAUY%pI!^N?F$9O zu@s`izU8cD2sV+*W=`TQOGFX6B(Qkp>MY!?v+sQc#858{|MeGo_=r0Dq9_;8yxSp? z>|bA~ga_G&RH>3nFOFmQfK&)=T!aAd8;Q_{D_tOaUyx}_cYp*X$If~Yy!GJ;EtoEq z=;*7`WJ(1EzW#bgl1xPqHKE#Un-Uok74q&DR4w#`par`+7D$~})1~!nnA$IrNQL6W zp2nyEKvg19>;C3shXYrElaQYyqE`HvMnn3=j`Uo=lhzOQ$otA^Q(rf!4uRu~KZ(rs z;J3K-ypZ2S1btQpIxQuii}Hc_6yn>)WA1l6uKjqbNL+k7wr1zhvT=Xe%+3k{cgtT=S*%JpFX# zpce>10h+wJFZNSG{EmZOe3UyCP_iv+yWGo0UcHZcGu~+{q=ibooHZeb9k>P=-Dom@ z4K!<$N01Z~@*l|oMH*ZL3%FWGon=@pb#}-+=#VlydnL*NPPvA&a>SNnmDW*_{Hqt& zX#$-@5sq!ecSi!IAKgli1d$*@rz60VCp+Sa0jMC_-6?_YLuUn_L>sC4#hcJ}IV_8xKenH=yrF5&yb znUpEAg$$J)m7@;{sZ^W-2b`oj;pE1mKxbBv5=OX)ZofdZu%&7d5H{3)o7Aqv7-;r} zQ=tZ~QMRtp-mW{sTzAI1?#gs^x22*N>I`wrG$hobleTZGq6&|m+{g^vKsRN&Zkl%8 z3w1Ncx#ghNJF&r~?yf061{0NT(AZQR0>qS}V!HyCskMxarW?#1_hccWI%&?B{&gD6 z$Lel5@$R{q?yN%hyh`_cZ`ZHxi0m^6A-i4X3RsM=4j~63Tj^&Ba(%cr^37OmC67uI zkMdcmJbp`>^WYIpk7LfrjmTWiT5WFn93mA*mx{4_JOeJA9NHpkG@eLc*3Fy8w{ruR^x_i&~6 z&1UagJ>DZD-nS>c@4WNA`@?$_<1?n@bI-u%zOBy#Z=Z)@K9Ayk9%uTD7y9g&oEN#oh3g0|0iH=7fXa#Q}!&B5D zTBChF$3-<7X*&%7xl+240;X;*dn*_8)vOVaV;p4Vcn&e__{hGZdLbBH|60JMt<~zKfDi44pC`XhQU@AXZs-pgHX3NLrAW0O4VYt8j`+$u*yzM6u>qq?oB;eEO536*5 za{zQ_m-QN&CP}qMj~K@RH#28!#o`oJO#$3c=Nr6hVL<*&G_?fj3oKa8);WsXJ-p!+ z^vG1$%kP#7$}0=#Es_U%KV5TIX2A?Lu=t%?4<3xo1x|Js*}ehdc}!_#mM~qR%z@>kZV zG+o$uB_#9q(IXbL-Mxzg#ni_;9lzmX~L4k=j85fU`InurWkw=^>%y^cXnpK-9lHozT_;U;BTYa7f9?rFf8q8(OuL+qh z`OGU%+_QKH{)JY!B5M=FJd2;B()maWk8n%LHR1zeTxeOQahnLC=w&EH88BWDQW)P4 z=%IR!(@e%x?Z;bGGoZm5taW^5AfB!*WPK&%Mo<|E>yb+C%pE}PMUm_kiO2D`fORZ` z19Axag0a-_5C-pQdEb_AW`UVRx->83U{%=7maw)kXPe1>YE?NL4-IAKY^EZ7sSJy` z?EL^kJ|a(hh_0&7tXG2&h#GVxRf`Yb2guvW9gib3xIm@M5ZHJQZbf3GSmh9L%=n>o z;wz!MS=mlP`cn=xfdf1A@PQeX<3?r7-G(O<5c-X@$u7Fp8U^8$$Pm+FC@+Z8dBE}; zx(CHY?#_QMQr9ktVWrs;S} z4h=j3k(D!FUlU*l6-?Y_OrFYl_CB1B1B}_Zb|f0~VwiS9q)v|Kv9oYnobGLxz+?Fj z^^v)IIA94~5TcVBGS?u*qYBl>4VBez2oHQfw!C|1;T+&i%`L!lzpx)iP;%W^VG=Pk zUFrjAGs!9;zwzAAzWXi-0)`^;CMu>ZU~OUB!b6snIY@#m@*FuTylI=<&G_20~CnzpstDqD{%izUd+qE8BQ80 z+xlQ+s_(9SS+0mszz3IW!i{7S0@qov^c!<1+DId=sP8NPO{qr^ylEAFNy7?tE1#+R zlf8?Iu;2_=p|7zyfVvfezzzWLfIs)K$7Z^x9Zhfb-ZbuhyBy;q;W~|sA|m1VxqASQ zZqg56LltS-G3q8U%(Y_Lco}T7JqrM!seH4@RO~|Z5h&5xZea^R^xMm)AD`$8@dpRB z04LSBKqvV0k!~cC>TQ){BHx+t>J0TuHf?8qh5a1!>Jb?pdn`@=OvG!dRO zhsYwF|0DsHkZT;g#Ae6=Qq-EwgqjU85O02bLGXJMipPY~`*-+Q4T^`8a*jO+WF86G z+Is|0O}r*#v?VM65joP0TMxClz>Fe|t#a)bff?7`r{Ik18c0Ye*ongo5%Ri{VfqwM z6=g@&m-DtBW0KtSTUU3lU;QYlvyeebf~e~LB7Xdyy4PqenP8-wH^fYI=UloPcl7OE zxWNC{t6iHXfv^?GrX|nOnQ>UxIaM|iGK$n@<&sD*b{M7CZA@2LrR`?J4itY$H$)2AENGO&nJTR3FyWa7Q2gv@Dwtwk zYk-Gxf?{kfzxwfT`uS8HE<6kO+3_O%pcS+A_9Y}4yvrTd=LtwHAc>WC0VMc(Zs|2Uu{+h};oF^BUZiA>2oDnUtjI9m$#$KQSpM4hMlmTI2F^iQLvaMpiN>5J-j3mB=r-LFvrkv zUukv&whX~tgsuEU=+<#W3>&1o5m4g8sDj|#VwJ=i-usMMkTV1Bb&d&o>`^3d8k5RF zf&e1O=8gSBnudF5x92NNO_w-$fPqZ9j8b%l7i&a(^S@1KHKxOe&m3EtOx=%IQv&o8 z-30_M7q3T?Bs0j%>r9lQrTX~t{E2#nkn<{hnit-Ift03?Q@F$D;!b@Y9cZ{yRB+yb zzN0&Em+z^RcUKby0zRnF^dtPpfoTwfY5X4J*Xpntm3JELgpIQWD8T+P9=s1 zt(WH?osYVE?x4-r4^!6|Vn$iEt4pu$)@?eUW%vEd2gtzK=~vEA&&nn~Jezi2Wna(x4mViu=H#uy?>WC0&%G?h|9`?<2~u7L$Wei*bc_DNJ~n;N2)rCGtM%|Fw0 zkq;9}pcPy9IGZrgdYM{8MB3WtvK^+ypBKO!Y$ngk>dT~4rI5WOxyf$O-2#N^o@@0y zyya+_Gv=fZ#X+IDy>5qYKxUVM8%K__$$rO|T_rZ#2Y97b8b>LS`Rkru7RNm6tOdhw zbjh}~-}m3za`AEGiIz(f$rCLd&*_REQqY9}M$dBez>yPoS`=xQ_XKAvl_|C;hF=*E zlJ12_c5VfwVr*s4w|~9)HsQpCkKlX?&_D4p8M9r7&^@d?%GZ4CE#BOzm@?UVLzSU) zVMya}*o9#YqXnwmWKYfFuu=cWdywI;2*xernaZ|1HlHTj?rwxAx2MZ;%JPwp8ddG7 z2%N-ij5L|s{vaSA{NlrqwWuoddoVLz-`EyLOUm_iBw*k8uDYsAPvhF2U7Fb2uiP=2 zazDJ|S=vlh$5h6rXC2QEK~y@0@*mqer*k!`J6{x-{$AL3Qt6sK9I&nH<*}&hu2&~g zrn+9AWT;%8t2?~y@|)9j)tBebwoP4rd%j<#`&~>(Q1|-|FWc@9-JhnqKT_8udlvd7 z*Y1A2p>eWj=~hU1&!;|9)hnOx2W+?Nyt{Gll`j)1&kw%&7R+5pb~oV@S8m%a0C2yQ z+$*1^`c<#}_+)yOCV{fdt(Q=&ygLc8!qE;+ByC@u+r@{d6KE+mPF9f)OxaF;{7@1f zzMqD1ZstO@hLqz74#mz&YYwo?J}fBjG+(lokge~%1*lFeq|}2&ByoZur3C;AM5<0C z_M@zZO3_2T@(a`f%zR3f1a@z>XPCO=3FHNMeXsl^3o0tyWXGBSu#@hH^;fxc$(VXy z#TAGp&lrJJIBo6Dtd^XZ8?@{zwPVmqtnbi}@`;IHQC&VRv{fwJY8pE1aS|YrQ3qlm zq9^=k6pCbTxH+1Xl{FU!xpI*SK)>jA1BYbx0Cao(jD(ufbdVg6s+1Y2e2L{KqVC@R z%Ise0;YzLbaq`1pO#s#~hcK<=57VW&KrDc;$G3uG4ra5xV&EJ7#~8~lI!7;6YMY0WrljAoCSMly|-0xQ`RqEKa$kN0HXbMx~ z3``h%&{`BE^_Jx#fra_Zw&TTT7p^NhC(^gOwv{ed>bk7cx6y=|Vs4HjbaoQy4)$Dj zH5*|%ij&LVz=dQsMyW)TL5sZswK7$DK5+`xLKP$xj+LW`J9*%&Eg71nJEJg4xdU%^ z$S>j2P!{gI*8}$({HyeX)NX+NKhMbet~4eqk!i+ZLW(eF?PL)?bLS95+L1FIpmBNd zOrQC=Wa%(zcN#qRs_BMulWf(@g;OW9P62s17&ed%MydEUq=XwpDWW?L99VazxN47Z z>!y3d@D_`mV}JA6VI!2JNU|mNdRBK>!EsKI{2%z{|Hb$41O@?|ut)%q zI)Iw6KIL(H8AwU}upwSee=bhLv(mk__IiPw>F&v)*18)dI0*QkhRk36IRC|0{hzY1 zfAo9&8)OE6&Tq&B%tLf26fcu@SK2|MjNFcNHlIT>eVE&$auSV`EIh=iA zY@=S@IKmLAet-XEKa&sfsXTr;qJMs4!RC%tE58?KA?qf`%P;1CdD18g7k{U4sxSVT zt3E~opMAzCoVIy2m``N$4c$}n9=RZ*jeB(--t1f`SUKJkY9DA|h>H$8Bdu)(8JgEs z==M$docZEQK~5g-Oq&dN>Bh01{ryW60iN)+%~4-Os*$9|L}Ca0RJI*d`sgx~-MsPh zI_}VsxT*&|I^q&wro%O}$G6`;-n6}5@|B(Mp{9yoKaMOfKHqr!6;H`2S)8_R*bsY~$i$((eRpfEbtw=-t62RO+rc4pwkdfS zYxF{#W)FOmE7SBij1!UaJFf2Hbxbw_i(I}Ezo_{5j>!EN4$@9jg&?%l?T zU!7V{vCtJw`@x?N)oM8Imt&_+!CBev*CI=E#b)Stdo0~7*7nG75IWSkzUnSKV-STQd zTi7b3hg_kFN2s5BqV#fpDw{z5Fd> zZ_6A_A67U#ZCCt!-PuuUSFlZz!Scgnx+Ibs9g+hA zm!Bq0cSO6NG1ds~NRY5e%bU99BsqSks%PIP{r*F4AN>y=`1-o(&!7AsZRLN}{8|5s z#pgfOasTFK{v&TMgHBDXXFyoFs^&Q((>@{y3EhBTsZhMz20d->fpWd1m$xfz4*WVn z0`6bl_vPJU+p)XbuDRiT9dS?FcFNd%#B>?=2Njhxf}31F=LP7vwno#cPgOi>c4&2q zeQKaszH8#L$#8YzTk#emV*R-%9yN|!nrK1{MF2dmg&?vzPtBX&7}ZI6T}fRS9j9Lx zO-?V3%iR-HEw9v9>!Q0L6kQfh+pun`EeBpx{(j+h%T`^tsg5*A$ofpm%=ExP4Y6}d zt4Xgri`)>u!mKB#|8Up+Ps8o60{Ztq;0R4X<<9~CFCtA~46lZG=y$-k8jD~Si0PB5 zKxyp_mdyIpUgL77q|?>wt?j)<3ycJ46MBX z3}?IG`T3 zgKGF+^q$bgHEr+T>i955hvx68ORC*Fat#Jy_vJ=sN7b2h4R%?&F+;B|Hu&jKlL7`g?20U zhu!J`Afnv=TMJ6;FI!Me!rvAZuS)i9Pa%&gZis|rT@_f z|1{IQ^sf*P1N-vq2C=W|KmGKAzlNbPa$KTA zHWGm?Hw~$wr?@d5otGRr7mok>;rYc}scZIEqgD%Et2W$N>9iU6@(?bY0-jecbDrGlxTTW0-5X~YEBoL|#_H0O zfXvP*drN(IK_#9%Mi5u3mx%^y=+Wh1PN&mh`I*i68tS&N)dlfyv?ixsX5j3!MH& z!KH@8k!l=~;&`G`C8bqJ=axsM@0`O$w|f}E~d(}CUSP9OkUQCvLLvx zCv6w?tNs8xMw{e*(6EJ5$_;4rK;Nv~BHj0}(ere5{5OGKXiKD?zS)ZT*@5=8M>6s2 zg5r^q@wXydY?h%@UFmnP`V_DeLR-T{>wM7Eeg={)nf0w)-6b2PL?Dh|ZeL`GhF@l@ zr4&3;G>`5a5%AIA!Ooh3EgYEy;uDoVl))H~G@hlA@qc*Ogs-B0;vlOMhrYxLJic%LsFKi(R0O#*ZF z0e0$u9z!NiwceZ%x6EFpMZ()7U+ zS<*;N_qKk=D*fqL{L|dmU&ZM2ze4e!idX;Ak3;@NKW>Yyfa|0b z@&1K*hI79&ie{{JCm#H+Ld!1QpjYwhOP!nCHEm}WzJ}APAy@A@N1mU+N@{amt3-4; z;<9oCA`8!TGWF8xbF5;M8Rs|Z`{OD-g^Pc3k#CB5N43xQ>JJqH)o%s;;j+d^!%#jV zwB)*jjunN?8s9Ojk!hSht&N}LgzBT77$CUI!hw!x$H;`SVw?HhhYA6S^Uep=_+RA$EK z(XNvp<*e}k3HJpB{Y#0H{+BWT|54&Nv7}60+hcHbuK7yn^dGv$n!Tl(YsZyXWwSSP z_10aDUtQFKRw(RwG16$-Fn}^Wn1Io5-{n_pU!?7#5D**CpjYLZJzuul=j?{or3WHq zXGf0Mbkn8J+>7&QbGjiS`lrbHKW|Te)zJQ~2Y>rLB!u7lUwg=Z)qVVBhbNU6@%VDa z*OkRvk9|2@MPbJnH$2u0Q3<+w#D6BoyNa|}w%kZK+;Cku%Ang;rw$W#;F`6P#rx;{ zkRHb@wC4CA)kxx*Ez7JRy@1m=8H1Ra=G>yz=(cLDPHwgl$!Isfij@i>*r+>a;xD{D zaY@hQYoq}>Uin(q*ZGTQA2_+ZxN`7Fc=C*PkuWXts`}>!u8^teQ-3fPg!* zTHXD;%f>HfetlOY8A&J8)_oo-Jw)IFFcGz-j@&;~yRXtxNmQ_>)K(h2Z`qFqRUgMQ z5bDTY2G}22maPyWSDK^vUiu#%r2n@6|Esp3CPY^4&&`5A6@hFkJc-R2sn|o1;!A}jw2?wtWuWzYIgK4+#N&7{Z8CItxq?c{>&B1m& zJ%2x9IACx1)eQZQvDbEeR4$V^uc~WdPNvdVKfQJ;CnSBJA;O^(-6fgdrZex8?WS_^ zhYqcMU%M^K&46SDl3fwIA3Vug@i2Gz^JT%`K0SZ+)mppoN=|U?nUw@8Qb2^n6)+d6zap5 z*ujJFUS!neD@p0?vrcjkE3kz)8ql=aLObyKN@7zm9i*$30g7mLVTazuY64!t{vE2f zJikk5Ow-^wL#=rc57tlaE}LR+?td-QWoKAftb{IeyLe=E*2POY8`?V@Bz8#Lf!04# z3vp20XQf8pEUOSSVQcV}8()T1wWZkAfDst=#a}5Ln%9GY-w7E`>HKiq^4!brU3a&g zl(;Q=42K865D|f1y_tJy)lxtEWH!V3ZbZ!|NG}VuXCF>eaZU%AkN_)f@Mkl!w=mbxD)@KbNml)95mF0m}vY76G{?Uh{^nu?i-u7tI8tW z%9^d%z+r>rryKn18W7&4rd|@2Y(UtpR`(>9%ReBG)p;C)U$>$O0_r_2eNS!vod9p? z_;qW=JkGl{3Vrm5{?TT?W~j1lOfLX^+8+FzzHh-{vmDNQ*X8UA^IlebY~ZYujoi7% z;*TCxcG@iTGES3yIgO;=Ue?|?DbpM_%}Yi&A=~BWl;eHWZ0gZa=%h>^J8t>Io2jbv zme*|eyPn#X|;L-oSD-9FsCk|qsR_3t6QdvZR+ zvPAq~`uy96X>N-D@Q?mq^mKpMVfzDE(!T@tKT4X#)P&bxH2Uw_oC-KB)OzI0x8agC zV{-70IU{Ul;!?D$_4K#cxUu*tTMr9~M`o)8`mxTwvj}|#B;V~4hh^kvKsY6 zD|AYHicn^!f=7nHO`7nGSEY<4^XBn97ip>cueHJQ>GumC=&s5nIDmOyTxg>MVdoVy zo?X2iDiE_!kg+fbn2p%E{TkFV8M$c8pp|BR2Xo{X1v?7sy}WubT;}fk%>g|Ylr7A+ zPimf5vx~O2j*khKG+}(Tl{bZ*B?wu2snz(GgPVuEq%!_o*W=JB`uZN=3Zc!Yw6P<3iV;xe|_a z^p%F?#2WM6A%zuZjx>!)_dR0mQe8pi=B|Ixu}6Ni>Cup3Z$}tkM9co{owrlzxbyG*?)#vCJN2+pEqxb0p@^8z*acjDVzZTaCokxu*TO8B_s-q zeQABDa0VnvU1ay?S5Nxk^{y_otiG4GZWxjBrBnmXgvqP*Q9;-!f20~1iliZw=cW@;;54ow8LS8*vu*sU#8Pd=!PB-c>IY7%$m1dtrX(P?}xTQs_Qh&JFb(&wxL8u}Q zbS7|OPuIbAzOU{7Y46;BnohGY{_T}gXn~eX0m0Hj76%=Iw zJFSCSFT=JJftCO*f)`+rn~Ea>4k{JUl+r;!yui$8Wq=d`6_#ND5s(4dn*G7aW;R)~ zyO`bh2fR5sdCr^nB=7k=$KtSB3cqyD(0P^l>_*QR3YBJtE21&jgH8;iQ{c>s45LB4 z)2PLeBb|{Aw6Zb?1apoei~juW-eT;~YAJcJqB+B!thwU2`iqVigQBewxpZ8mNDqFL zc#G+JbgyQ}$YZlcLP^j(?gp&egDM<5%I|8BtG_^9Oj5 zhlbT)6LbAOd+n5J56H?j>XL;DCwSt=;~CL_2$ck?hejI2H7ioq?>m`V(bQ{kP`P$_ zQE(!*4e2PNTkPV>$eTtF>;Wa|Ubi&Vf6tDCYdgEPSa~Q- zLBRYiV*2+|ZwQwOTi?!DbGt%S(@g0)kbssvYYyHp;~nvnA<2>7O@eg^;euy zG=-&;zFF=hbTZ8k91#X#WmI!9=4AqX-N_f@{Vleg3I)@$u0oBk1J&*9yq`B_*F-4q zDLx7{IeCSt6QHs(ta&Md_6^yIRK0N)#SDyy-%O-3iG4BIU&!E$l9$Ie%-=ICh14_| zWR0}CJ=-u=F95N<$2_%1Gc}La;0NqZL&NK&?-v!S{5oCL;PByV$4Z}vBF!;rJiIy% zwK4K)$B!w&l_Cf%76?jsLkhU40htV7ciMBs!K1Bw#P=*hb4mkmJcswsg<7ARvAAFz#*d*vF)7LUct59m5>zdk_-(Req1?=(77GCKC2GeqQ5lA2sE-Upz z(2$8Nvj8id#HU`@R%S;|E+<60T-=&o8{WAsJ2xF#zNT%{x1%{Oqu3hn;WkB+&iGdx z)RxB;8yAuaVuWG?zZO`WcNyk5N8%7sf)*9*_j~(0%U*~~MhVNNi;=cf1XP1o zVi$mW2|_;x`69~f3S_73k8?fIP?8(B;GWOigy)Hl=yfLQ6i&b)tLA6Tc6(w&Wnesf z2RAQl%lIH~)?do+k=QTr4QzD;z)~o&&z=Q)6}Fq4NQiNJQ=G=OuFX2E-!OTUy1kuL zD&FP2-!;`%x|llGCL4c1t5}dZg%xyrD_)*o*zO*GfcmP3DvY z{F%mA3-^RiujWkEKW!Y%T*d7BZTH(G*fDriAoN_$p1g7d`_{$k6TdX%pq#}U=eDWg za|JmDIuSxtc}?^Ko10hYue8tr?N?OdfYNctA)5IMua-vy42naEf-fdV`r*<(^ zVYBp}*t8O|xj+Rm1=7DxXhyAYo`4PNjP-8jaNmUM8U02BxfDF=q0ZkicKpmwzr&0Y z6$B%#YPnLJNtKVpEo>*BF4(D1!0?Ockyv&acfA;H&P7ye(>w~t-DLV{N9URppBv&- zfeq`yP)zNn$hBZ5AA;k(I&|H+3qzVE*qvof$XwJSeRS+!YnbLfZBbA0`n?wsfgp?s z95yAf-g0irFS0b3qPL5ZbLeo?EC5ITt3*gXXN%Lw$)T8UL7CuUtKHH0N z0kHWFCgCCbYp;0Tx_y;~qyQ&-sP9BB^E$}YZ+wQ|vqK%6xF?$y2JTjlJv+?ny;=KB zJ?}3Ki31)-Uv=FXdw6Gk-}$REciifJO$zYPLB8y1!WJo0eH;1MYN3vNcjE5X^GAOF zkG~YH*MB+2$2Ybge`3j6;Y|P(v~+FiA1SkBss2&$k5}fOo>;OxK1lXSS%oFb_y13~ zPsJ*Hmh2xBe~Z+{7daZcb)SDWAu!)(J2{4R*4g)43KhGbeSVdorH2#t xGN_0u9@A*UUImxZ73e#h@ZqhO0!uuGIEsEonkgx^w>>YO_Ad-l{Nv-f{%_3A>Q?{& literal 0 HcmV?d00001 diff --git a/docs/user-guide.md b/docs/user-guide.md deleted file mode 100644 index 7f3398e..0000000 --- a/docs/user-guide.md +++ /dev/null @@ -1,1147 +0,0 @@ -# User Guide - -!!! info - - This guide provides technical guidance and exploration of the PyScript - platform. - - While we endeavour to write clearly, some of the content in this user guide - will not be suitable for beginners. We assume readers already have Python - or web development experience. If you're a beginner start with our - [beginner's guide](beginning-pyscript.md). - - We [welcome constructive feedback](https://github.com/pyscript/docs/issues). - -This guide has three aims: - -1. A [clear overview](#what-is-pyscript) of all things PyScript. -2. [Exploration of PyScript](#architecture) in substantial technical detail. -3. Demonstration of the features of PyScript working together in - [real-world example applications](#examples). - -_Read this page in full_: it is a short but comprehensive overview of the -PyScript platform. - -Get involved! Join in the PyScript conversation on our -[discord server](https://discord.gg/HxvBtukrg2). There you'll find core -developers, community contributors and a flourishing forum for those creating -projects with PyScript. Should you wish to engage with the development of -PyScript, you are welcome to contribute via -[the project's GitHub organisation](https://github.com/pyscript). - -Finally, the projects at the end of this page are all freely available -and copiously commented on [pyscript.com](https://pyscript.com). - -!!! note - - Many of these examples come from contributors in our wonderful - community. We love to recognise, amplify and celebrate the incredible work - of folks in the PyScript community. If you believe you have a project that - would make a good demonstration, please don't hesitate to - [get in touch](https://discord.gg/HxvBtukrg2). - -## What is PyScript? - -[PyScript](https://pyscript.net) is a platform for [Python](https://python.org) in the -[browser](https://en.wikipedia.org/wiki/Web_browser). - -PyScript brings together two of the most vibrant technical ecosystems on the -planet. If [the web](https://en.wikipedia.org/wiki/World_Wide_Web) and Python -had a baby, you'd get PyScript. - -PyScript works because modern browsers support -[WebAssembly](https://webassembly.org/) (abbreviated to WASM) - an -[instruction set](https://en.wikipedia.org/wiki/Instruction_set_architecture) -for a [virtual machine](https://en.wikipedia.org/wiki/Virtual_machine) with -an open specification and near native performance. PyScript takes -versions of the Python interpreter compiled to WASM, and makes them easy to use -inside the browser. - -At the core of PyScript is a _philosophy of digital empowerment_. The web is -the world's most ubiquitous computing platform, mature and familiar to billions -of people. Python is one of the -[world's most popular programming languages](https://spectrum.ieee.org/the-top-programming-languages-2023): -it is easy to teach and learn, used in a plethora of existing domains -(such as data science, games, embedded systems, artificial intelligence, -finance, physics and film production - to name but a few), and the Python -ecosystem contains a huge number of popular and powerful libraries to address -its many uses. - -PyScript brings together the ubiquity, familiarity and accessibility of the web -with the power, depth and expressiveness of Python. It means PyScript isn't -just for programming experts but, as we like to say, for the 99% of the rest of -the planet who use computers. - -## Features - -

-
All the web
-
-

Pyscript gives you full access to the DOM and all - the web - APIs implemented by your browser.

- -

Thanks to the foreign - function interface (FFI), Python just works with all the browser has to - offer, including any third party JavaScript libraries that may be included - in the page.

- -

The FFI is bi-directional ~ it also enables JavaScript to access the - power of Python.

- -
All of Python
-
-

PyScript brings you two Python interpreters:

-
    -
  1. Pyodide - the original standard - CPython interpreter you know and love, but compiled to WebAssembly. -
  2. -
  3. MicroPython - a lean and - efficient reimplementation of Python3 that includes a comprehensive - subset of the standard library, compiled to WebAssembly.
  4. -
-

Because it is just regular CPython, Pyodide puts Python's deep and - diverse ecosystem of libraries, frameworks - and modules at your disposal. No matter the area of computing endeavour, - there's probably a Python library to help. Got a favourite library in - Python? Now you can use it in the browser and share your work with just - a URL.

-

MicroPython, because of its small size (170k) and speed, is especially - suited to running on more constrained browsers, such as those on mobile - or tablet devices. It includes a powerful sub-set of the Python standard - library and efficiently exposes the expressiveness of Python to the - browser.

-

Both Python interpreters supported by PyScript implement the - same FFI to bridge the gap between the worlds of Python - and the browser.

-
- -
AI and Data science built in
-
Python is famous for its extraordinary usefulness in artificial - intelligence and data science. The Pyodide interpreter comes with many of - the libraries you need for this sort of work already baked in.
- -
Mobile friendly MicroPython
-
-

Thanks to MicroPython in PyScript, there is a compelling story for - Python on mobile.

- -

MicroPython is small and fast enough that your app will start quickly - on first load, and almost instantly (due to the cache) on subsequent - runs.

- -
Parallel execution
-
Thanks to a browser technology called - web workers - expensive and blocking computation can run somewhere other than the main - application thread controlling the user interface. When such work is done - on the main thread, the browser appears frozen; web workers ensure - expensive blocking computation happens elsewhere. - Think of workers as independent subprocesses in your web page.
- -
Rich and powerful plugins
-
-

PyScript has a small, efficient yet powerful core called - PolyScript. Most of - the functionality of PyScript is actually implemented through PolyScript's - plugin system.

- -

This approach ensures a clear separation of concerns: PolyScript - can focus on being small, efficient and powerful, whereas the PyScript - related plugins allow us to build upon the solid foundations of - PolyScript.

- -

Because there is a plugin system, folks - independent of the PyScript core team have a way to create and - contribute to a rich ecosystem of plugins whose functionality reflects the - unique and diverse needs of PyScript's users.

-
-
- -## First steps - -It's simple: - -* tell your browser to use PyScript, then, -* tell PyScript how to run your Python code. - -For the browser to use PyScript, simply add a ` - - - - - -``` - -There are two ways to tell PyScript how to find your code. - -* With a standard HTML ` -``` - -...and here's a `` tag with inline Python code. - -```html title="A <py-script> tag with inline code" - -import sys -from pyscript import display - - -display(sys.version) - -``` - -The ` - - ``` - - Notice how different interpreters can be used with different - configurations. - -## Architecture - -PyScript's architecture has two core concepts: - -1. A small, efficient and powerful kernel called - [PolyScript](https://github.com/pyscript/polyscript) is the foundation - upon which PyScript and plugins are built. -2. The PyScript [stack](https://en.wikipedia.org/wiki/Solution_stack) inside - the browser is simple and clearly defined. - -### PolyScript - -[PolyScript](https://github.com/pyscript/polyscript) is the core of PyScript. - -!!! danger - - Unless you are an advanced user, you only need to know that PolyScript - exists, and it can be safely ignored. - -PolyScript's purpose is to bootstrap the platform and provide all the necessary -core capabilities. Setting aside PyScript for a moment, to use -*just PolyScript* requires a ` - - - - - - -``` - -!!! warning - - **PolyScript is not PyScript.** - - PyScript enhances the available Python interpreters with convenient - features, helper functions and easy-to-use yet powerful capabilities. - - These enhancements are missing from PolyScript. - -PolyScript's capabilities, upon which PyScript is built, can be summarised as: - -* Evaluation of code via [` -``` - -If you use JSON, you can make it the value of the `config` attribute: - -```HTML title="JSON as the value of the config attribute" - -``` - -For historical and convenience reasons we still support the inline -specification of configuration information via a _single_ `` or -`` tag in your HTML document: - -```HTML title="Inline configuration via the <py-config> tag" - -{ - "packages": ["arrr", "numberwang" ] -} - -``` - -!!! warning - - Should you use `` or ``, **there must be only one of - these tags on the page per interpreter**. - -### Options - -There are four core options ([`interpreter`](#interpreter), [`files`](#files), -[`packages`](#packages) and [`plugins`](#plugins)). The user is free to define -arbitrary additional configuration options that plugins or an app may require -for their own reasons. - -#### Interpreter - -The `interpreter` option pins the Python interpreter to the version of the -specified value. This is useful for testing (does my code work on a specific -version of Pyodide?), or to ensure the precise combination of PyScript version -and interpreter version are pinned to known values. - -The value of the `interpreter` option should be a valid version number -for the Python interpreter you are configuring, or a fully qualified URL to -a custom version of the interpreter. - -The following two examples are equivalent: - -```TOML title="Specify the interpreter version in TOML" -interpreter = "0.23.4" -``` - -```JSON title="Specify the interpreter version in JSON" -{ - "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" -{ - "interpreter": "https://cdn.jsdelivr.net/pyodide/v0.23.4/full/pyodide.mjs" -} -``` - -#### Files - -The `files` option fetches arbitrary content from URLs onto the filesystem -available to Python, and emulated by the browser. Just map a valid URL to a -destination filesystem path. - -The following JSON and TOML are equivalent: - -```json title="Fetch files onto the filesystem with JSON" -{ - "files": { - "https://example.com/data.csv": "./data.csv", - "/code.py": "./subdir/code.py" - } -} -``` - -```toml title="Fetch files onto the filesystem with TOML" -[files] -"https://example.com/data.csv" = "./data.csv" -"/code.py" = "./subdir/code.py" -``` - -If you make the target an empty string, the final "filename" part of the source -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" -{ - "files": { - "https://example.com/data.csv": "", - ... etc ... - } -} -``` - -```toml title="TOML implied filename in the root directory" -[files] -"https://example.com/data.csv" = "" -... etc ... -``` - - -!!! warning - - **PyScript expects all file destinations to be unique.** - - If there is a duplication PyScript will raise an exception to help you find - the problem. - -!!! tip - - **For most people, most of the time, the simple URL to filename mapping, - described above, will be sufficient.** - - Yet certain situations may require more flexibility. In which case, read - on. - -Sometimes many resources are needed to be fetched from a single location and -copied into the same directory on the file system. To aid readability and -reduce repetition, the `files` option comes with a mini -[templating language](https://en.wikipedia.org/wiki/Template_processor) -that allows re-usable placeholders to be defined between curly brackets (`{` -and `}`). When these placeholders are encountered in the `files` configuration, -their name is replaced with their associated value. - -!!! Attention - - Valid placeholder names are always enclosed between curly brackets - (`{` and `}`), like this: `{FROM}`, `{TO}` and `{DATA SOURCE}` - (capitalized names help identify placeholders - when reading code ~ although this isn't strictly necessary). - - Any number of placeholders can be defined and used anywhere within URLs and - paths that map source to destination. - -The following JSON and TOML are equivalent: - -```json title="Using the template language in JSON" -{ - "files": { - "{DOMAIN}": "https://my-server.com", - "{PATH}": "a/path", - "{VERSION}": "1.2.3", - "{FROM}": "{DOMAIN}/{PATH}/{VERSION}", - "{TO}": "./my_module", - "{FROM}/__init__.py": "{TO}/__init__.py", - "{FROM}/foo.py": "{TO}/foo.py", - "{FROM}/bar.py": "{TO}/bar.py", - "{FROM}/baz.py": "{TO}/baz.py", - } -} -``` - -```toml title="Using the template language in TOML" -[files] -"{DOMAIN}" = "https://my-server.com" -"{PATH}" = "a/path" -"{VERSION}" = "1.2.3" -"{FROM}" = "{DOMAIN}/{PATH}/{VERSION}" -"{TO}" = "./my_module" -"{FROM}/__init__.py" = "{TO}/__init__.py" -"{FROM}/foo.py" = "{TO}/foo.py" -"{FROM}/bar.py" = "{TO}/bar.py" -"{FROM}/baz.py" = "{TO}/baz.py" -``` - -The `{DOMAIN}`, `{PATH}`, and `{VERSION}` placeholders are -used to create a further `{FROM}` placeholder. The `{TO}` placeholder is also -defined to point to a common sub-directory on the file system. The final four -entries use `{FROM}` and `{TO}` to copy over four files (`__init__.py`, -`foo.py`, `bar.py` and `baz.py`) from the same source to a common destination -directory. - -For convenience, if the destination is just a directory (it ends with `/`) -then PyScript automatically uses the filename part of the source URL as the -filename in the destination directory. - -For example, the end of the previous config file could be: - -```toml -"{TO}" = "./my_module/" -"{FROM}/__init__.py" = "{TO}" -"{FROM}/foo.py" = "{TO}" -"{FROM}/bar.py" = "{TO}" -"{FROM}/baz.py" = "{TO}" -``` - -#### Packages - -The `packages` option defines a list of Python `packages` to be installed from -[PyPI](https://pypi.org/) onto the filesystem by Pyodide's -[micropip](https://micropip.pyodide.org/en/stable/index.html) package -installer. - -!!! warning - - Because `micropip` is a Pyodide-only feature, and MicroPython doesn't - support code packaged on PyPI, **the `packages` option is only available - for use with Pyodide**. - - If you need **Python modules for MicroPython** to use, you should use the - [files](#files) option to manually copy the source code onto the - file system. - -The following two examples are equivalent: - -```TOML title="A packages list in TOML" -packages = ["arrr", "numberwang", "snowballstemmer>=2.2.0" ] -``` - -```JSON title="A packages list in JSON" -{ - "packages": ["arrr", "numberwang", "snowballstemmer>=2.2.0" ] -} -``` - -The names in the list of `packages` can be any of the following valid forms: - -* A name of a package on PyPI: `"snowballstemmer"` -* A name for a package on PyPI with additional constraints: - `"snowballstemmer>=2.2.0"` -* An arbitrary URL to a Python package: `"https://.../package.whl"` -* A file copied onto the browser based file system: `"emfs://.../package.whl"` - -#### Plugins - -The `plugins` option lists plugins enabled by PyScript to add extra -functionality to the platform. - -Each plugin should be included on the web page, as described in the -[plugins](#plugins_1) section below. Then the plugin's name should be listed. - -```TOML title="A list of plugins in TOML" -plugins = ["custom_plugin", "!error"] -``` - -```JSON title="A list of plugins in JSON" -{ - "plugins": ["custom_plugin", "!error"] -} -``` - -!!! info - - The `"!error"` syntax is a way to turn off a plugin built into PyScript - that is enabled by default. - - Currently, the only built-in plugin is the `error` plugin to display a - stack trace and error messages in the DOM. More may be added at a later - date. - -#### Custom - -Sometimes plugins or apps need bespoke configuration options. - -So long as you don't cause a name collision with the built-in option names then -you are free to use any valid data structure that works with both TOML and JSON -to express your configuration needs. - -**TODO: explain how to programmatically get access to an object representing -the config.** - -## The DOM - -The DOM -([document object model](https://developer.mozilla.org/en-US/docs/Web/API/Document_object_model)) -is a tree like data structure representing the web page displayed by the -browser. PyScript interacts with the DOM to change the user interface and react -to things happening in the browser. - -There are currently two ways to interact with the DOM: - -1. Through the [foreign function interface](#ffi) (FFI) to interact with objects found - in the browser's `globalThis` or `document` objects. -2. Through the [`pydom` module](#pydom) that acts as a Pythonic wrapper around - the FFI and comes as standard with PyScript. - -### FFI - -The foreign function interface (FFI) gives Python access to all the -[standard web capabilities and features](https://developer.mozilla.org/en-US/docs/Web), -such as the browser's built-in -[web APIs](https://developer.mozilla.org/en-US/docs/Web/API). - -This is available via the `pyscript.window` module which is a proxy for -the main thread's `globalThis` object, or `pyscript.document` which is a proxy -for the website's `document` object in JavaScript: - -```Python title="Accessing the window and document objects in Python" -from pyscript import window, document - - -my_element = document.querySelector("#my-id") -my_element.innerText = window.location.hostname -``` - -The FFI creates _proxy objects_ in Python linked to _actual objects_ in -JavaScript. - -The objects in your Python code look and behave like Python -objects but have related JavaScript objects associated with them. It means the -API defined in JavaScript remains the same in Python, so any -[browser based JavaScript APIs](https://developer.mozilla.org/en-US/docs/Web/API) -or third party JavaScript libraries that expose objects in the web page's -`globalThis`, will have exactly the same API in Python as in JavaScript. - -The FFI automatically transforms Python and JavaScript objects into the -equivalent in the other language. For example, Python's boolean `True` and -`False` will become JavaScript's `true` and `false`, while a JavaScript array -of strings and integers, `["hello", 1, 2, 3]` becomes a Python list of the -equivalent values: `["hello", 1, 2, 3]`. - -!!! info - - Instantiating classes into objects is an interesting special case that the - FFI expects you to handle. - - **If you wish to instantiate a JavaScript class in your Python - code, you need to call the class's `new` method:** - - ```python - from pyscript import window - - - my_obj = window.MyJavaScriptClass.new("some value") - - ``` - - The underlying reason for this is simply JavaScript and Python do - instantiation very differently. By explicitly calling the JavaScript - class's `new` method PyScript both signals and honours this difference. - - -### PyDom - -The built-in Python module `pydom` wraps many (although not all) the features -available via the FFI in an idiomatically Pythonic manner. - - -The PyDom API is extensively described and demonstrated -[on this PyScript page](https://fpliger.pyscriptapps.com/pyweb/latest/pydom.html). - -!!! warning - - PyDom is currently a work in progress. - - We welcome feedback and suggestions. - -**TODO Fabio to finish** - -## Workers - -Workers run code that won't block the "main thread" controlling the user -interface. If you block the main thread, your web page becomes annoyingly -unresponsive.** You should never block the main thread.** - -Happily, PyScript makes it very easy to use workers. - -To make this happen PyScript uses a feature recently added to web standards -called -[Atomics](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics). - -### HTTP headers - -For Atomics to work **you must ensure your web server enables the following -headers** (this is the default behaviour for -[pyscript.com](https://pyscript.com)): - -``` -Cross-Origin-Opener-Policy: same-origin -Cross-Origin-Embedder-Policy: require-corp -Cross-Origin-Resource-Policy: cross-origin -``` - -If you are not able to configure your server's headers, use the -[mini-coi](https://github.com/WebReflection/mini-coi#readme) project to -achieve the same end. - -### Start working - -To start your code in a worker, simply ensure the ` -``` - -Code running in the worker needs to be able to access the web page running in -the main thread. This is achieved via builtin helper utilities described in the -next section. - -!!! note - - For ease of use, the worker related functionality in PyScript is - a simpler presentation of more sophisticated and powerful behaviour - available via PolyScript. - - **If you are a confident advanced user**, please - [consult the XWorker](https://pyscript.github.io/polyscript/#xworker) - related documentation from the PolyScript project for how to make use of - these features. - -## Builtin helpers - -PyScript makes available convenience objects and functions inside -Python. This is done via the `pyscript` module: - -```python title="Accessing the document object via the pyscript module" -from pyscript import document -``` - -### Common features - -These objects / functions are available in both the main thread and in code -running on a web worker: - -#### `pyscript.window` - -This object is a proxy for the web page's -[global window context](https://developer.mozilla.org/en-US/docs/Web/API/Window). - -!!! warning - - Please note that in workers, this is still the main window, not the - worker's own global context. A worker's global context is reachable instead - via `import js` (the `js` object being a proxy for the worker's - `globalThis`). - -#### `pyscript.document` - -This object is a proxy for the the web page's -[document object](https://developer.mozilla.org/en-US/docs/Web/API/Document). -The `document` is a representation of the -[DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_object_model/Using_the_Document_Object_Model) -and can be used to manipulate the content of the web page. - -#### `pyscript.display` - -A function used to display content. The function is intelligent enough to -introspect the object[s] it is passed and work out how to correctly display the -object[s] in the web page. - -The `display` function takes a list of `*values` as its first argument, and has -two optional named arguments: - -* `target=None` - the DOM element into which the content should be placed. -* `append=True` - a flag to indicate if the output is going to be appended to - the `target`. - -There are some caveats: - -* When used in the main thread, the `display` function automatically uses - the current ` + + + + + + +``` + +!!! warning + + **PolyScript is not PyScript.** + + PyScript enhances the available Python interpreters with convenient + features, helper functions and easy-to-use yet powerful capabilities. + + These enhancements are missing from PolyScript. + +PolyScript's capabilities, upon which PyScript is built, can be summarised as: + +* Evaluation of code via [` +``` + +If you use JSON, you can make it the value of the `config` attribute: + +```HTML title="JSON as the value of the config attribute" + +``` + +For historical and convenience reasons we still support the inline +specification of configuration information via a _single_ `` or +`` tag in your HTML document: + +```HTML title="Inline configuration via the <py-config> tag" + +{ + "packages": ["arrr", "numberwang" ] +} + +``` + +!!! warning + + Should you use `` or ``, **there must be only one of + these tags on the page per interpreter**. + +## Options + +There are four core options ([`interpreter`](#interpreter), [`files`](#files), +[`packages`](#packages) and [`plugins`](#plugins)). The user is free to define +arbitrary additional configuration options that plugins or an app may require +for their own reasons. + +### Interpreter + +The `interpreter` option pins the Python interpreter to the version of the +specified value. This is useful for testing (does my code work on a specific +version of Pyodide?), or to ensure the precise combination of PyScript version +and interpreter version are pinned to known values. + +The value of the `interpreter` option should be a valid version number +for the Python interpreter you are configuring, or a fully qualified URL to +a custom version of the interpreter. + +The following two examples are equivalent: + +```TOML title="Specify the interpreter version in TOML" +interpreter = "0.23.4" +``` + +```JSON title="Specify the interpreter version in JSON" +{ + "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" +{ + "interpreter": "https://cdn.jsdelivr.net/pyodide/v0.23.4/full/pyodide.mjs" +} +``` + +### Files + +The `files` option fetches arbitrary content from URLs onto the filesystem +available to Python, and emulated by the browser. Just map a valid URL to a +destination filesystem path. + +The following JSON and TOML are equivalent: + +```json title="Fetch files onto the filesystem with JSON" +{ + "files": { + "https://example.com/data.csv": "./data.csv", + "/code.py": "./subdir/code.py" + } +} +``` + +```toml title="Fetch files onto the filesystem with TOML" +[files] +"https://example.com/data.csv" = "./data.csv" +"/code.py" = "./subdir/code.py" +``` + +If you make the target an empty string, the final "filename" part of the source +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" +{ + "files": { + "https://example.com/data.csv": "", + ... etc ... + } +} +``` + +```toml title="TOML implied filename in the root directory" +[files] +"https://example.com/data.csv" = "" +... etc ... +``` + + +!!! warning + + **PyScript expects all file destinations to be unique.** + + If there is a duplication PyScript will raise an exception to help you find + the problem. + +!!! tip + + **For most people, most of the time, the simple URL to filename mapping, + described above, will be sufficient.** + + Yet certain situations may require more flexibility. In which case, read + on. + +Sometimes many resources are needed to be fetched from a single location and +copied into the same directory on the file system. To aid readability and +reduce repetition, the `files` option comes with a mini +[templating language](https://en.wikipedia.org/wiki/Template_processor) +that allows re-usable placeholders to be defined between curly brackets (`{` +and `}`). When these placeholders are encountered in the `files` configuration, +their name is replaced with their associated value. + +!!! Attention + + Valid placeholder names are always enclosed between curly brackets + (`{` and `}`), like this: `{FROM}`, `{TO}` and `{DATA SOURCE}` + (capitalized names help identify placeholders + when reading code ~ although this isn't strictly necessary). + + Any number of placeholders can be defined and used anywhere within URLs and + paths that map source to destination. + +The following JSON and TOML are equivalent: + +```json title="Using the template language in JSON" +{ + "files": { + "{DOMAIN}": "https://my-server.com", + "{PATH}": "a/path", + "{VERSION}": "1.2.3", + "{FROM}": "{DOMAIN}/{PATH}/{VERSION}", + "{TO}": "./my_module", + "{FROM}/__init__.py": "{TO}/__init__.py", + "{FROM}/foo.py": "{TO}/foo.py", + "{FROM}/bar.py": "{TO}/bar.py", + "{FROM}/baz.py": "{TO}/baz.py", + } +} +``` + +```toml title="Using the template language in TOML" +[files] +"{DOMAIN}" = "https://my-server.com" +"{PATH}" = "a/path" +"{VERSION}" = "1.2.3" +"{FROM}" = "{DOMAIN}/{PATH}/{VERSION}" +"{TO}" = "./my_module" +"{FROM}/__init__.py" = "{TO}/__init__.py" +"{FROM}/foo.py" = "{TO}/foo.py" +"{FROM}/bar.py" = "{TO}/bar.py" +"{FROM}/baz.py" = "{TO}/baz.py" +``` + +The `{DOMAIN}`, `{PATH}`, and `{VERSION}` placeholders are +used to create a further `{FROM}` placeholder. The `{TO}` placeholder is also +defined to point to a common sub-directory on the file system. The final four +entries use `{FROM}` and `{TO}` to copy over four files (`__init__.py`, +`foo.py`, `bar.py` and `baz.py`) from the same source to a common destination +directory. + +For convenience, if the destination is just a directory (it ends with `/`) +then PyScript automatically uses the filename part of the source URL as the +filename in the destination directory. + +For example, the end of the previous config file could be: + +```toml +"{TO}" = "./my_module/" +"{FROM}/__init__.py" = "{TO}" +"{FROM}/foo.py" = "{TO}" +"{FROM}/bar.py" = "{TO}" +"{FROM}/baz.py" = "{TO}" +``` + +### Packages + +The `packages` option defines a list of Python `packages` to be installed from +[PyPI](https://pypi.org/) onto the filesystem by Pyodide's +[micropip](https://micropip.pyodide.org/en/stable/index.html) package +installer. + +!!! warning + + Because `micropip` is a Pyodide-only feature, and MicroPython doesn't + support code packaged on PyPI, **the `packages` option is only available + for use with Pyodide**. + + If you need **Python modules for MicroPython**, use the + [files](#files) option to manually copy the source code onto the + file system. + +The following two examples are equivalent: + +```TOML title="A packages list in TOML" +packages = ["arrr", "numberwang", "snowballstemmer>=2.2.0" ] +``` + +```JSON title="A packages list in JSON" +{ + "packages": ["arrr", "numberwang", "snowballstemmer>=2.2.0" ] +} +``` + +The names in the list of `packages` can be any of the following valid forms: + +* A name of a package on PyPI: `"snowballstemmer"` +* A name for a package on PyPI with additional constraints: + `"snowballstemmer>=2.2.0"` +* An arbitrary URL to a Python package: `"https://.../package.whl"` +* A file copied onto the browser based file system: `"emfs://.../package.whl"` + +### Plugins + +The `plugins` option lists plugins enabled by PyScript to add extra +functionality to the platform. + +Each plugin should be included on the web page, as described in the +[plugins](#plugins_1) section below. Then the plugin's name should be listed. + +```TOML title="A list of plugins in TOML" +plugins = ["custom_plugin", "!error"] +``` + +```JSON title="A list of plugins in JSON" +{ + "plugins": ["custom_plugin", "!error"] +} +``` + +!!! info + + The `"!error"` syntax is a way to turn off a plugin built into PyScript + that is enabled by default. + + Currently, the only built-in plugin is the `error` plugin to display a + stack trace and error messages in the DOM. More may be added at a later + date. + +### Custom + +Sometimes plugins or apps need bespoke configuration options. + +So long as you don't cause a name collision with the built-in option names then +you are free to use any valid data structure that works with both TOML and JSON +to express your configuration needs. + +**TODO: explain how to programmatically get access to an object representing +the config.** + diff --git a/docs/user-guide/dom.md b/docs/user-guide/dom.md new file mode 100644 index 0000000..4aafd37 --- /dev/null +++ b/docs/user-guide/dom.md @@ -0,0 +1,87 @@ +# The DOM + +The DOM +([document object model](https://developer.mozilla.org/en-US/docs/Web/API/Document_object_model)) +is a tree like data structure representing the web page displayed by the +browser. PyScript interacts with the DOM to change the user interface and react +to things happening in the browser. + +There are currently two ways to interact with the DOM: + +1. Through the [foreign function interface](#ffi) (FFI) to interact with objects found + in the browser's `globalThis` or `document` objects. +2. Through the [`pydom` module](#pydom) that acts as a Pythonic wrapper around + the FFI and comes as standard with PyScript. + +## FFI + +The foreign function interface (FFI) gives Python access to all the +[standard web capabilities and features](https://developer.mozilla.org/en-US/docs/Web), +such as the browser's built-in +[web APIs](https://developer.mozilla.org/en-US/docs/Web/API). + +This is available via the `pyscript.window` module which is a proxy for +the main thread's `globalThis` object, or `pyscript.document` which is a proxy +for the website's `document` object in JavaScript: + +```Python title="Accessing the window and document objects in Python" +from pyscript import window, document + + +my_element = document.querySelector("#my-id") +my_element.innerText = window.location.hostname +``` + +The FFI creates _proxy objects_ in Python linked to _actual objects_ in +JavaScript. + +The proxy objects in your Python code look and behave like Python +objects but have related JavaScript objects associated with them. It means the +API defined in JavaScript remains the same in Python, so any +[browser based JavaScript APIs](https://developer.mozilla.org/en-US/docs/Web/API) +or third party JavaScript libraries that expose objects in the web page's +`globalThis`, will have exactly the same API in Python as in JavaScript. + +The FFI automatically transforms Python and JavaScript objects into the +equivalent in the other language. For example, Python's boolean `True` and +`False` will become JavaScript's `true` and `false`, while a JavaScript array +of strings and integers, `["hello", 1, 2, 3]` becomes a Python list of the +equivalent values: `["hello", 1, 2, 3]`. + +!!! info + + Instantiating classes into objects is an interesting special case that the + FFI expects you to handle. + + **If you wish to instantiate a JavaScript class in your Python + code, you need to call the class's `new` method:** + + ```python + from pyscript import window + + + my_obj = window.MyJavaScriptClass.new("some value") + + ``` + + The underlying reason for this is simply JavaScript and Python do + instantiation very differently. By explicitly calling the JavaScript + class's `new` method PyScript both signals and honours this difference. + + +## PyDom + +The built-in Python module `pydom` wraps many (although not all) the features +available via the FFI in an idiomatically Pythonic manner. + + +The PyDom API is extensively described and demonstrated +[on this PyScript page](https://fpliger.pyscriptapps.com/pyweb/latest/pydom.html). + +!!! warning + + PyDom is currently a work in progress. + + We welcome feedback and suggestions. + +**TODO Fabio to finish** diff --git a/docs/user-guide/examples.md b/docs/user-guide/examples.md new file mode 100644 index 0000000..8a105df --- /dev/null +++ b/docs/user-guide/examples.md @@ -0,0 +1,3 @@ +# Example applications + +** TODO: fill this with references and descriptions to examples on PyScript.com ** diff --git a/docs/user-guide/features.md b/docs/user-guide/features.md new file mode 100644 index 0000000..1dc5b75 --- /dev/null +++ b/docs/user-guide/features.md @@ -0,0 +1,87 @@ +# Features + +
+
All the web
+
+

Pyscript gives you full access to the DOM and all + the web + APIs implemented by your browser.

+ +

Thanks to the foreign + function interface (FFI), Python just works with all the browser has to + offer, including any third party JavaScript libraries that may be included + in the page.

+ +

The FFI is bi-directional ~ it also enables JavaScript to access the + power of Python.

+ +
All of Python
+
+

PyScript brings you two Python interpreters:

+
    +
  1. Pyodide - the original standard + CPython interpreter you know and love, but compiled to WebAssembly. +
  2. +
  3. MicroPython - a lean and + efficient reimplementation of Python3 that includes a comprehensive + subset of the standard library, compiled to WebAssembly.
  4. +
+

Because it is just regular CPython, Pyodide puts Python's deep and + diverse ecosystem of libraries, frameworks + and modules at your disposal. No matter the area of computing endeavour, + there's probably a Python library to help. Got a favourite library in + Python? Now you can use it in the browser and share your work with just + a URL.

+

MicroPython, because of its small size (170k) and speed, is especially + suited to running on more constrained browsers, such as those on mobile + or tablet devices. It includes a powerful sub-set of the Python standard + library and efficiently exposes the expressiveness of Python to the + browser.

+

Both Python interpreters supported by PyScript implement the + same FFI to bridge the gap between the worlds of Python + and the browser.

+
+ +
AI and Data science built in
+
Python is famous for its extraordinary usefulness in artificial + intelligence and data science. The Pyodide interpreter comes with many of + the libraries you need for this sort of work already baked in.
+ +
Mobile friendly MicroPython
+
+

Thanks to MicroPython in PyScript, there is a compelling story for + Python on mobile.

+ +

MicroPython is small and fast enough that your app will start quickly + on first load, and almost instantly (due to the cache) on subsequent + runs.

+ +
Parallel execution
+
Thanks to a browser technology called + web workers + expensive and blocking computation can run somewhere other than the main + application thread controlling the user interface. When such work is done + on the main thread, the browser appears frozen; web workers ensure + expensive blocking computation happens elsewhere. + Think of workers as independent subprocesses in your web page.
+ +
Rich and powerful plugins
+
+

PyScript has a small, efficient yet powerful core called + PolyScript. Most of + the functionality of PyScript is actually implemented through PolyScript's + plugin system.

+ +

This approach ensures a clear separation of concerns: PolyScript + can focus on being small, efficient and powerful, whereas the PyScript + related plugins allow us to build upon the solid foundations of + PolyScript.

+ +

Because there is a plugin system, folks + independent of the PyScript core team have a way to create and + contribute to a rich ecosystem of plugins whose functionality reflects the + unique and diverse needs of PyScript's users.

+
+
+ + diff --git a/docs/user-guide/first-steps.md b/docs/user-guide/first-steps.md new file mode 100644 index 0000000..0b7a7e0 --- /dev/null +++ b/docs/user-guide/first-steps.md @@ -0,0 +1,141 @@ +# First steps + +It's simple: + +* tell your browser to use PyScript, then, +* tell PyScript how to run your Python code. + +That's it! + +For the browser to use PyScript, simply add a ` + + + + + +``` + +There are two ways to tell PyScript how to find your code. + +* With a standard HTML ` +``` + +...and here's a `` tag with inline Python code. + +```html title="A <py-script> tag with inline code" + +import sys +from pyscript import display + + +display(sys.version) + +``` + +The ` + + ``` + + Notice how different interpreters can be used with different + configurations. + + diff --git a/docs/user-guide/index.md b/docs/user-guide/index.md new file mode 100644 index 0000000..fec64b3 --- /dev/null +++ b/docs/user-guide/index.md @@ -0,0 +1,41 @@ +# The PyScript User Guide + +!!! info + + This guide provides technical guidance and exploration of the PyScript + platform. + + While we endeavour to write clearly, some of the content in this user guide + will not be suitable for beginners. We assume you already have Python + or web development experience. If you're a beginner start with our + [beginner's guide](../beginning-pyscript.md). + + We [welcome constructive feedback](https://github.com/pyscript/docs/issues). + +This guide has three aims: + +1. A [clear overview](what.md) of all things PyScript. +2. [Exploration of PyScript](architecture.md) in substantial technical detail. +3. Demonstration of the features of PyScript working together in + [real-world example applications](examples.md). + +_Read this user guide in full_: it is a short but comprehensive overview of the +PyScript platform. + +Get involved! Join in the PyScript conversation on our +[discord server](https://discord.gg/HxvBtukrg2). There you'll find core +developers, community contributors and a flourishing forum for those creating +projects with PyScript. Should you wish to engage with the development of +PyScript, you are welcome to contribute via +[the project's GitHub organisation](https://github.com/pyscript). + +Finally, the projects at the end of this guide are all freely available +and copiously commented on [pyscript.com](https://pyscript.com). + +!!! note + + Many of these examples come from contributors in our wonderful + community. We love to recognise, share and celebrate the incredible work + of folks in the PyScript community. If you believe you have a project that + would make a good demonstration, please don't hesitate to + [get in touch](https://discord.gg/HxvBtukrg2). diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md new file mode 100644 index 0000000..8a5d2ff --- /dev/null +++ b/docs/user-guide/plugins.md @@ -0,0 +1,3 @@ +# Plugins + +** TODO: Finish this ** diff --git a/docs/user-guide/terminal.md b/docs/user-guide/terminal.md new file mode 100644 index 0000000..6fd4e89 --- /dev/null +++ b/docs/user-guide/terminal.md @@ -0,0 +1,54 @@ +# Terminal + +In conventional (non-browser based) Python, it is common to run scripts from +the terminal, or to interact directly with the Python interpreter via the +[REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop). +It's to the terminal that `print` writes characters (via `stdout`), and it's +from the terminal that the `input` reads characters (via `stdin`). + +It usually looks something like this: + + + +Because of the historic importance of the use of a terminal, PyScript makes one +available in the browser (based upon [XTerm.js](https://xtermjs.org/)). +As [mentioned earlier](first-steps.md), PyScript's built-in terminal is activated +with the `terminal` flag when using the ` +``` + +The end result will look like this (the rectangular box indicates the current +position of the cursor): + + + +Should you need an interactive terminal, for example because you use the +`input` statement that requires the user to type things into the terminal, you +**must ensure your code is run on a worker**: + +```html + +``` + +Once the Python code has finished you are automatically dropped into the +Python REPL, like this: + + + + diff --git a/docs/user-guide/what.md b/docs/user-guide/what.md new file mode 100644 index 0000000..4ce87ba --- /dev/null +++ b/docs/user-guide/what.md @@ -0,0 +1,32 @@ +# What is PyScript? + +[PyScript](https://pyscript.net) is a platform for [Python](https://python.org) in the +[browser](https://en.wikipedia.org/wiki/Web_browser). + +PyScript brings together two of the most vibrant technical ecosystems on the +planet. If [the web](https://en.wikipedia.org/wiki/World_Wide_Web) and Python +had a baby, you'd get PyScript. + +PyScript works because modern browsers support +[WebAssembly](https://webassembly.org/) (abbreviated to WASM) - an +[instruction set](https://en.wikipedia.org/wiki/Instruction_set_architecture) +for a [virtual machine](https://en.wikipedia.org/wiki/Virtual_machine) with +an open specification and near native performance. PyScript takes +versions of the Python interpreter compiled to WASM, and makes them easy to use +inside the browser. + +At the core of PyScript is a _philosophy of digital empowerment_. The web is +the world's most ubiquitous computing platform, mature and familiar to billions +of people. Python is one of the +[world's most popular programming languages](https://spectrum.ieee.org/the-top-programming-languages-2023): +it is easy to teach and learn, used in a plethora of existing domains +(such as data science, games, embedded systems, artificial intelligence, +finance, physics and film production - to name but a few), and the Python +ecosystem contains a huge number of popular and powerful libraries to address +its many uses. + +PyScript brings together the ubiquity, familiarity and accessibility of the web +with the power, depth and expressiveness of Python. It means PyScript isn't +just for programming experts but, as we like to say, for the 99% of the rest of +the planet who use computers. + diff --git a/docs/user-guide/workers.md b/docs/user-guide/workers.md new file mode 100644 index 0000000..4c3362f --- /dev/null +++ b/docs/user-guide/workers.md @@ -0,0 +1,52 @@ +# Workers + +Workers run code that won't block the "main thread" controlling the user +interface. If you block the main thread, your web page becomes annoyingly +unresponsive.** You should never block the main thread.** + +Happily, PyScript makes it very easy to use workers and uses a feature recently +added to web standards called +[Atomics](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics). + +## HTTP headers + +For Atomics to work **you must ensure your web server enables the following +headers** (this is the default behaviour for +[pyscript.com](https://pyscript.com)): + +``` +Cross-Origin-Opener-Policy: same-origin +Cross-Origin-Embedder-Policy: require-corp +Cross-Origin-Resource-Policy: cross-origin +``` + +If you are not able to configure your server's headers, use the +[mini-coi](https://github.com/WebReflection/mini-coi#readme) project to +achieve the same end. + +## Start working + +To start your code in a worker, simply ensure the ` +``` + +Code running in the worker needs to be able to access the web page running in +the main thread. This is achieved via builtin helper utilities described in the +next section. + +!!! note + + For ease of use, the worker related functionality in PyScript is + a simpler presentation of more sophisticated and powerful behaviour + available via PolyScript. + + **If you are a confident advanced user**, please + [consult the XWorker](https://pyscript.github.io/polyscript/#xworker) + related documentation from the PolyScript project for how to make use of + these features. + + diff --git a/mkdocs.yml b/mkdocs.yml index c23db8c..039c5c9 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -61,3 +61,24 @@ plugins: css_dir: css javascript_dir: js canonical_version: null + +nav: + - Home: index.md + - Beginning PyScript: beginning-pyscript.md + - Code of Conduct: conduct.md + - Contributing: contributing.md + - Developer Guide: developers.md + - License: license.md + - User guide: + - Introduction: user-guide/index.md + - What is PyScript?: user-guide/what.md + - Features: user-guide/features.md + - First steps: user-guide/first-steps.md + - Architecture: user-guide/architecture.md + - Configuration: user-guide/configuration.md + - The DOM: user-guide/dom.md + - Workers: user-guide/workers.md + - Builtin helpers: user-guide/builtins.md + - Python terminal: user-guide/terminal.md + - Plugins: user-guide/plugins.md + - Example apps: user-guide/examples.md From 1079d16524406d17fc06d2e2e888fc41f9c7406f Mon Sep 17 00:00:00 2001 From: Fabio Pliger Date: Wed, 1 Nov 2023 14:51:47 -0500 Subject: [PATCH 037/201] add initial paragraph about Pydom --- docs/user-guide.md | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/docs/user-guide.md b/docs/user-guide.md index 0cfff6a..a62f384 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -918,15 +918,27 @@ equivalent values: `["hello", 1, 2, 3]`. ### PyDom -The built-in Python module `pydom` wraps many (although not all) features -to access the brower DOM interface and can be used to interact with the elements -of a web page in an idiomatically Pythonic manner, accessible to humans. While the -[FFI](#ffi) interface described above focus on giving full access to the entire -Javascript Interface, `pydom` focuses on providing a small, intuitive and yet -powerful API. For this reason, while it's first laywer is simple and intuitive -(hence limited), saving many lines of code and making the code easier, it also provides -a secondary layer that can be used to directly use full FFI related to a specific -element. +The Standard Web APIs are massive and not always very user-friendly. `PyDom` is a +Python modue that exposes the power of the web with an easy and idiomatic Pythonic +interface on top. + +While the[FFI](#ffi) interface described above focuses on giving full access to +the entire Standard Web APIs, `pydom` focuses on providing a small, intuitive and yet +powerful API that priotirizes common use cases fist. For this reason, it's first +layer is simple and intuitive (but limited to the most common use cases), but `pydom` +also provides a secondary layer that can be used to directly use full FFI interface +of a specific element. + +It does not aim to replace the regular Web [Javascript] API nor to be as wide and offer +feature parity. On the contrary, it's intentionally small and focused on the most popular +use cases while still providing [a backdoor] access to the full JS API. + + +`Pydom` draws inspiration from popular Python APIs/Libraries known to be friendly and +easy to learn, and other successful projects related the web as well (for isntance, +`JQuery` was a good source of inspiration). + +#### Core Concepts From 684e323d340237bedd047e52066553a1e07367f5 Mon Sep 17 00:00:00 2001 From: Fabio Pliger Date: Wed, 1 Nov 2023 15:09:25 -0500 Subject: [PATCH 038/201] added core concepts and beginning of the Element section --- docs/user-guide.md | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/docs/user-guide.md b/docs/user-guide.md index a62f384..4e24ecc 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -933,23 +933,43 @@ It does not aim to replace the regular Web [Javascript] API nor to be as wide an feature parity. On the contrary, it's intentionally small and focused on the most popular use cases while still providing [a backdoor] access to the full JS API. - `Pydom` draws inspiration from popular Python APIs/Libraries known to be friendly and easy to learn, and other successful projects related the web as well (for isntance, `JQuery` was a good source of inspiration). +!!! warning + + PyDom is currently a work in progress. + + We welcome feedback and suggestions. + + #### Core Concepts +`Pydom` builds on topic of very few and simple core concepts: +* __`Element`:__ any component that is part of a web page. This is a rough abstraction of an +[HTMLElement](https://developer.mozilla.org/en-US/docs/Glossary/Element). In general, +`pydom` elements always map to an underlying `HTML` `Element` in a we page +* __`ElementCollection`:__ a collection of one or more `Elements`. It is a rough abstraction +of a [HTMLCollection](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection). +* __Querying:__ a method to query elements on a page based on a +[selector](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_selectors). Pydom supports +standard HTML DOM query selectors to [locate DOM elements](https://developer.mozilla.org/en-US/docs/Web/API/Document_object_model/Locating_DOM_elements_using_selectors) as other native `JavaScript` methods like +`querySelector` or `querySelectorAll`. -The PyDom API is extensively described and demonstrated -[on this PyScript page](https://fpliger.pyscriptapps.com/pyweb/latest/pydom.html). +Following, we'll look into each one of these aspects a bit more in detail. -!!! warning +##### Element - PyDom is currently a work in progress. +`pydom` `Element` is simply just an abstraction of a tranditional `Element` in a web page. +Every `Element` always maps to an underlying `JavaScript` `Element` in a web page. These 2 +elements are always in sync and any change of state in one is reflect into the other. + +__ADD DIAGRAM HERE__ + +###### Creating a new element - We welcome feedback and suggestions. From 2faaf59edbb46ded1e70455b64c373e598005124 Mon Sep 17 00:00:00 2001 From: Fabio Pliger Date: Wed, 1 Nov 2023 15:21:36 -0500 Subject: [PATCH 039/201] add create element section --- docs/user-guide.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docs/user-guide.md b/docs/user-guide.md index 4e24ecc..af481a8 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -970,7 +970,33 @@ __ADD DIAGRAM HERE__ ###### Creating a new element +New elements can be created by using the `pydom.create` method and passing the type of element +being crated. Here's an example of what it looks like: +(To execute and explore the following code, click on the "load" button. The result will be +conveniently displayed in the box on the below of the code example) + +```python +from pyweb import pydom + +# Creating an element directly from pydom creates an unbounded element. +new_div = pydom.create("div") + +# Creating an element from another element automatically creates that element +# as a child of the original element +new_p = new_div.create("p", classes=["code-description"], html="Ciao PyScripters!") + +# elements can be appended to any other element on the page +pydom['#element-creation-example'][0].append(new_div) +``` + +
+

Result will go here

+
+
+ + +For more details about `pydom.create` please refer to its reference documentation. ## Workers From 81240e08908295da67628406e12f5da8bb531af7 Mon Sep 17 00:00:00 2001 From: Fabio Pliger Date: Wed, 1 Nov 2023 17:32:33 -0500 Subject: [PATCH 040/201] add content to Element paragraph --- docs/user-guide.md | 56 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/docs/user-guide.md b/docs/user-guide.md index af481a8..424911a 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -960,7 +960,7 @@ standard HTML DOM query selectors to [locate DOM elements](https://developer.moz Following, we'll look into each one of these aspects a bit more in detail. -##### Element +#### Element `pydom` `Element` is simply just an abstraction of a tranditional `Element` in a web page. Every `Element` always maps to an underlying `JavaScript` `Element` in a web page. These 2 @@ -968,7 +968,7 @@ elements are always in sync and any change of state in one is reflect into the o __ADD DIAGRAM HERE__ -###### Creating a new element +##### Creating a new element New elements can be created by using the `pydom.create` method and passing the type of element being crated. Here's an example of what it looks like: @@ -991,14 +991,62 @@ pydom['#element-creation-example'][0].append(new_div) ```
-

Result will go here

+
Result will go here
For more details about `pydom.create` please refer to its reference documentation. - +##### Setting the content of an element + +The Element interface offers 2 main ways to set an element content: the `html` and the +`content` attributes: + +* `content`: sets the `innerHTML` field via the PyScript `display` function. This takes care +of properly rendering the object being passed based on the object mimetype. So, for instance, +if the objects is an image, it'll be properly rendered on the element +* `html`: directly sets the `innerHTML` field of the underlying element without attemnpting +any conversion. + +In general, we suggest using `content` directly as it'll take care of most use cases without +requiring any extra logic from the user. + +##### Changing the element style + +Elements have a `style` attribute that can be used to change the element style rules. +The style attribyte can be used as a dictionary and, to set a style rule for the element, +simply set the correct key on the `.style` attribute. For instance, the following +code changes the background color of the element just created in the example above: + +```python +new_p.style["background-color"] = "yellow" +``` + +to remove a specific style key, simply use the `pop` method as you'd to to remove +a key from a dictionary: + +```python +new_p.style.pop("background-color") +``` + +In addition to the dictionary interface to explicitly set CSS rules, the `style` attribute +also offers a convenient `visible` property that can be use show/hide an element. + +```python +new_p.style.visible = False +``` + +##### Other useful aspects of the Element API + +`append`: method to append a new child to the element. +`children`: list of the children of the element. +`value`: allows to set the `value` attribute of an element. +`clone`: method that creates a clone of the element. NODE: The clone elements will not be +attached to any element. +`show_me`: method to scroll the page to where the element is placed. + + ## Workers Workers run code that won't block the "main thread" controlling the user From 8d3e4264485df71ccf40b659f12d3aaeae22d983 Mon Sep 17 00:00:00 2001 From: Fabio Pliger Date: Thu, 2 Nov 2023 12:16:06 -0500 Subject: [PATCH 041/201] fix minor text and add ElementCollection --- docs/user-guide.md | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/docs/user-guide.md b/docs/user-guide.md index 424911a..4762eec 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -922,7 +922,7 @@ The Standard Web APIs are massive and not always very user-friendly. `PyDom` is Python modue that exposes the power of the web with an easy and idiomatic Pythonic interface on top. -While the[FFI](#ffi) interface described above focuses on giving full access to +While the [FFI](#ffi) interface described above focuses on giving full access to the entire Standard Web APIs, `pydom` focuses on providing a small, intuitive and yet powerful API that priotirizes common use cases fist. For this reason, it's first layer is simple and intuitive (but limited to the most common use cases), but `pydom` @@ -1039,12 +1039,29 @@ new_p.style.visible = False ##### Other useful aspects of the Element API -`append`: method to append a new child to the element. -`children`: list of the children of the element. -`value`: allows to set the `value` attribute of an element. -`clone`: method that creates a clone of the element. NODE: The clone elements will not be +* `append`: method to append a new child to the element. +* `children`: list of the children of the element. +* `value`: allows to set the `value` attribute of an element. +* `clone`: method that creates a clone of the element. NODE: The clone elements will not be attached to any element. -`show_me`: method to scroll the page to where the element is placed. +* `show_me`: method to scroll the page to where the element is placed. + + +#### ElementCollection + +Element Collections represent a collection of elements typically returned from a query. For instance: + +```python +paragraphs = pydom['p'] +``` + +In the example above, `paragraphs` is an `ElementCollection` that maps to all `p` elements in the page. + + + +##### Interacting with an ElementCollection + +Interacting ## Workers From d126dc54ddf825777c29127ba513128139a88012 Mon Sep 17 00:00:00 2001 From: Fabio Pliger Date: Thu, 2 Nov 2023 12:31:24 -0500 Subject: [PATCH 042/201] add interacting with a collection --- docs/user-guide.md | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/docs/user-guide.md b/docs/user-guide.md index 4762eec..0fb32b1 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -1057,11 +1057,36 @@ paragraphs = pydom['p'] In the example above, `paragraphs` is an `ElementCollection` that maps to all `p` elements in the page. +As any collections, `ElementCollection` can be used to iterate over a collection of elements or to pick +specific elements or slices of elements in the collection. For instance: +```python +for element in paragraphs: + display(element.html) + +# let's now display only the last 2 elements +for element in paragraphs[-2:]: + display(element.html) +``` ##### Interacting with an ElementCollection -Interacting +Besides from allowing operations as an iterable object, `ElementCollection` objects also offer a few +convenient methods to directly interact with th elements in the collection. For instance, it's possible +to ask for specific attributes of the elements in the collection directly: + +```python +display(paragraphs.html) +``` + +The example above displays a list with the value of the `html` attribute for all the elements in the +`paragraphs` collection. + +The same way we can read attributes, we can also set an attribute directly in the collection. For instance: + +```python +paragraphs.html = "That's cool :)" +``` ## Workers From ddb721730324d0a2d3bcbed933a120de86f6bd61 Mon Sep 17 00:00:00 2001 From: Fabio Pliger Date: Thu, 2 Nov 2023 12:42:40 -0500 Subject: [PATCH 043/201] add Interacting with an ElementCollection --- docs/user-guide.md | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/docs/user-guide.md b/docs/user-guide.md index 0fb32b1..7e5f79e 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -1082,12 +1082,27 @@ display(paragraphs.html) The example above displays a list with the value of the `html` attribute for all the elements in the `paragraphs` collection. -The same way we can read attributes, we can also set an attribute directly in the collection. For instance: +The same way we can read attributes, we can also set an attribute directly in the collection. For instance, +you can directly set the html content of all the elements in the collection ```python -paragraphs.html = "That's cool :)" +# This will change the text of all H1 elements in the page +pydom['h1'].html = "That's cool :)" ``` +or perhaps change their style + +``` +paragraphs.style['background-color'] = 'lightyellow' +``` + +`ElementCollection` currently support the following attributes: + +* `style`: just like in `Element`, this proxy attribute can be used to change the style of the elements in +a collection by setting the proper CSS rules, using `style` with the same API as a dictionary. +* `html`: allows to change the `html` attribute on all the elements of a collection. +* `value`: allows to change the `value` attribute on all the elements of a collection. + ## Workers From 8dbd29b71aca0780a31d0c332efc443a22ae3253 Mon Sep 17 00:00:00 2001 From: Fabio Pliger Date: Thu, 2 Nov 2023 16:59:43 -0500 Subject: [PATCH 044/201] remove call for diagram --- docs/user-guide.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/user-guide.md b/docs/user-guide.md index 7e5f79e..68c73a8 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -966,8 +966,6 @@ Following, we'll look into each one of these aspects a bit more in detail. Every `Element` always maps to an underlying `JavaScript` `Element` in a web page. These 2 elements are always in sync and any change of state in one is reflect into the other. -__ADD DIAGRAM HERE__ - ##### Creating a new element New elements can be created by using the `pydom.create` method and passing the type of element From 2d5b0a5e7acd7c5b4657c5c44d43f8b2dbb35469 Mon Sep 17 00:00:00 2001 From: Fabio Pliger Date: Fri, 3 Nov 2023 08:58:05 -0500 Subject: [PATCH 045/201] remove one level on section titles --- docs/user-guide/dom.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/user-guide/dom.md b/docs/user-guide/dom.md index d05df22..6299542 100644 --- a/docs/user-guide/dom.md +++ b/docs/user-guide/dom.md @@ -69,7 +69,7 @@ equivalent values: `["hello", 1, 2, 3]`. class's `new` method PyScript both signals and honours this difference. -### PyDom +## PyDom The Standard Web APIs are massive and not always very user-friendly. `PyDom` is a Python modue that exposes the power of the web with an easy and idiomatic Pythonic @@ -97,7 +97,7 @@ easy to learn, and other successful projects related the web as well (for isntan We welcome feedback and suggestions. -#### Core Concepts +### Core Concepts `Pydom` builds on topic of very few and simple core concepts: @@ -113,13 +113,13 @@ standard HTML DOM query selectors to [locate DOM elements](https://developer.moz Following, we'll look into each one of these aspects a bit more in detail. -#### Element +### Element `pydom` `Element` is simply just an abstraction of a tranditional `Element` in a web page. Every `Element` always maps to an underlying `JavaScript` `Element` in a web page. These 2 elements are always in sync and any change of state in one is reflect into the other. -##### Creating a new element +#### Creating a new element New elements can be created by using the `pydom.create` method and passing the type of element being crated. Here's an example of what it looks like: @@ -149,7 +149,7 @@ pydom['#element-creation-example'][0].append(new_div) For more details about `pydom.create` please refer to its reference documentation. -##### Setting the content of an element +#### Setting the content of an element The Element interface offers 2 main ways to set an element content: the `html` and the `content` attributes: @@ -163,7 +163,7 @@ any conversion. In general, we suggest using `content` directly as it'll take care of most use cases without requiring any extra logic from the user. -##### Changing the element style +#### Changing the element style Elements have a `style` attribute that can be used to change the element style rules. The style attribyte can be used as a dictionary and, to set a style rule for the element, @@ -188,7 +188,7 @@ also offers a convenient `visible` property that can be use show/hide an element new_p.style.visible = False ``` -##### Other useful aspects of the Element API +#### Other useful aspects of the Element API * `append`: method to append a new child to the element. * `children`: list of the children of the element. @@ -198,7 +198,7 @@ attached to any element. * `show_me`: method to scroll the page to where the element is placed. -#### ElementCollection +### ElementCollection Element Collections represent a collection of elements typically returned from a query. For instance: @@ -220,7 +220,7 @@ for element in paragraphs[-2:]: display(element.html) ``` -##### Interacting with an ElementCollection +#### Interacting with an ElementCollection Besides from allowing operations as an iterable object, `ElementCollection` objects also offer a few convenient methods to directly interact with th elements in the collection. For instance, it's possible From 72d1e8572b1ce9e19e193ceb30a9f118f89c7283 Mon Sep 17 00:00:00 2001 From: Fabio Pliger Date: Tue, 7 Nov 2023 17:26:19 -0600 Subject: [PATCH 046/201] add warning about latest deprecation --- docs/user-guide/first-steps.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/user-guide/first-steps.md b/docs/user-guide/first-steps.md index 0b7a7e0..b46a1a0 100644 --- a/docs/user-guide/first-steps.md +++ b/docs/user-guide/first-steps.md @@ -30,6 +30,13 @@ CSS: ``` +!!! warning + + Since release `2023.11.1` the `https://pyscript/latest/` path has been deprecated and will be + completely removed from release >= `2023.12.x`. If you've been using `\latest` as a path we + highly encourage you to pin your application to a specific version to avoid breaking your + application. + There are two ways to tell PyScript how to find your code. * With a standard HTML ` + @@ -155,7 +155,7 @@ In the end, our HTML should look like this: Codestin Search App - +

Polyglot 🦜 💬 🇬🇧 ➡️ 🏴‍☠️

diff --git a/docs/javascripts/mini-coi.js b/docs/javascripts/mini-coi.js deleted file mode 100644 index b7a23bf..0000000 --- a/docs/javascripts/mini-coi.js +++ /dev/null @@ -1,28 +0,0 @@ -/*! coi-serviceworker v0.1.7 - Guido Zuidhof and contributors, licensed under MIT */ -/*! mini-coi - Andrea Giammarchi and contributors, licensed under MIT */ -(({ document: d, navigator: { serviceWorker: s } }) => { - if (d) { - const { currentScript: c } = d; - s.register(c.src, { scope: c.getAttribute('scope') || '.' }).then(r => { - r.addEventListener('updatefound', () => location.reload()); - if (r.active && !s.controller) location.reload(); - }); - } - else { - addEventListener('install', () => skipWaiting()); - addEventListener('activate', e => e.waitUntil(clients.claim())); - addEventListener('fetch', e => { - const { request: r } = e; - if (r.cache === 'only-if-cached' && r.mode !== 'same-origin') return; - e.respondWith(fetch(r).then(r => { - const { body, status, statusText } = r; - if (!status || status > 399) return r; - const h = new Headers(r.headers); - h.set('Cross-Origin-Opener-Policy', 'same-origin'); - h.set('Cross-Origin-Embedder-Policy', 'require-corp'); - h.set('Cross-Origin-Resource-Policy', 'cross-origin'); - return new Response(body, { status, statusText, headers: h }); - })); - }); - } -})(self); diff --git a/docs/user-guide/first-steps.md b/docs/user-guide/first-steps.md index 41515c4..9f48b1b 100644 --- a/docs/user-guide/first-steps.md +++ b/docs/user-guide/first-steps.md @@ -20,9 +20,9 @@ CSS: - + - + diff --git a/mkdocs.yml b/mkdocs.yml index 039c5c9..ff7ec16 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -8,8 +8,6 @@ theme: logo: assets/images/pyscript-black.svg - custom_dir: overrides - palette: # Palette toggle for automatic mode - media: "(prefers-color-scheme)" diff --git a/overrides/main.html b/overrides/main.html deleted file mode 100644 index 7f2577d..0000000 --- a/overrides/main.html +++ /dev/null @@ -1,11 +0,0 @@ -{% extends "base.html" %} - -{% block libs %} -{%- for script in config.extra_javascript %} - {{ script | script_tag }} -{%- endfor %} -{{ super() }} -{% endblock %} - -{% block scripts %} -{% endblock %} diff --git a/version.json b/version.json index 4ae6d7d..3e546ec 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2023.11.1.RC3" + "version": "2023.11.1" } From eb105420b187fed2d488fa835111975c48b6ba3c Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Fri, 10 Nov 2023 08:55:48 +0000 Subject: [PATCH 051/201] Remove extra JS. --- mkdocs.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index ff7ec16..18a9f35 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,8 +1,5 @@ site_name: PyScript -extra_javascript: - - javascripts/mini-coi.js - theme: name: material From 928d87da5223a73db951d169119c5f25c764faee Mon Sep 17 00:00:00 2001 From: Fabio Pliger Date: Fri, 10 Nov 2023 22:46:25 -0600 Subject: [PATCH 052/201] fix wrong link to release --- docs/user-guide/first-steps.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/user-guide/first-steps.md b/docs/user-guide/first-steps.md index 9f48b1b..b4707a0 100644 --- a/docs/user-guide/first-steps.md +++ b/docs/user-guide/first-steps.md @@ -20,9 +20,9 @@ CSS: - + - + From e91aa04340153d2dbc54d7863e14a793e28f3417 Mon Sep 17 00:00:00 2001 From: Fabio Pliger Date: Fri, 10 Nov 2023 22:48:53 -0600 Subject: [PATCH 053/201] replace missing wrong links --- docs/beginning-pyscript.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/beginning-pyscript.md b/docs/beginning-pyscript.md index cba4321..996fee4 100644 --- a/docs/beginning-pyscript.md +++ b/docs/beginning-pyscript.md @@ -106,7 +106,7 @@ module in the document's `` tag: Codestin Search App - + @@ -155,7 +155,7 @@ In the end, our HTML should look like this: Codestin Search App - +

Polyglot 🦜 💬 🇬🇧 ➡️ 🏴‍☠️

From b23d8078d587804136f7a873b7c730ce92b4aff7 Mon Sep 17 00:00:00 2001 From: Fabio Pliger Date: Tue, 14 Nov 2023 19:11:43 -0600 Subject: [PATCH 054/201] initial plugins docs content --- docs/user-guide/plugins.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md index 8a5d2ff..5c2e28b 100644 --- a/docs/user-guide/plugins.md +++ b/docs/user-guide/plugins.md @@ -1,3 +1,16 @@ # Plugins -** TODO: Finish this ** +PyScript, like many other software plaforms, offers a Plugin API that can be used to extend its +own functionality without the need to modify its own core. By using this API, users can add new +features and distribute them as plugins. + +At the moment, PyScript supports plugins written in Javascript. These plugins can use PyScript +Plugins API to define entry points and hooks so that the plugin can be collected and hook into +the PyScript lifecycle events, with the ablity to modify and integrate the features of PyScript +core itself. + +Here's an example of how a PyScript plugin looks like: + +```js + +``` \ No newline at end of file From ec1e7657efadf64ac1534038d28b5157b05eca41 Mon Sep 17 00:00:00 2001 From: Fabio Pliger Date: Tue, 14 Nov 2023 19:15:47 -0600 Subject: [PATCH 055/201] add plugin example --- docs/user-guide/plugins.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md index 5c2e28b..36c1cbe 100644 --- a/docs/user-guide/plugins.md +++ b/docs/user-guide/plugins.md @@ -12,5 +12,42 @@ core itself. Here's an example of how a PyScript plugin looks like: ```js +// import the hooks from PyScript first... +import { hooks } from "/core.js"; +// Use the `main` attribute on hooks do define plugins that run on the main thread +hooks.main.onReady.add((wrap, element) => { + console.log("main", "onReady"); + if (location.search === '?debug') { + console.debug("main", "wrap", wrap); + console.debug("main", "element", element); + } +}); +hooks.main.onBeforeRun.add(() => { + console.log("main", "onBeforeRun"); +}); +hooks.main.codeBeforeRun.add('print("main", "codeBeforeRun")'); +hooks.main.codeAfterRun.add('print("main", "codeAfterRun")'); +hooks.main.onAfterRun.add(() => { + console.log("main", "onAfterRun"); +}); + +// Use the `worker` attribute on hooks do define plugins that run on workers +hooks.worker.onReady.add((wrap, xworker) => { + console.log("worker", "onReady"); + if (location.search === '?debug') { + console.debug("worker", "wrap", wrap); + console.debug("worker", "xworker", xworker); + } +}); + +hooks.worker.onBeforeRun.add(() => { + console.log("worker", "onBeforeRun"); +}); + +hooks.worker.codeBeforeRun.add('print("worker", "codeBeforeRun")'); +hooks.worker.codeAfterRun.add('print("worker", "codeAfterRun")'); +hooks.worker.onAfterRun.add(() => { + console.log("worker", "onAfterRun"); +}); ``` \ No newline at end of file From 6cce635e0a711b2fd180c8662d5a6ae795685f2e Mon Sep 17 00:00:00 2001 From: Fabio Pliger Date: Tue, 14 Nov 2023 20:36:15 -0600 Subject: [PATCH 056/201] add plugins API intro and placeholder for concepts --- docs/user-guide/plugins.md | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md index 36c1cbe..4ffb393 100644 --- a/docs/user-guide/plugins.md +++ b/docs/user-guide/plugins.md @@ -1,5 +1,6 @@ # Plugins + PyScript, like many other software plaforms, offers a Plugin API that can be used to extend its own functionality without the need to modify its own core. By using this API, users can add new features and distribute them as plugins. @@ -50,4 +51,23 @@ hooks.worker.codeAfterRun.add('print("worker", "codeAfterRun")'); hooks.worker.onAfterRun.add(() => { console.log("worker", "onAfterRun"); }); -``` \ No newline at end of file +``` + +That's it. + + +## Plugins API + +As mentioned above, PyScript Plugins API exposes a set of hooks that can be used to intercept +specific events in the lifecycle of a PyScript application and add or modify specific features +of the platform itself. To better understand how it works it's important to understand the concepts +behind Plugins. + +### Concepts + +**TODO: ADD LIST OF CONCEPTS** + + + + +Here's a list of the available hooks: From 23ccf47665955a18c9e31bd93381567bb09631bb Mon Sep 17 00:00:00 2001 From: Fabio Pliger Date: Tue, 14 Nov 2023 21:47:27 -0600 Subject: [PATCH 057/201] add hooks section --- docs/user-guide/plugins.md | 119 +++++++++++++++++++++++++++++++++++-- 1 file changed, 115 insertions(+), 4 deletions(-) diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md index 4ffb393..d4ab093 100644 --- a/docs/user-guide/plugins.md +++ b/docs/user-guide/plugins.md @@ -61,13 +61,124 @@ That's it. As mentioned above, PyScript Plugins API exposes a set of hooks that can be used to intercept specific events in the lifecycle of a PyScript application and add or modify specific features of the platform itself. To better understand how it works it's important to understand the concepts -behind Plugins. +around a PyScript application and plugins. -### Concepts +### Code Execution Methods -**TODO: ADD LIST OF CONCEPTS** +There are 2 mains PyScript Applications can execute code: the browser main +[thread](https://developer.mozilla.org/en-US/docs/Glossary/Main_thread) and on +[web workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers). +We highly recommend users to independently search the difference between the 2 methods to fully understand +the difference and consequences but here's a short summary: +* main thread: executing code in the browser main thread means the code is being executed in the same +process where the browser processes user events and paints. By default, the browser uses this single thread +to run all the JavaScript code in your page, as well as to perform layout, reflows, and garbage collection. +This means that long-running code or blocking calls can or will block the thread, leading to an unresponsive +page and a bad user experience. +* web workers: code executed in workers actually run on "background" threads. This means the code can perform +tasks without interfering with the user interface or other operations being perfomed in the main thread. While +this adds great flexibility it's important to understand that workers actually have limited capabilities when +comparing to code executed on the main thread. For instace, while PyScript offers a DOM API that actually can +be used in web workers the browser, by default, does not allow DOM operation in workers. +In general, we recommend executing your code on workers unless there are explicit reasons preventing users from +doing that. -Here's a list of the available hooks: +### Lifecycle Events + +During the execution of a PyScript application there are specfic events that capture the beginning +or the end of specific stages. Here are the main lifecycle events of a PyScript Application: + +Every script or tag running through PyScript inevitably passes through some main or worker thread related tasks. + +In both worlds (wither executing code in the main thread or on a web worker), the exact sequence of steps around code execution is the following: + + * **ready** - the DOM recognized the special script or tag and the associated interpreter is ready to work. A *JS* callback might be useful to instrument the interpreter before anything else happens. + * **before run** - there could be some *JS* code setup specific for the script on the main thread, or the worker. This is similar to a generic *setup* callback in tests. + * **code before run** - there could be some *PL* code to prepend to the one being executed. In this case the code is a string because it will be part of the evaluation. + * **actual code** - the code in the script or tag or the `src` file specified in the script. This is not a hook, just the exact time the code gets executed in general. + * **code after run** - there could be some *PL* code to append to the one being executed. Same as *before*, the code is a string targeting the foreign *PL*. + * **after run** - there could be some *JS* to execute right after the whole code has been evaluated. This is similar to a generic *teardown* callback in tests. + +As most interpreters can run their code either *synchronously* or *asynchronously*, the very same sequence is guaranteed to run in order in both cases, and the difference is only around the naming convention [as we'll see below]. + +### Hooks + +Hooks are a especial mechanism that can be used to tell PyScript that your code wants to subscribe to specific events, allowing your code to get called +by PyScript's event loop when a specific event happens. + +#### Main Hooks + +When it comes to *main* hooks all callbacks will receive a *wrapper* of the interpreter with its utilities, see the further section to know more, plus the element on the page that is going to execute its related code, being this a custom script/type or a custom tag. + +This is the list of all possible, yet **optional** hooks, a custom type can define for **main**: + +| name | example | behavior | +| :------------------------ | :-------------------------------------------- | :-------- | +| onReady | `onReady(wrap:Wrap, el:Element) {}` | If defined, it is invoked before any other hook to signal that the element is going to execute the code. For custom scripts, this hook is in charge of eventually running the content of the script, anyway it prefers to do so. | +| onBeforeRun | `onBeforeRun(wrap:Wrap, el:Element) {}` | If defined, it is invoked before any other hook to signal that the element is going to execute the code. | +| onBeforeRunAsync | `onBeforeRunAsync(wrap:Wrap, el:Element) {}` | Same as `onBeforeRun` except it's the one used whenever the script is `async`. | +| codeBeforeRun | `codeBeforeRun: () => 'print("before")'` | If defined, prepend some code to evaluate right before the rest of the code gets executed. | +| codeBeforeRunAsync | `codeBeforeRunAsync: () => 'print("before")'` | Same as `codeBeforeRun` except it's the one used whenever the script is `async`. | +| codeAfterRun | `codeAfterRun: () => 'print("after")'` | If defined, append some code to evaluate right after the rest of the code already executed. | +| codeAfterRunAsync | `codeAfterRunAsync: () => 'print("after")'` | Same as `codeAfterRun` except it's the one used whenever the script is `async`. | +| onAfterRun | `onAfterRun(wrap:Wrap, el:Element) {}` | If defined, it is invoked after the foreign code has been executed already. | +| onAfterRunAsync | `onAfterRunAsync(wrap:Wrap, el:Element) {}` | Same as `onAfterRun` except it's the one used whenever the script is `async`. | +| onWorker | `onWorker(wrap = null, xworker) {}` | If defined, whenever a script or tag with a `worker` attribute is processed it gets triggered on the main thread, to allow to expose possible `xworker` features before the code gets executed within the worker thread. The `wrap` reference is most of the time `null` unless an explicit `XWorker` call has been initialized manually and/or there is an interpreter on the main thread (*very advanced use case*). Please **note** this is the only hook that doesn't exist in the *worker* counter list of hooks. | + +#### Worker Hooks + +When it comes to *worker* hooks, **all non code related callbacks must be serializable**, meaning that callbacks cannot use any outer scope reference, as these are forwarded as strings, hence evaluated after in the worker, to survive the main <-> worker `postMessage` dance. + +Here an example of what works and what doesn't: + +```js +// this works 👍 +define('pl', { + interpreter: 'programming-lang', + hooks: { + worker: { + onReady() { + // NOT suggested, just as example! + if (!('i' in globalThis)) + globalThis.i = 0; + console.log(++i); + } + } + } +}); + +// this DOES NOT WORK ⚠️ +let i = 0; +define('pl', { + interpreter: 'programming-lang', + hooks: { + worker: { + onReady() { + // that outer-scope `i` is nowhere understood + // whenever this code executes in the worker + // as this function gets stringified and re-evaluated + console.log(++i); + } + } + } +}); +``` + +At the same time, as the worker doesn't have any `element` strictly related, as workers can be created also procedurally, the second argument won't be an element but the related *xworker* that is driving the logic. + +As summary, this is the list of all possible, yet **optional** hooks, a custom type can define for **worker**: + +| name | example | behavior | +| :------------------------ | :-------------------------------------------- | :--------| +| onReady | `onReady(wrap:Wrap, xw:XWorker) {}` | If defined, it is invoked before any other hook to signal that the xworker is going to execute the code. Differently from **main**, the code here is already known so all other operations will be performed automatically. | +| onBeforeRun | `onBeforeRun(wrap:Wrap, xw:XWorker) {}` | If defined, it is invoked before any other hook to signal that the xworker is going to execute the code. | +| onBeforeRunAsync | `onBeforeRunAsync(wrap:Wrap, xw:XWorker) {}` | Same as `onBeforeRun` except it's the one used whenever the worker script is `async`. | +| codeBeforeRun | `codeBeforeRun: () => 'print("before")'` | If defined, prepend some code to evaluate right before the rest of the code gets executed. | +| codeBeforeRunAsync | `codeBeforeRunAsync: () => 'print("before")'` | Same as `codeBeforeRun` except it's the one used whenever the worker script is `async`. | +| codeAfterRun | `codeAfterRun: () => 'print("after")'` | If defined, append some code to evaluate right after the rest of the code already executed. | +| codeAfterRunAsync | `codeAfterRunAsync: () => 'print("after")'` | Same as `codeAfterRun` except it's the one used whenever the worker script is `async`. | +| onAfterRun | `onAfterRun(wrap:Wrap, xw:XWorker) {}` | If defined, it is invoked after the foreign code has been executed already. | +| onAfterRunAsync | `onAfterRunAsync(wrap:Wrap, xw:XWorker) {}` | Same as `onAfterRun` except it's the one used whenever the worker script is `async`. | From 49d69ab8ccab171b36a9a27e144d7c10440c74b2 Mon Sep 17 00:00:00 2001 From: Fabio Pliger Date: Wed, 15 Nov 2023 10:16:31 -0600 Subject: [PATCH 058/201] expand on the DOM api we support in workers --- docs/user-guide/plugins.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md index d4ab093..a4ecaff 100644 --- a/docs/user-guide/plugins.md +++ b/docs/user-guide/plugins.md @@ -81,7 +81,10 @@ page and a bad user experience. tasks without interfering with the user interface or other operations being perfomed in the main thread. While this adds great flexibility it's important to understand that workers actually have limited capabilities when comparing to code executed on the main thread. For instace, while PyScript offers a DOM API that actually can -be used in web workers the browser, by default, does not allow DOM operation in workers. +be used in web workers on the browser, by default, does not allow DOM operation in workers. So, in this case, +if you just use `window` and `document` directly mapping the Javascript FFI provided directly by the interpreters +we support (Pyodide and MicroPython): `from pyscript import window, document` will work and allow you to interact +with the DOM while `from js import window, document` will not. In general, we recommend executing your code on workers unless there are explicit reasons preventing users from doing that. From cf3fe61d46f364ae22e98040ad2e0e08a8b7a61c Mon Sep 17 00:00:00 2001 From: Fabio Pliger Date: Wed, 15 Nov 2023 10:19:11 -0600 Subject: [PATCH 059/201] change path to the actuall CDN path --- docs/user-guide/plugins.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md index a4ecaff..5099e33 100644 --- a/docs/user-guide/plugins.md +++ b/docs/user-guide/plugins.md @@ -14,7 +14,7 @@ Here's an example of how a PyScript plugin looks like: ```js // import the hooks from PyScript first... -import { hooks } from "/core.js"; +import { hooks } from "https://pyscript.net/releases/2023.11.1/core.js"; // Use the `main` attribute on hooks do define plugins that run on the main thread hooks.main.onReady.add((wrap, element) => { From 30914ef4c3ab2e8eeed66a675a1a57ca60a62dae Mon Sep 17 00:00:00 2001 From: Fabio Pliger Date: Wed, 15 Nov 2023 10:38:10 -0600 Subject: [PATCH 060/201] rephrase examples of what works with web workers and what doesn't --- docs/user-guide/plugins.md | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md index 5099e33..dd35864 100644 --- a/docs/user-guide/plugins.md +++ b/docs/user-guide/plugins.md @@ -83,8 +83,28 @@ this adds great flexibility it's important to understand that workers actually h comparing to code executed on the main thread. For instace, while PyScript offers a DOM API that actually can be used in web workers on the browser, by default, does not allow DOM operation in workers. So, in this case, if you just use `window` and `document` directly mapping the Javascript FFI provided directly by the interpreters -we support (Pyodide and MicroPython): `from pyscript import window, document` will work and allow you to interact -with the DOM while `from js import window, document` will not. +we support (Pyodide and MicroPython). With that in mind, `from pyscript import window, document` will work and +allow you to interact with the DOM while the following will not: + +``` +from js import document, window +``` + +or + +``` +import js +js.document +``` + +or + +``` +import js +js.window +``` + +will not. In general, we recommend executing your code on workers unless there are explicit reasons preventing users from doing that. From 4630e142bec53d246bcc37b5b1c243b6f8446b99 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Wed, 29 Nov 2023 15:14:39 +0000 Subject: [PATCH 061/201] Bump version to 2023-11-2 --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index 3e546ec..58149c6 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2023.11.1" + "version": "2023.11.2" } From c5bae4b8216ba8dcc33bcc72d6d10ced3b06a837 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Wed, 29 Nov 2023 15:18:01 +0000 Subject: [PATCH 062/201] Update in-doc based references to 2023-11-2 where appropriate. --- docs/beginning-pyscript.md | 4 ++-- docs/user-guide/first-steps.md | 4 ++-- docs/user-guide/plugins.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/beginning-pyscript.md b/docs/beginning-pyscript.md index 996fee4..9fd002a 100644 --- a/docs/beginning-pyscript.md +++ b/docs/beginning-pyscript.md @@ -106,7 +106,7 @@ module in the document's `` tag: Codestin Search App - + @@ -155,7 +155,7 @@ In the end, our HTML should look like this: Codestin Search App - +

Polyglot 🦜 💬 🇬🇧 ➡️ 🏴‍☠️

diff --git a/docs/user-guide/first-steps.md b/docs/user-guide/first-steps.md index b4707a0..b432f87 100644 --- a/docs/user-guide/first-steps.md +++ b/docs/user-guide/first-steps.md @@ -20,9 +20,9 @@ CSS: - + - + diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md index dd35864..c5ec6d2 100644 --- a/docs/user-guide/plugins.md +++ b/docs/user-guide/plugins.md @@ -14,7 +14,7 @@ Here's an example of how a PyScript plugin looks like: ```js // import the hooks from PyScript first... -import { hooks } from "https://pyscript.net/releases/2023.11.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2023.11.2/core.js"; // Use the `main` attribute on hooks do define plugins that run on the main thread hooks.main.onReady.add((wrap, element) => { From 2f039266d475ce58d28a79cfe0b254780ba2e976 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Thu, 30 Nov 2023 14:00:06 +0000 Subject: [PATCH 063/201] Add docs about the new js_modules settings. --- docs/user-guide/builtins.md | 12 +++++ docs/user-guide/configuration.md | 86 ++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/docs/user-guide/builtins.md b/docs/user-guide/builtins.md index 93120e8..4c6907d 100644 --- a/docs/user-guide/builtins.md +++ b/docs/user-guide/builtins.md @@ -94,6 +94,18 @@ def click_handler(event): display("I've been clicked!") ``` +### `pyscript.js_modules` + +It is possible to [define JavaScript modules to use within your Python code](configuration.md#javascript-modules). + +Such named modules will always then be available under the +`pyscript.js_modules` namespace. + +!!! warning + + Please see the documentation (linked above) about restrictions and gotchas + when configuring how JavaScript modules are made available to PyScript. + ## Main-thread only features ### `pyscript.PyWorker` diff --git a/docs/user-guide/configuration.md b/docs/user-guide/configuration.md index b6c2462..ace0b01 100644 --- a/docs/user-guide/configuration.md +++ b/docs/user-guide/configuration.md @@ -309,6 +309,92 @@ plugins = ["custom_plugin", "!error"] stack trace and error messages in the DOM. More may be added at a later date. +### JavaScript modules + +It's easy to import and use JavaScript modules in your Python code. + +To do so, requires telling PyScript about the JavaScript modules you want to +use. This is the purpose of the `js_modules` related configuration fields. + +There are two fields: + +* `js_modules.main` defines JavaScript modules loaded in the context of the + main thread of the browser. Helpfully, it is also possible to interact with + such modules **from the context of workers**. Sometimes such modules also + need CSS files to work, and these can also be specified. +* `js_modules.worker` defines JavaScript modules loaded into the context of + the web worker. Such modules **must not expect** `document` or `window` + references (if this is the case,you must load them via `js_modules.main` and + use them from the worker). However, if the JavaScript module could work + without such references, then performance is better if defined on a worker. + Because CSS is meaningless in the context of a worker, it is not possible to + specify such files in a worker context. + +Once specified, your JavaScript modules will be available under the +`pyscript.js_modules.*` namespace. + +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" +[js_modules.main] +"https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet-src.esm.js" = "leaflet" +"https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.css" = "leaflet" # CSS +``` + +```JSON title="JavaScript main thread modules defined in JSON" +{ + "js_modules.main": { + "https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet-src.esm.js": "leaflet", + "https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.css": "leaflet" + } +} +``` + +!!! info + + Notice how the second line references the required CSS needed for the + JavaScript module to work correctly. + + The CSS file **MUST** target the very same name as the JavaScript module to + which it is related. + +!!! warning + + Since the Leaflet module expects to manipulate the DOM and have access to + `document` and `window` references, **it must only be added via the + `js_modules.main` setting** (as shown) and cannot be added in a worker + context. + +At this point Python code running on either the main thread or in a +worker will have access to the JavaScript module like this: + +```python title="Making use of a JavaScript module from within Python." +from pyscript.js_modules import leaflet as L + +map = L.map("map") + +# etc.... +``` + +Some JavaScript modules (such as +[html-escaper](https://www.npmjs.com/package/html-escaper)) don't require +access to the DOM and, for efficiency reasons, can be included in the worker +context: + +```JSON title="A JavaScript worker module defined in JSON" +{ + "js_modules.worker": { + "https://cdn.jsdelivr.net/npm/html-escaper": "html_escaper" + } +} +``` + +However, `from polyscript.js_modules import html_escaper` would then only work +within the context of Python code **running on a worker**. + ### Custom Sometimes plugins or apps need bespoke configuration options. From ceacdb85493efdf130d50357476589fbbb477428 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Thu, 7 Dec 2023 11:16:16 +0000 Subject: [PATCH 064/201] Fix broken links, add documentation updates. --- docs/beginning-pyscript.md | 3 +- docs/index.md | 8 ++-- docs/user-guide/architecture.md | 2 +- docs/user-guide/builtins.md | 66 ++++++++++++++++++++++++++++++-- docs/user-guide/configuration.md | 7 ++-- docs/user-guide/features.md | 14 +++---- 6 files changed, 81 insertions(+), 19 deletions(-) diff --git a/docs/beginning-pyscript.md b/docs/beginning-pyscript.md index 9fd002a..d75abb2 100644 --- a/docs/beginning-pyscript.md +++ b/docs/beginning-pyscript.md @@ -139,7 +139,8 @@ application's output. There's something strange about the ` ``` +These APIs will work with both Pyodide and Micropython in exactly the same way. + +!!! info + + Both Pyodide and MicroPython provide access to two further lower-level + APIs: + + * Access to + [JavaScript's `globalThis`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis) + via importing the `js` module: `import js` (now `js` is a proxy for + `globalThis` in which all native JavaScript based browser APIs are + found). + * Access to interpreter specific versions of utilities and the foreign + function interface. Since these are different for each interpreter, and + beyond the scope of PyScript's own documentation, please check each + project's documentation + ([Pyodide](https://pyodide.org/en/stable/usage/api-reference.html) / + [MicroPython](https://docs.micropython.org/en/latest/)) for details of + these lower-level APIs. + +PyScript can run in two contexts: the main browser thread, or on a web worker. +The following three categories of API functionality explain features that are +common for both main thread and worker, main thread only, and worker only. Most +features work in both contexts in exactly the same manner, but please be aware +that some are specific to either the main thread or a worker context. + ## Common features These Python objects / functions are available in both the main thread and in code running on a web worker: -### `pyscript.window` +### `pyscript.config` -On the main thread, this object is exactly the same as `import js` which, in -turn, is a proxy of JavaScript's -[globalThis](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis) -object. +A Python dictionary representing the configuration for the interpreter. + +```python title="Reading the current configuration." +from pyscript import config -On a worker thread, this object is a proxy for the web page's -[global window context](https://developer.mozilla.org/en-US/docs/Web/API/Window). + +# It's just a dict. +print(config.get("files")) +``` !!! warning - The reference for `pyscript.window` is **always** a reference to the main - thread's global window context. + Changing the `config` dictionary at runtime has no effect on the actual + configuration. - If you're running code in a worker this is **not the worker's own global - context**. A worker's global context is always reachable via `import js` - (the `js` object being a proxy for the worker's `globalThis`). + It's just a convenience to **read the configuration** at run time. -### `pyscript.document` +### `pyscript.current_target` -On both main and worker threads, this object is a proxy for the web page's -[document object](https://developer.mozilla.org/en-US/docs/Web/API/Document). -The `document` is a representation of the -[DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_object_model/Using_the_Document_Object_Model) -and can be used to read or manipulate the content of the web page. +A utility function to retrieve the unique identifier of the element used +to display content. If the element is not a ` +``` + +!!! Note + + The return value of `current_target()` always references a visible element + on the page, **not** at the current ` + ``` + + Then use the standard `document.getElementById(script_id)` function to + return a reference to it in your code. ### `pyscript.display` @@ -118,54 +181,13 @@ There are some caveats:

``` -### `pyscript.when` - -A Python decorator to indicate the decorated function should handle the -specified events for selected elements. - -The decorator takes two parameters: - -* The `event_type` should be the name of the - [browser event to handle](https://developer.mozilla.org/en-US/docs/Web/Events) - as a string (e.g. `"click"`). -* The `selector` should be a string containing a - [valid selector](https://developer.mozilla.org/en-US/docs/Web/API/Document_object_model/Locating_DOM_elements_using_selectors) - to indicate the target elements in the DOM whose events of `event_type` are - of interest. - -The following example has a button with an id of `my_button` and a decorated -function that handles `click` events dispatched by the button. - -```html title="The HTML button" - -``` - -```python title="The decorated Python function to handle click events" -from pyscript import when, display - - -@when("click", "#my_button") -def click_handler(event): - """ - Event handlers get an event object representing the activity that raised - them. - """ - display("I've been clicked!") -``` - -This functionality is related to the `py-*` or `mpy-*` [HTML attributes](#html-attributes). - -### `pyscript.js_modules` - -It is possible to [define JavaScript modules to use within your Python code](configuration.md#javascript-modules). - -Such named modules will always then be available under the -`pyscript.js_modules` namespace. - -!!! warning +### `pyscript.document` - Please see the documentation (linked above) about restrictions and gotchas - when configuring how JavaScript modules are made available to PyScript. +On both main and worker threads, this object is a proxy for the web page's +[document object](https://developer.mozilla.org/en-US/docs/Web/API/Document). +The `document` is a representation of the +[DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_object_model/Using_the_Document_Object_Model) +and can be used to read or manipulate the content of the web page. ### `pyscript.fetch` @@ -257,120 +279,63 @@ result = await fetch("https://example.com", method="POST", body="HELLO").text() bug). However, you could use a pass-through proxy service to get around this limitation (i.e. the proxy service makes the call on your behalf). -### `pyscript.WebSocket` - -If a `pyscript.fetch` results in a call and response HTTP interaction with a -web server, the `pyscript.Websocket` class provides a way to use -[websockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) -for two-way sending and receiving of data via a long term connection with a -web server. - -PyScript's implementation, available in both the main thread and a web worker, -closely follows the browser's own -[WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) class. - -This class accepts the following named arguments: - -* A `url` pointing at the _ws_ or _wss_ address. E.g.: - `WebSocket(url="ws://localhost:5037/")` -* Some `protocols`, an optional string or a list of strings as - [described here](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/WebSocket#parameters). - -The `WebSocket` class also provides these convenient static constants: - -* `WebSocket.CONNECTING` (`0`) - the `ws.readyState` value when a web socket - has just been created. -* `WebSocket.OPEN` (`1`) - the `ws.readyState` value once the socket is open. -* `WebSocket.CLOSING` (`2`) - the `ws.readyState` after `ws.close()` is - explicitly invoked to stop the connection. -* `WebSocket.CLOSED` (`3`) - the `ws.readyState` once closed. - -A `WebSocket` instance has only 2 methods: +### `pyscript.ffi` -* `ws.send(data)` - where `data` is either a string or a Python buffer, - automatically converted into a JavaScript typed array. This sends data via - the socket to the connected web server. -* `ws.close(code=0, reason="because")` - which optionally accepts `code` and - `reason` as named arguments to signal some specific status or cause for - closing the web socket. Otherwise `ws.close()` works with the default - standard values. +The `pyscript.ffi` namespace contains foreign function interface (FFI) methods +that work in both Pyodide and MicroPython. -A `WebSocket` instance also has the fields that the JavaScript -`WebSocket` instance will have: +#### `pyscript.ffi.create_proxy` -* [binaryType](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/binaryType) - - the type of binary data being received over the WebSocket connection. -* [bufferedAmount](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/bufferedAmount) - - a read-only property that returns the number of bytes of data that have been - queued using calls to `send()` but not yet transmitted to the network. -* [extensions](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/extensions) - - a read-only property that returns the extensions selected by the server. -* [protocol](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/protocol) - - a read-only property that returns the name of the sub-protocol the server - selected. -* [readyState](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState) - - a read-only property that returns the current state of the WebSocket - connection as one of the `WebSocket` static constants (`CONNECTING`, `OPEN`, - etc...). -* [url](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/url) - - a read-only property that returns the absolute URL of the `WebSocket` - instance. +A utility function explicitly for when a callback function is added via an +event listener. It ensures the function still exists beyond the assignment of +the function to an event. Should you not `create_proxy` around the callback +function, it will be immediately garbage collected after being bound to the +event. -A `WebSocket` instance can have the following listeners. Directly attach -handler functions to them. Such functions will always receive a single -`event` object. +!!! warning -* [onclose](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close_event) - - fired when the `WebSocket`'s connection is closed. -* [onerror](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/error_event) - - fired when the connection is closed due to an error. -* [onmessage](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/message_event) - - fired when data is received via the `WebSocket`. If the `event.data` is a - JavaScript typed array instead of a string, the reference it will point - directly to a _memoryview_ of the underlying `bytearray` data. -* [onopen](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/open_event) - - fired when the connection is opened. + There is some technical complexity to this situation, and we have attempted + to create a mechanism where `create_proxy` is never needed. -The following code demonstrates a `pyscript.WebSocket` in action. + *Pyodide* expects the created proxy to be explicitly destroyed when it's + not needed / used anymore. However, the underlying `proxy.destroy()` method + has not been implemented in *MicroPython* (yet). -```html - -``` +#### `pyscript.ffi.to_js` -!!! info +A utility function to convert Python references into their JavaScript +equivalents. For example, a Python dictionary is converted into a JavaScript +object literal (rather than a JavaScript `Map`), unless a `dict_converter` +is explicitly specified and the runtime is Pyodide. - It's also possible to pass in any handler functions as named arguments when - you instantiate the `pyscript.WebSocket` class: +The technical details of how this works are [described here](../user-guide/ffi#to_js). - ```python - from pyscript import WebSocket +### `pyscript.js_modules` +It is possible to [define JavaScript modules to use within your Python code](../user-guide/configuration#javascript-modules). - def onmessage(event): - print(event.type, event.data) - ws.close() +Such named modules will always then be available under the +`pyscript.js_modules` namespace. +!!! warning - ws = WebSocket(url="ws://example.com/socket", onmessage=onmessage) - ``` + Please see the documentation (linked above) about restrictions and gotchas + when configuring how JavaScript modules are made available to PyScript. ### `pyscript.storage` @@ -446,110 +411,169 @@ store = await storage("my-data-store", storage_class=MyStorage) # The store object is now an instance of MyStorage. ``` -### `pyscript.ffi.to_js` +### `pyscript.web` -A utility function to convert Python references into their JavaScript -equivalents. For example, a Python dictionary is converted into a JavaScript -object literal (rather than a JavaScript `Map`), unless a `dict_converter` -is explicitly specified and the runtime is Pyodide. +The classes and references in this namespace provide a Pythonic way to interact +with the DOM. An explanation for how to idiomatically use this API can be found +[in the user guide](../user-guide/dom/#pyscriptweb) -The technical details of how this works are [described here](../ffi#to_js). +#### `pyscript.web.dom` -### `pyscript.ffi.create_proxy` +This object has two attributes and a single method: -A utility function explicitly for when a callback function is added via an -event listener. It ensures the function still exists beyond the assignment of -the function to an event. Should you not `create_proxy` around the callback -function, it will be immediately garbage collected after being bound to the -event. +* `head` - a reference to a Python object representing the [document's head](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head). +* `body` - a reference to a Python object representing the [document's body](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/body). +* `find` - a method that takes a single [selector](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_selectors) + argument and returns a collection of matching elements. -!!! warning +You have several options for accessing the - There is some technical complexity to this situation, and we have attempted - to create a mechanism where `create_proxy` is never needed. +#### `pyscript.web.elements.*` - *Pyodide* expects the created proxy to be explicitly destroyed when it's - not needed / used anymore. However, the underlying `proxy.destroy()` method - has not been implemented in *MicroPython* (yet). +There are many classes in this namespace. Each is a one-to-one mapping of any +HTML element name for a Python class representing the HTML element of that +name. Each Python class ensures only valid properties and attributes can be +assigned, according to web standards. - To simplify this situation and automatically destroy proxies based on - JavaScript memory management (garbage collection) heuristics, we have - introduced an **experimental flag**: +Usage of these classes is +[explained in the user guide](../user-guide/dom/#pyscriptweb). - ```toml - experimental_create_proxy = "auto" - ``` +!!! info - This flag ensures the proxy creation and destruction process is managed for - you. When using this flag you should never need to explicitly call - `create_proxy`. + The full list of supported element/class names is: -The technical details of how this works are -[described here](../ffi#create_proxy). + ``` + grid + a, abbr, address, area, article, aside, audio + b, base, blockquote, body, br, button + canvas, caption, cite, code, col, colgroup + data, datalist, dd, del_, details, dialog, div, dl, dt + em, embed + fieldset, figcaption, figure, footer, form + h1, h2, h3, h4, h5, h6, head, header, hgroup, hr, html + i, iframe, img, input_, ins + kbd + label, legend, li, link + main, map_, mark, menu, meta, meter + nav + object_, ol, optgroup, option, output + p, param, picture, pre, progress + q + s, script, section, select, small, source, span, strong, style, sub, summary, sup + table, tbody, td, template, textarea, tfoot, th, thead, time, title, tr, track + u, ul + var, video + wbr + ``` + + These correspond to the standard + [HTML elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Element) + with the caveat that `del_` and `input_` have the trailing underscore + (`_`) because they are also keywords in Python, and the `grid` is a custom + class for a `div` with a `grid` style `display` property. + +In addition to properties defined by the HTML standard for each type of HTML +element (e.g. `title`, `src` or `href`), all elements have the following +properties and methods (in alphabetical order): + +* `append(child)` - add the `child` element to the element's children. +* `children` - a collection containing the element's child elements (that it + contains). +* `classes` - a set of CSS classes associated with the element. +* `clone(clone_id=None)` - Make a clone of the element (and the underlying DOM + object), and assign it the optional `clone_id`. +* `content` - get or set the + [innerHTML](https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML) + of the element. +* `find(selector)` - use a CSS selector to find matching child elements. +* `parent` - the element's parent element (that contains it). +* `show_me` - scroll the element into view. +* `style` - a dictionary of CSS style properties associated with the element. +* `update(classes=None, style=None, **kwargs)` - update the element with the + specified classes (set), style (dict) and DOM properties (kwargs). + +The `classes` set-like object has the following convenience functions: + +* `add(*class_names)` - add the class(es) to the element. +* `contains(class_name)` - indicate if `class_name` is associated with the + element. +* `remove(*class_names)` - remove the class(es) from the element. +* `replace(old_class, new_class)` - replace the `old_class` with `new_class`. +* `toggle(class_name)` - add a class if it is absent, or remove a class if it + is present. +* `_dom_element` - a reference to the proxy object that represents the + underlying HTML element. + +Finally, the collection of elements returned by `find` and `children` is +iterable, indexable and sliceable: -### `pyscript.current_target` +```python +for child in my_element.children[10:]: + print(child.html) +``` -A utility function to retrieve the unique identifier of the element used -to display content. If the element is not a ` -``` +A Python decorator to indicate the decorated function should handle the +specified events for selected elements. -!!! Note +The decorator takes two parameters: - The return value of `current_target()` always references a visible element - on the page, **not** at the current ` - ``` +```html title="The HTML button" + +``` - Then use the standard `document.getElementById(script_id)` function to - return a reference to it in your code. +```python title="The decorated Python function to handle click events" +from pyscript import when, display -### `pyscript.config` -A Python dictionary representing the configuration for the interpreter. +@when("click", "#my_button") +def click_handler(event): + """ + Event handlers get an event object representing the activity that raised + them. + """ + display("I've been clicked!") +``` -```python title="Reading the current configuration." -from pyscript import config +This functionality is related to the `py-*` or `mpy-*` [HTML attributes](#html-attributes). +### `pyscript.window` -# It's just a dict. -print(config.get("files")) -``` +On the main thread, this object is exactly the same as `import js` which, in +turn, is a proxy of JavaScript's +[globalThis](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis) +object. + +On a worker thread, this object is a proxy for the web page's +[global window context](https://developer.mozilla.org/en-US/docs/Web/API/Window). !!! warning - Changing the `config` dictionary at runtime has no effect on the actual - configuration. + The reference for `pyscript.window` is **always** a reference to the main + thread's global window context. - It's just a convenience to **read the configuration** at run time. + If you're running code in a worker this is **not the worker's own global + context**. A worker's global context is always reachable via `import js` + (the `js` object being a proxy for the worker's `globalThis`). ### `pyscript.HTML` @@ -576,6 +600,121 @@ A class to wrap generic content and display it as un-escaped HTML on the page. This constant flag is `True` when the current code is running within a *worker*. It is `False` when the code is running within the *main* thread. +### `pyscript.WebSocket` + +If a `pyscript.fetch` results in a call and response HTTP interaction with a +web server, the `pyscript.Websocket` class provides a way to use +[websockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) +for two-way sending and receiving of data via a long term connection with a +web server. + +PyScript's implementation, available in both the main thread and a web worker, +closely follows the browser's own +[WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) class. + +This class accepts the following named arguments: + +* A `url` pointing at the _ws_ or _wss_ address. E.g.: + `WebSocket(url="ws://localhost:5037/")` +* Some `protocols`, an optional string or a list of strings as + [described here](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/WebSocket#parameters). + +The `WebSocket` class also provides these convenient static constants: + +* `WebSocket.CONNECTING` (`0`) - the `ws.readyState` value when a web socket + has just been created. +* `WebSocket.OPEN` (`1`) - the `ws.readyState` value once the socket is open. +* `WebSocket.CLOSING` (`2`) - the `ws.readyState` after `ws.close()` is + explicitly invoked to stop the connection. +* `WebSocket.CLOSED` (`3`) - the `ws.readyState` once closed. + +A `WebSocket` instance has only 2 methods: + +* `ws.send(data)` - where `data` is either a string or a Python buffer, + automatically converted into a JavaScript typed array. This sends data via + the socket to the connected web server. +* `ws.close(code=0, reason="because")` - which optionally accepts `code` and + `reason` as named arguments to signal some specific status or cause for + closing the web socket. Otherwise `ws.close()` works with the default + standard values. + +A `WebSocket` instance also has the fields that the JavaScript +`WebSocket` instance will have: + +* [binaryType](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/binaryType) - + the type of binary data being received over the WebSocket connection. +* [bufferedAmount](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/bufferedAmount) - + a read-only property that returns the number of bytes of data that have been + queued using calls to `send()` but not yet transmitted to the network. +* [extensions](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/extensions) - + a read-only property that returns the extensions selected by the server. +* [protocol](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/protocol) - + a read-only property that returns the name of the sub-protocol the server + selected. +* [readyState](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState) - + a read-only property that returns the current state of the WebSocket + connection as one of the `WebSocket` static constants (`CONNECTING`, `OPEN`, + etc...). +* [url](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/url) - + a read-only property that returns the absolute URL of the `WebSocket` + instance. + +A `WebSocket` instance can have the following listeners. Directly attach +handler functions to them. Such functions will always receive a single +`event` object. + +* [onclose](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close_event) - + fired when the `WebSocket`'s connection is closed. +* [onerror](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/error_event) - + fired when the connection is closed due to an error. +* [onmessage](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/message_event) - + fired when data is received via the `WebSocket`. If the `event.data` is a + JavaScript typed array instead of a string, the reference it will point + directly to a _memoryview_ of the underlying `bytearray` data. +* [onopen](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/open_event) - + fired when the connection is opened. + +The following code demonstrates a `pyscript.WebSocket` in action. + +```html + +``` + +!!! info + + It's also possible to pass in any handler functions as named arguments when + you instantiate the `pyscript.WebSocket` class: + + ```python + from pyscript import WebSocket + + + def onmessage(event): + print(event.type, event.data) + ws.close() + + + ws = WebSocket(url="ws://example.com/socket", onmessage=onmessage) + ``` + ## Main-thread only features ### `pyscript.PyWorker` @@ -620,30 +759,23 @@ PyWorker("worker.py", type="micropython") ## Worker only features -### `pyscript.sync` - -A function used to pass serializable data from workers to the main thread. +### `pyscript.js_import` -Imagine you have this code on the main thread: +If a JavaScript module is only needed under certain circumstances, we provide +an asynchronous way to import packages that were not originally referenced in +your configuration. -```python title="Python code on the main thread" -from pyscript import PyWorker +```html title="A pyscript.js_import example." + + + @@ -163,8 +163,8 @@ In the end, our HTML should look like this: Codestin Search App - - + +

Polyglot 🦜 💬 🇬🇧 ➡️ 🏴‍☠️

diff --git a/docs/user-guide/first-steps.md b/docs/user-guide/first-steps.md index 36520f5..1c78a3c 100644 --- a/docs/user-guide/first-steps.md +++ b/docs/user-guide/first-steps.md @@ -20,9 +20,9 @@ CSS: - + - + diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md index 1b49f66..3fea9be 100644 --- a/docs/user-guide/plugins.md +++ b/docs/user-guide/plugins.md @@ -99,7 +99,7 @@ For example, this will work because all references are contained within the registered function: ```js -import { hooks } from "https://pyscript.net/releases/2024.6.2/core.js"; +import { hooks } from "https://pyscript.net/releases/2024.7.1/core.js"; hooks.worker.onReady.add(() => { // NOT suggested, just an example! @@ -113,7 +113,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/2024.6.2/core.js"; +import { hooks } from "https://pyscript.net/releases/2024.7.1/core.js"; // NO NO NO NO NO! ☠️ let i = 0; @@ -146,7 +146,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/2024.6.2/core.js"; +import { hooks } from "https://pyscript.net/releases/2024.7.1/core.js"; // The `hooks.main` attribute defines plugins that run on the main thread. hooks.main.onReady.add((wrap, element) => { @@ -196,8 +196,8 @@ hooks.worker.onAfterRun.add(() => { - - + + + Codestin Search App diff --git a/version.json b/version.json index f7ef6ba..fe19b81 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2024.6.2" + "version": "2024.7.1" } From ad42cc0eefa3bb2a2e212268ca0143df15cec8e7 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Thu, 4 Jul 2024 11:34:31 +0100 Subject: [PATCH 141/201] Updated worker docs. --- docs/api.md | 53 ++++++++++++++++++++++++++++++++++++++ docs/user-guide/workers.md | 43 ++++++++++++++++++++++++++++++- 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/docs/api.md b/docs/api.md index 03152fa..5c7bb3c 100644 --- a/docs/api.md +++ b/docs/api.md @@ -805,6 +805,59 @@ PyWorker("worker.py", type="micropython")
``` +### `pyscript.workers` + +The `pyscript.workers` reference allows Python code in the main thread to +easily access named workers (and their exported functionality). + +For example, the following Pyodide code may be running on a named worker +(see the `name` attribute of the `script` tag): + +```html + +``` + +While over on the main thread, this fragment of MicroPython will be able to +access the worker's `version` function via the `workers` reference: + +```html + +``` + +Importantly, the `workers` reference will **NOT** provide a list of +known workers, but will only `await` for a reference to a named worker +(resolving when the worker is ready). This is because the timing of worker +startup is not deterministic. + +Should you wish to await for all workers on the page at load time, it's +possible to loop over matching elements in the document like this: + +```html + +``` + ## Worker only features ### `pyscript.js_import` diff --git a/docs/user-guide/workers.md b/docs/user-guide/workers.md index 458fc5b..380f3cd 100644 --- a/docs/user-guide/workers.md +++ b/docs/user-guide/workers.md @@ -69,6 +69,19 @@ attribute flag: ``` +You may also want to add a `name` attribute to the tag, so you can use +`pyscript.workers` in the main thread to retrieve a reference to the worker: + +```html + +``` + +```python +from pyscript import workers + +my_worker = await workers["my-worker"] +``` + Alternatively, to launch a worker from within Python running on the main thread use the [pyscript.PyWorker](../../api/#pyscriptpyworker) class and you must reference both the target Python script and interpreter type: @@ -77,7 +90,7 @@ reference both the target Python script and interpreter type: from pyscript import PyWorker # The type MUST be given and can be either `micropython` or `pyodide` -PyWorker("my-worker-code.py", type="micropython") +my_worker = PyWorker("my-worker-code.py", type="micropython") ``` ## Worker interactions @@ -121,6 +134,34 @@ greeting = sync.hello("PyScript") window.console.log(greeting) ``` +Alternatively, for the main thread to call functions in a worker, specify the +functions in a `__export__` list: + +```python title="Python code on the worker." +import sys + +def version(): + return sys.version + +# Define what to export to the main thread. +__export__ = ["version", ] +``` + +Then ensure you have a reference to the worker in the main thread (for +instance, by using the `pyscript.workers`): + +```html title="Creating a named worker in the web page." + +``` + +```python title="Referencing and using the worker from the main thread." +from pyscript import workers + +my_worker = await workers["my-worker"] + +print(await my_worker.version()) +``` + The values passed between the main thread and the worker **must be serializable**. Try the example given above via [this project on PyScript.com](https://pyscript.com/@ntoll/tiny-silence/latest). From 117caba7c9d4ea7359f89ee07decacdbf58ee203 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Sun, 7 Jul 2024 11:26:19 +0100 Subject: [PATCH 142/201] WiP --- docs/beginning-pyscript.md | 5 +++++ docs/index.md | 11 ++++++----- docs/user-guide/what.md | 4 +++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/docs/beginning-pyscript.md b/docs/beginning-pyscript.md index e1bcf7e..5031fbb 100644 --- a/docs/beginning-pyscript.md +++ b/docs/beginning-pyscript.md @@ -59,6 +59,11 @@ refresh the page (`CTRL-R`) to see any updates you may have made. [Live Server extension](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer) can be used to reload the page as you edit your files. + Alternatively, if you have an account on [GitHub](https://github.com) you + could use VSCode in your browser as a + [PyScript aware "CodeSpace"](https://github.com/ntoll/codespaces-project-template-pyscript/) + (just follow the instructions in the README file). + If you decide to use [pyscript.com](https://pyscript.com) (recommended for first steps), once signed in, create a new project by pressing the "+" button on the left hand side below the site's logo. You'll be presented with a page diff --git a/docs/index.md b/docs/index.md index b50d38e..2cfbb01 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,6 +1,6 @@ ![PyScript Logo](assets/images/pyscript.svg) -

PyScript is a platform for Python in the browser.

+

PyScript is an open source platform for Python in the browser.

## PyScript is... @@ -22,18 +22,19 @@
I'm a beginner...
Welcome! PyScript is designed to be friendly for beginner coders. The - best place to start is by reading our + best way to start is to read our beginning PyScript guide - and then using + and then use pyscript.com - to create your first apps. Having problems? Check out our + to create your first apps. Problems? Check out our frequently asked questions.
I'm already technical...
The beginner docs will set you up with a simple coding environment. For more in-depth technical coverage of PyScript, consult the user guide. The example applications demonstrate many of the features - of PyScript. The FAQ contains lots of technical detail.
+ of PyScript. The API docs and FAQ + contain lots of technical detail.
I want to contribute...

Welcome, friend! diff --git a/docs/user-guide/what.md b/docs/user-guide/what.md index 4ce87ba..84304c1 100644 --- a/docs/user-guide/what.md +++ b/docs/user-guide/what.md @@ -1,6 +1,8 @@ # What is PyScript? -[PyScript](https://pyscript.net) is a platform for [Python](https://python.org) in the +[PyScript](https://pyscript.net) is an +[open source](../../license/) platform for +[Python](https://python.org) in the [browser](https://en.wikipedia.org/wiki/Web_browser). PyScript brings together two of the most vibrant technical ecosystems on the From ec6e33241e69d5efed01d79a32032af1d116318a Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Sun, 7 Jul 2024 11:48:30 +0100 Subject: [PATCH 143/201] More updates for EuroPython. --- docs/user-guide/architecture.md | 4 ++-- docs/user-guide/first-steps.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/user-guide/architecture.md b/docs/user-guide/architecture.md index e383602..be311b6 100644 --- a/docs/user-guide/architecture.md +++ b/docs/user-guide/architecture.md @@ -73,8 +73,8 @@ PolyScript's capabilities, upon which PyScript is built, can be summarised as: defined moments in the page lifecycle, provide a means of calling user defined functions to modify and enhance PolyScript's default behaviour. * [Multiple interpreters](https://pyscript.github.io/polyscript/#interpreter-features) - (in addition to Pyodide and MicroPython, PolyScript works with Lua and Ruby - - although these are beyond the scope of this project). + (in addition to Pyodide and MicroPython, PolyScript works with R, Lua and + Ruby - although these are beyond the scope of this project). PolyScript may become important if you encounter problems with PyScript. You should investigate PolyScript if any of the following is true about your diff --git a/docs/user-guide/first-steps.md b/docs/user-guide/first-steps.md index 1c78a3c..314be79 100644 --- a/docs/user-guide/first-steps.md +++ b/docs/user-guide/first-steps.md @@ -123,7 +123,7 @@ attributes: The browser's tab displaying the website running PyScript is an isolated computing sandbox. Define the Python environment in which your code will run with [configuration options](configuration.md) (discussed later in this - document). + user guide). !!! tip From 24f98a5d683b49cd34e7d993fd73160012d8562e Mon Sep 17 00:00:00 2001 From: webreflection Date: Fri, 26 Jul 2024 12:56:34 +0200 Subject: [PATCH 144/201] Update SharedArrayBuffer + add service-worker attribute details --- docs/faq.md | 70 +++++++------------- docs/user-guide/workers.md | 132 +++++++++++++++++++++++++++++-------- 2 files changed, 127 insertions(+), 75 deletions(-) diff --git a/docs/faq.md b/docs/faq.md index c42a1c7..4608269 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -49,7 +49,7 @@ encounter. ### SharedArrayBuffer -This is the first and most common error users may encounter with PyScript. +This is the first and most common error users may encounter with PyScript: !!! failure @@ -58,52 +58,28 @@ This is the first and most common error users may encounter with PyScript. you see this message: ``` - Unable to use SharedArrayBuffer due insecure environment. - Please read requirements in MDN: ... + Unable to use `window` or `document` -> https://docs.pyscript.net/latest/faq/#sharedarraybuffer ``` -The error contains -[a link to MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer#security_requirements) -but it's the amount of content provided on this topic is overwhelming. - #### When This error happens when **the server delivering your PyScript application is -incorrectly configured**. It fails to provide the correct headers to handle -security concerns for web workers, or you're not using -[mini-coi](https://github.com/WebReflection/mini-coi#readme) as an alternative -solution. (These requirements are explored -[in the worker page](../user-guide/workers#http-headers).) - -**And** at least one of the following scenarios is true: - -* There is a `worker` attribute in the *py* or *mpy* script element and the - [sync_main_only](https://pyscript.github.io/polyscript/#extra-config-features) - flag is not present or not `true`. -* There is a ` - - - - +If you need those features and you are not able to configure your server's headers, +there are at least 2 options: use the +[mini-coi](https://github.com/WebReflection/mini-coi#readme) project +to enforce server side headers on each request or +use the `service-worker` attribute. + +### Option 1: mini-coi + +This is still a preferred option, mostly for performance reasons, so that +*Atomics*' synchronous operations can work at native speed. + +The simplest way to use mini-coi is to copy the +[mini-coi.js](https://raw.githubusercontent.com/WebReflection/mini-coi/main/mini-coi.js) +file content and save it in the root of your website (i.e. `/`), and reference it +as the first child tag in the `` of your HTML documents: + +```html + + + + + + + +``` + +### Option 2: service-worker attribute + +Recently introduced, each ` + + +``` + +!!! note + + Using the *sabayon* fallback to enable *Atomics* synchronous operations + should be the least solution to consider because it is inevitably + slower than having native operations enabled by other means. + + When that is still needed or desired, it is always better to reduce + the amount of synchronous operations by caching references from the + *main* thread. + + ```python + # ❌ THIS IS UNNECESSARILY SLOWER + from pyscript import document + + # add a data-test="not ideal attribute" + document.body.dataset.test = "not ideal" + # read a data-test attribute + print(document.body.dataset.test) + + # - - - - - - - - - - - - - - - - - - - - - + + # ✔️ THIS IS FINE + from pyscript import document + + # if needed elsewhere, reach it once + body = document.body + dataset = body.dataset + + # add a data-test="not ideal attribute" + dataset.test = "not ideal" + # read a data-test attribute + print(dataset.test) ``` +In latter example the amount of operations have been reduced +from *6* to just *4* and the rule of thumb is: +if you ever need a *DOM* reference more than once, cache it 👍 + + ## Start working To start your code in a worker, simply ensure the ` + + @@ -168,8 +168,8 @@ In the end, our HTML should look like this: Codestin Search App - - + +

Polyglot 🦜 💬 🇬🇧 ➡️ 🏴‍☠️

diff --git a/docs/user-guide/first-steps.md b/docs/user-guide/first-steps.md index 141cc05..d0fcffe 100644 --- a/docs/user-guide/first-steps.md +++ b/docs/user-guide/first-steps.md @@ -20,9 +20,9 @@ CSS: - + - + diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md index 3fea9be..8d2d696 100644 --- a/docs/user-guide/plugins.md +++ b/docs/user-guide/plugins.md @@ -99,7 +99,7 @@ For example, this will work because all references are contained within the registered function: ```js -import { hooks } from "https://pyscript.net/releases/2024.7.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2024.8.1/core.js"; hooks.worker.onReady.add(() => { // NOT suggested, just an example! @@ -113,7 +113,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/2024.7.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2024.8.1/core.js"; // NO NO NO NO NO! ☠️ let i = 0; @@ -146,7 +146,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/2024.7.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2024.8.1/core.js"; // The `hooks.main` attribute defines plugins that run on the main thread. hooks.main.onReady.add((wrap, element) => { @@ -196,8 +196,8 @@ hooks.worker.onAfterRun.add(() => { - - + + + Codestin Search App diff --git a/version.json b/version.json index fe19b81..08382ff 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2024.7.1" + "version": "2024.8.1" } From a25b63734e313a475788ea9935eed3d35b016f00 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Thu, 1 Aug 2024 11:39:18 +0100 Subject: [PATCH 147/201] Update pyscript.web docs. --- docs/api.md | 19 +++++++++----- docs/user-guide/dom.md | 58 ++++++++++++++++++++++-------------------- 2 files changed, 42 insertions(+), 35 deletions(-) diff --git a/docs/api.md b/docs/api.md index 5c7bb3c..664145f 100644 --- a/docs/api.md +++ b/docs/api.md @@ -413,29 +413,34 @@ store = await storage("my-data-store", storage_class=MyStorage) ### `pyscript.web` -TODO: Use `display(element)` not `element.display()`. - The classes and references in this namespace provide a Pythonic way to interact with the DOM. An explanation for how to idiomatically use this API can be found [in the user guide](../user-guide/dom/#pyscriptweb) -#### `pyscript.web.dom` +#### `pyscript.web.page` -This object has two attributes and a single method: +This object represents a web page. It has four attributes and two methods: +* `html` - a reference to a Python object representing the [document's html](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/html) root element. * `head` - a reference to a Python object representing the [document's head](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head). * `body` - a reference to a Python object representing the [document's body](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/body). +* `title` - the page's [title](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/title) (usually displayed in the browser's title bar or a page's tab. * `find` - a method that takes a single [selector](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_selectors) argument and returns a collection of Python objects representing the matching elements. +* `append` - a shortcut for `page.body.append` (to add new elements to the + page). + +You may also shortcut the `find` method by enclosing a CSS selector in square +brackets: `page["#my-thing"]`. These are provided as a convenience so you have several simple and obvious -options for accessing the content of the page (DOM). +options for accessing and changing the content of the page. All the Python objects returned by these attributes and method are instances of -classes defined in the `pyscript.web.elements` namespace. +classes relating to HTML elements defined in the `pyscript.web` namespace. -#### `pyscript.web.elements.*` +#### `pyscript.web.*` There are many classes in this namespace. Each is a one-to-one mapping of any HTML element name to a Python class representing the HTML element of that diff --git a/docs/user-guide/dom.md b/docs/user-guide/dom.md index d469d42..b2b0a5b 100644 --- a/docs/user-guide/dom.md +++ b/docs/user-guide/dom.md @@ -99,39 +99,45 @@ There are three core concepts to remember: The `find` API uses exactly the [same queries](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Locating_DOM_elements_using_selectors) as those used by native browser methods like `qurerySelector` or `querySelectorAll`. -* Use classes in the `pyscript.web.elements` namespace to create and organise +* Use classes in the `pyscript.web` namespace to create and organise new elements on the web page. * Collections of elements allow you to access and change attributes en-mass. Such collections are returned from `find` queries and are also used for the [children](https://developer.mozilla.org/en-US/docs/Web/API/Element/children) of an element. -You have several options for accessing the content of the page (i.e. the DOM), -and these can be found in the `pyscript.web.dom` object. The `head` and `body` -attributes reference the page's head and body. Furthermore, the `find` method -can be used to return collections of elements matching your CSS query. Finally, -all elements have a `find` method that searches within their children for -elements matching your CSS query. +You have several options for accessing the content of the page, and these are +all found in the `pyscript.web.page` object. The `html`, `head` and `body` +attributes reference the page's top-level html, head and body. As a convenience +the `page`'s `title` attribute can be used to get and set the web page's title +(usually shown in the browser's tab). The `append` method is a shortcut for +adding content to the page's `body`. Whereas, the `find` method is used to +return collections of elements matching a CSS query. You may also shortcut +`find` via a CSS query in square brackets. Finally, all elements have a `find` +method that searches within their children for elements matching your CSS +query. ```python -from pyscript.web import dom +from pyscript.web import page # Print all the child elements of the document's head. -print(dom.head.children) +print(page.head.children) # Find all the paragraphs in the DOM. -paragraphs = dom.find("p") +paragraphs = page.find("p") +# Or use square brackets. +paragraphs = page["p"] ``` The object returned from a query, or used as a reference to an element's children is iterable: ```python -from pyscript.web import dom +from pyscript.web import page # Get all the paragraphs in the DOM. -paragraphs = dom.find("p") +paragraphs = page["p"] # Print the inner html of each paragraph. for p in paragraphs: @@ -141,38 +147,36 @@ for p in paragraphs: Alternatively, it is also indexable / sliceable: ```python -from pyscript.web import dom +from pyscript.web import page # Get an ElementCollection of all the paragraphs in the DOM -paragraphs = dom.find("p") +paragraphs = page["p"] # Only the final two paragraphs. for p in paragraphs[-2:]: print(p.html) ``` -It also makes available the following read and writable attributes related to -all contained elements: +You have access to all the standard attributes related to HTML elements (for +example, the `innerHTML` or `value`), along with a couple of convenient ways +to interact with classes and CSS styles: * `classes` - the list of classes associated with the elements. -* `innerHTML` - the innerHTML of each element. * `style` - a dictionary like object for interacting with CSS style rules. -* `value` - the `value` attribute associated with each element. For example, to continue the example above, `paragraphs.innerHTML` will return a list of all the values of the `innerHTML` attribute on each contained element. Alternatively, set an attribute for all elements contained in the collection like this: `paragraphs.style["background-color"] = "blue"`. -It's possible to create new elements to add to the DOM: +It's possible to create new elements to add to the page: ```python -from pyscript.web import dom -from pyscript.web.elements import * +from pyscript.web import page, div, select, option, button, span, br -dom.body.append( +page.append( div( div("Hello!", classes="a-css-class", id="hello"), select( @@ -206,7 +210,7 @@ dom.body.append( ``` This example demonstrates a declaritive way to add elements to the body of the -DOM. Notice how the first (unnamed) arguments to an element are its children. +page. Notice how the first (unnamed) arguments to an element are its children. The named arguments (such as `id`, `classes` and `style`) refer to attributes of the underlying HTML element. If you'd rather be explicit about the children of an element, you can always pass in a list of such elements as the named @@ -216,9 +220,7 @@ Of course, you can achieve similar results in an imperative style of programming: ```python -from pyscript.web import dom -from pyscript.web.elements import * - +from pyscript.web import page, div, p my_div = div() @@ -238,10 +240,10 @@ element references from `pyscript.web`: ```python from pyscript import when -from pyscript.web import dom +from pyscript.web import page -btn = dom.find("#my-button") +btn = page["#my-button"] @when("click", btn) From cf41d5595f72a44d3d005ead2f0d2ca4b4b006c1 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Mon, 5 Aug 2024 14:06:12 +0100 Subject: [PATCH 148/201] Bump version to 2024-08-2 in examples. --- docs/beginning-pyscript.md | 8 ++++---- docs/user-guide/first-steps.md | 4 ++-- docs/user-guide/plugins.md | 10 +++++----- docs/user-guide/workers.md | 4 ++-- version.json | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/beginning-pyscript.md b/docs/beginning-pyscript.md index 7a4f90f..12a7717 100644 --- a/docs/beginning-pyscript.md +++ b/docs/beginning-pyscript.md @@ -117,8 +117,8 @@ module in the document's `` tag: Codestin Search App - - + + @@ -168,8 +168,8 @@ In the end, our HTML should look like this: Codestin Search App - - + +

Polyglot 🦜 💬 🇬🇧 ➡️ 🏴‍☠️

diff --git a/docs/user-guide/first-steps.md b/docs/user-guide/first-steps.md index d0fcffe..7ff3b46 100644 --- a/docs/user-guide/first-steps.md +++ b/docs/user-guide/first-steps.md @@ -20,9 +20,9 @@ CSS: - + - + diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md index 8d2d696..836bc08 100644 --- a/docs/user-guide/plugins.md +++ b/docs/user-guide/plugins.md @@ -99,7 +99,7 @@ For example, this will work because all references are contained within the registered function: ```js -import { hooks } from "https://pyscript.net/releases/2024.8.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2024.8.2/core.js"; hooks.worker.onReady.add(() => { // NOT suggested, just an example! @@ -113,7 +113,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/2024.8.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2024.8.2/core.js"; // NO NO NO NO NO! ☠️ let i = 0; @@ -146,7 +146,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/2024.8.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2024.8.2/core.js"; // The `hooks.main` attribute defines plugins that run on the main thread. hooks.main.onReady.add((wrap, element) => { @@ -196,8 +196,8 @@ hooks.worker.onAfterRun.add(() => { - - + + + Codestin Search App diff --git a/version.json b/version.json index 08382ff..f0baa93 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2024.8.1" + "version": "2024.8.2" } From af49775703487652ca2dc223c76c8b57bec90b48 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Mon, 5 Aug 2024 14:21:02 +0100 Subject: [PATCH 149/201] Document the new async behaviour. --- docs/api.md | 14 ++++++-------- docs/faq.md | 2 +- docs/user-guide/first-steps.md | 23 +++++++++++++++++++++-- docs/user-guide/plugins.md | 7 ++++--- docs/user-guide/workers.md | 3 +-- 5 files changed, 33 insertions(+), 16 deletions(-) diff --git a/docs/api.md b/docs/api.md index 664145f..b12953d 100644 --- a/docs/api.md +++ b/docs/api.md @@ -197,10 +197,8 @@ Pyodide and MicroPython. It is closely modelled on the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) found in browsers with some important Pythonic differences. -The simple use case is to pass in a URL and `await` the response. Remember, in -order to use `await` you must have the `async` attribute in the `script` tag -that references your code. If this request is in a function, that function -should also be defined as `async`. +The simple use case is to pass in a URL and `await` the response. If this +request is in a function, that function should also be defined as `async`. ```python title="A simple HTTP GET with pyscript.fetch" from pyscript import fetch @@ -834,7 +832,7 @@ While over on the main thread, this fragment of MicroPython will be able to access the worker's `version` function via the `workers` reference: ```html - Codestin Search App - - + ``` From 8653cd12519c8f10cee80b646bef56fea0c43666 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Mon, 5 Aug 2024 14:22:52 +0100 Subject: [PATCH 150/201] Fix typo --- docs/user-guide/first-steps.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user-guide/first-steps.md b/docs/user-guide/first-steps.md index 1c7805a..b13ba18 100644 --- a/docs/user-guide/first-steps.md +++ b/docs/user-guide/first-steps.md @@ -75,7 +75,7 @@ attributes: JSON or a TOML file, `config='{"packages":["numpy"]}'` and `config="./config.json"` or `config="./config.toml"` are all valid. -* `async` - set this flag to `"false"` so your code won't not run within a +* `async` - set this flag to `"false"` so your code won't run within a [top level await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await#top_level_await) (the default behaviour). From 7013332f4a164581e49f763a7fd327a90d47d239 Mon Sep 17 00:00:00 2001 From: Neon22 <899355+Neon22@users.noreply.github.com> Date: Sat, 17 Aug 2024 12:59:18 +1200 Subject: [PATCH 151/201] Update examples.md included new examples. Made notes about what packages are loaded and added complexity sub headings. --- docs/examples.md | 76 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 71 insertions(+), 5 deletions(-) diff --git a/docs/examples.md b/docs/examples.md index 6599f1f..94ed671 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -5,18 +5,84 @@ PyScript can be found [on PyScript.com](https://pyscript.com/@examples). The examples are (links take you to the code): +### Simple: + * [Hello world](https://pyscript.com/@examples/hello-world/latest) + * uses included datetime module. No additional packages. * [A simple clock](https://pyscript.com/@examples/simple-clock/latest) -* [Simple slider panel](https://pyscript.com/@examples/simple-panel/latest) -* [Streaming data panel](https://pyscript.com/@examples/streaming-in-panel/latest) + * Not found * [WebGL Icosahedron](https://pyscript.com/@examples/webgl-icosahedron/latest) -* [KMeans in a panel](https://pyscript.com/@examples/kmeans-in-panel/latest) -* [New York Taxi panel (WebGL)](https://pyscript.com/@examples/nyc-taxi-panel-deckgl/latest) + * uses very old version of [three.js](https://threejs.org/) directly imported in index.html. (not as a module in toml) * [Pandas dataframe fun](https://pyscript.com/@examples/pandas/latest) + * uses [pandas](https://pandas.pydata.org/) from pypi + * pyodide * [Matplotlib example](https://pyscript.com/@examples/matplotlib/latest) + * uses [matplotlib](https://matplotlib.org/) + * not clear how numpy is being loaded as it is not referenced. + * pyodide +* [Todo](https://pyscript.com/@examples/todo-app/latest) + * uses pyweb. No additional packages. + * pyodide +* [Tic Tac Toe](https://pyscript.com/@examples/tic-tac-toe/latest) + * uses pyweb. No additional packages. + * pyodide +* [Pyscript Jokes](https://pyscript.com/@examples/pyscript-jokes/latest) + * uses pyweb and [pyjokes](https://pyjok.es/) + * pyodide +* [D3 visualization](https://pyscript.com/@examples/d3-visualization/latest) + * uses [d3]() + * mixes javascript code with python code. imports d3 from javascript. + * pyodide +* [Import antigravity](https://pyscript.com/@examples/antigravity/latest) + * uses svg + * pyodide +* [API proxy tutorial](https://pyscript.com/@examples/api-proxy-tutorial/latest) + * uses fetch + * pyodide +* [API proxy and secrets tutorial](https://pyscript.com/@examples/api-proxy-and-secrets-tutorial/latest) + * uses fetch + * pyodide + +### More complex: + * [Numpy fractals](https://pyscript.com/@examples/fractals-with-numpy-and-canvas/latest) + * uses [numpy](https://numpy.org/), [sympy](https://www.sympy.org/en/index.html) from pypi + * pyodide +* [Simple slider panel](https://pyscript.com/@examples/simple-panel/latest) + * uses [Panel](https://panel.holoviz.org/) and [Bokeh](https://bokeh.org/) from pypi and loads in index.html + * does not run + * pyodide +* [Streaming data panel](https://pyscript.com/@examples/streaming-in-panel/latest) + * uses [Panel](https://panel.holoviz.org/), [Bokeh](https://bokeh.org/) [numpy](https://numpy.org/), [pandas](https://pandas.pydata.org/) from pypi + * loads bokeh, panel, tabulator in index.html + * pyodide +* [KMeans in a panel](https://pyscript.com/@examples/kmeans-in-panel/latest) + * uses [Bokeh](https://bokeh.org/), [altair](https://altair-viz.github.io/), [numpy](https://numpy.org/), [pandas](https://pandas.pydata.org/), [scikit-learn](https://scikit-learn.org/stable/), [Panel](https://panel.holoviz.org/) from pypi + * loads panel, bootstrap, vega, tabulator, bokeh in index.html + * runs but displays errors to do with threadpools + * pyodide +* [New York Taxi panel (WebGL)](https://pyscript.com/@examples/nyc-taxi-panel-deckgl/latest) + * uses a mixture of pypi and direct load packages in index.html + * [Bokeh](https://bokeh.org/), [numpy](https://numpy.org/), [pandas](https://pandas.pydata.org/), [Panel](https://panel.holoviz.org/), [deck-gl](https://deck.gl/) + * deckGL, bokeh are loaded directly in index.html + * pyodide * [Folium geographical data](https://pyscript.com/@examples/folium/latest) + * uses [folium](https://python-visualization.github.io/folium/latest/), [pandas](https://pandas.pydata.org/) from pypi + * pyodide * [Bokeh data plotting](https://pyscript.com/@examples/bokeh/latest) -* [Import antigravity](https://pyscript.com/@examples/antigravity/latest) + * uses [pandas](https://pandas.pydata.org/), [Bokeh](https://bokeh.org/), [xyzservices](https://github.com/geopandas/xyzservices) from pypi + * pyodide * [Altair data plotting](https://pyscript.com/@examples/altair/latest) + * uses [altair](https://altair-viz.github.io/), [pandas](https://pandas.pydata.org/), [vega_datasets](https://github.com/altair-viz/vega_datasets) from pypi + * pyodide +* [Panel and hyplot](https://pyscript.com/@examples/panel-and-hvplot/latest) + * uses [Bokeh](https://bokeh.org/), [Panel](https://panel.holoviz.org/), [markdown-it-py](https://github.com/executablebooks/markdown-it-py), [numpy](https://numpy.org/), [pandas](https://pandas.pydata.org/), [hvplot](https://hvplot.holoviz.org/), [pyodide-http](https://pyodide.org/en/stable/usage/api/python-api/http.html) a fetch library. + * bokeh and panel are loaded in the index.html + * pyodide +Notes: + - Updated from 14 to 20 found at above link + - No micropython examples - all are pyodide + - No worker examples + - async used in some examples - probably obsolete now + - fetch done several ways From 86661debda2f4a79095f673de65613249d0d205d Mon Sep 17 00:00:00 2001 From: Neon22 <899355+Neon22@users.noreply.github.com> Date: Wed, 28 Aug 2024 08:06:59 +1200 Subject: [PATCH 152/201] missing d3 link --- docs/examples.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples.md b/docs/examples.md index 94ed671..18424a7 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -30,7 +30,7 @@ The examples are (links take you to the code): * uses pyweb and [pyjokes](https://pyjok.es/) * pyodide * [D3 visualization](https://pyscript.com/@examples/d3-visualization/latest) - * uses [d3]() + * uses [d3](https://d3js.org/) * mixes javascript code with python code. imports d3 from javascript. * pyodide * [Import antigravity](https://pyscript.com/@examples/antigravity/latest) From bab374afc8497353cdd5666bb6a5ffe33a10c399 Mon Sep 17 00:00:00 2001 From: Neon22 <899355+Neon22@users.noreply.github.com> Date: Wed, 28 Aug 2024 15:11:51 +1200 Subject: [PATCH 153/201] sample clock removed This example has just been removed in another PR - so making sure it stays removed here. --- docs/examples.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/examples.md b/docs/examples.md index 18424a7..7b0f394 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -9,8 +9,6 @@ The examples are (links take you to the code): * [Hello world](https://pyscript.com/@examples/hello-world/latest) * uses included datetime module. No additional packages. -* [A simple clock](https://pyscript.com/@examples/simple-clock/latest) - * Not found * [WebGL Icosahedron](https://pyscript.com/@examples/webgl-icosahedron/latest) * uses very old version of [three.js](https://threejs.org/) directly imported in index.html. (not as a module in toml) * [Pandas dataframe fun](https://pyscript.com/@examples/pandas/latest) From 8dad7449c2487e974acb4ce4489da7300a020c8a Mon Sep 17 00:00:00 2001 From: Neon22 <899355+Neon22@users.noreply.github.com> Date: Thu, 29 Aug 2024 14:29:04 +1200 Subject: [PATCH 154/201] updated text after fixes made to examples --- docs/examples.md | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/docs/examples.md b/docs/examples.md index 7b0f394..06dc0a8 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -10,13 +10,12 @@ The examples are (links take you to the code): * [Hello world](https://pyscript.com/@examples/hello-world/latest) * uses included datetime module. No additional packages. * [WebGL Icosahedron](https://pyscript.com/@examples/webgl-icosahedron/latest) - * uses very old version of [three.js](https://threejs.org/) directly imported in index.html. (not as a module in toml) + * uses [three.js](https://threejs.org/) imported as a module in toml) * [Pandas dataframe fun](https://pyscript.com/@examples/pandas/latest) * uses [pandas](https://pandas.pydata.org/) from pypi * pyodide * [Matplotlib example](https://pyscript.com/@examples/matplotlib/latest) * uses [matplotlib](https://matplotlib.org/) - * not clear how numpy is being loaded as it is not referenced. * pyodide * [Todo](https://pyscript.com/@examples/todo-app/latest) * uses pyweb. No additional packages. @@ -32,7 +31,7 @@ The examples are (links take you to the code): * mixes javascript code with python code. imports d3 from javascript. * pyodide * [Import antigravity](https://pyscript.com/@examples/antigravity/latest) - * uses svg + * uses svg simply * pyodide * [API proxy tutorial](https://pyscript.com/@examples/api-proxy-tutorial/latest) * uses fetch @@ -48,7 +47,6 @@ The examples are (links take you to the code): * pyodide * [Simple slider panel](https://pyscript.com/@examples/simple-panel/latest) * uses [Panel](https://panel.holoviz.org/) and [Bokeh](https://bokeh.org/) from pypi and loads in index.html - * does not run * pyodide * [Streaming data panel](https://pyscript.com/@examples/streaming-in-panel/latest) * uses [Panel](https://panel.holoviz.org/), [Bokeh](https://bokeh.org/) [numpy](https://numpy.org/), [pandas](https://pandas.pydata.org/) from pypi @@ -57,7 +55,6 @@ The examples are (links take you to the code): * [KMeans in a panel](https://pyscript.com/@examples/kmeans-in-panel/latest) * uses [Bokeh](https://bokeh.org/), [altair](https://altair-viz.github.io/), [numpy](https://numpy.org/), [pandas](https://pandas.pydata.org/), [scikit-learn](https://scikit-learn.org/stable/), [Panel](https://panel.holoviz.org/) from pypi * loads panel, bootstrap, vega, tabulator, bokeh in index.html - * runs but displays errors to do with threadpools * pyodide * [New York Taxi panel (WebGL)](https://pyscript.com/@examples/nyc-taxi-panel-deckgl/latest) * uses a mixture of pypi and direct load packages in index.html @@ -79,8 +76,5 @@ The examples are (links take you to the code): * pyodide Notes: - - Updated from 14 to 20 found at above link - No micropython examples - all are pyodide - No worker examples - - async used in some examples - probably obsolete now - - fetch done several ways From cfdd81dd43cebff1d891dc29258a381e9829ee42 Mon Sep 17 00:00:00 2001 From: webreflection Date: Fri, 13 Sep 2024 11:27:37 +0200 Subject: [PATCH 155/201] Add m/py:progress events description --- docs/api.md | 92 ++++++++++++++++++++++++++--------------------------- docs/faq.md | 16 ++++++++++ 2 files changed, 62 insertions(+), 46 deletions(-) diff --git a/docs/api.md b/docs/api.md index b12953d..4644dd3 100644 --- a/docs/api.md +++ b/docs/api.md @@ -766,6 +766,52 @@ The following code demonstrates a `pyscript.WebSocket` in action. ws = WebSocket(url="ws://example.com/socket", onmessage=onmessage) ``` +### `pyscript.js_import` + +If a JavaScript module is only needed under certain circumstances, we provide +an asynchronous way to import packages that were not originally referenced in +your configuration. + +```html title="A pyscript.js_import example." + +``` + +The `py_import` call returns an asynchronous tuple containing the Python +modules provided by the packages referenced as string arguments. + ## Main-thread only features ### `pyscript.PyWorker` @@ -863,52 +909,6 @@ for el in document.querySelectorAll("[type='py'][worker][name]"): ## Worker only features -### `pyscript.js_import` - -If a JavaScript module is only needed under certain circumstances, we provide -an asynchronous way to import packages that were not originally referenced in -your configuration. - -```html title="A pyscript.js_import example." - -``` - -The `py_import` call returns an asynchronous tuple containing the Python -modules provided by the packages referenced as string arguments. - ### `pyscript.sync` A function used to pass serializable data from workers to the main thread. diff --git a/docs/faq.md b/docs/faq.md index 23c25af..7b78a72 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -682,6 +682,22 @@ done"` message is written to the browser's console. ``` +#### m/py:progress + +The `py:progress` or `mpy:progress` event triggers on the main thread *during* interpreter bootstrap, being this either on *main* or *worker*. + +Following previous work around progress events from *micropip*, the received `event.detail` will be a string that confine operations between `Loading {what}` and `Loaded {what}`, where the first event would hence be `Loading Pyodide` and the last one per each bootstrap would be `Loaded Pyodide`. + +In between all operations will be forwarded as `event.detail`, such as: + + * `Loading files` and `Loaded files`, when `[files]` is found in the optional config + * `Loading fetch` and `Loaded fetch`, when `[fetch]` is found in the optional config + * `Loading JS modules` and `Loaded JS modules`, when `[js_modules.main]` or `[js_modules.worker]` +is found in the optional config + * finally, all optional packages handled via *micropip* or *mip* will also trigger various `Loading ...` and `Loaded ...` events so that users can actually see what is going on while the *app* is bootstrapping + +An example of this listener applied to a dialog cna be found in here: https://agiammarchi.pyscriptapps.com/kmeans-in-panel-copy/v1/ + ### Packaging pointers Applications need third party packages and [PyScript can be configured to From 7f57512a37601a76b7bb810740641430503e4250 Mon Sep 17 00:00:00 2001 From: webreflection Date: Fri, 13 Sep 2024 11:38:33 +0200 Subject: [PATCH 156/201] I took a chance to update some other part of the docs too --- docs/user-guide/offline.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/user-guide/offline.md b/docs/user-guide/offline.md index 9bf7717..919f387 100644 --- a/docs/user-guide/offline.md +++ b/docs/user-guide/offline.md @@ -40,7 +40,7 @@ cd pyscript-offline Build PyScript core by cloning the project repository and follow the instructions in our [developer guide](../developers.md) -Once completed, copy the `build` folder, that was been created by the build +Once completed, copy the `dist` folder, that has been created by the build step, into your `pyscript-offline` folder. ### PyScript core from `npm` @@ -114,7 +114,7 @@ python3 -m http.server -d ./public/ If you would like to test `worker` features, try instead: ```sh -npx static-handler --coi ./public/ +npx mini-coi ./public/ ``` ## Download a local interpreter @@ -231,7 +231,7 @@ Finally, we need the ability to install Python packages from a local source when using Pyodide. Put simply, we use the packages bundle from -[pyodide releases](https://github.com/pyodide/pyodide/releases/tag/0.24.1). +[pyodide releases](https://github.com/pyodide/pyodide/releases/tag/0.26.2). !!! warning @@ -240,8 +240,8 @@ Put simply, we use the packages bundle from It contains each package that is required by Pyodide, and Pyodide will only load packages when needed. -Once downloaded and extracted (we're using version `0.24.1` in this example), -we can simply copy the files and folders inside the `pyodide-0.24.1/pyodide/*` +Once downloaded and extracted (we're using version `0.26.2` in this example), +we can simply copy the files and folders inside the `pyodide-0.26.2/pyodide/*` directory into our `./public/pyodide/*` folder. Feel free to either skip or replace the content, or even directly move the From fc1efb60f7f89021d6d4d0d3dc5d3dd9d4ac3bb9 Mon Sep 17 00:00:00 2001 From: webreflection Date: Fri, 13 Sep 2024 12:08:26 +0200 Subject: [PATCH 157/201] Added JS storage too --- docs/api.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/api.md b/docs/api.md index 4644dd3..cec8145 100644 --- a/docs/api.md +++ b/docs/api.md @@ -409,6 +409,12 @@ store = await storage("my-data-store", storage_class=MyStorage) # The store object is now an instance of MyStorage. ``` +### `@pyscript/core/dist/storage.js` + +The equivalent functionality based on the *JS* module can be found through our module. + +The goal is to be able to share the same database across different worlds (interpreters) and the functionality is nearly identical except there is no *class* to provide because the storage in *JS* is just a dictionary proxy that synchronizes behind the scene all read, write or delete operations. + ### `pyscript.web` The classes and references in this namespace provide a Pythonic way to interact From ae2fafa6ba888f010652d66913b766c67a83154c Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Fri, 13 Sep 2024 11:11:23 +0100 Subject: [PATCH 158/201] Minor edits. --- docs/faq.md | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/docs/faq.md b/docs/faq.md index 7b78a72..0cf9b8a 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -684,19 +684,28 @@ done"` message is written to the browser's console. #### m/py:progress -The `py:progress` or `mpy:progress` event triggers on the main thread *during* interpreter bootstrap, being this either on *main* or *worker*. - -Following previous work around progress events from *micropip*, the received `event.detail` will be a string that confine operations between `Loading {what}` and `Loaded {what}`, where the first event would hence be `Loading Pyodide` and the last one per each bootstrap would be `Loaded Pyodide`. - -In between all operations will be forwarded as `event.detail`, such as: - - * `Loading files` and `Loaded files`, when `[files]` is found in the optional config - * `Loading fetch` and `Loaded fetch`, when `[fetch]` is found in the optional config - * `Loading JS modules` and `Loaded JS modules`, when `[js_modules.main]` or `[js_modules.worker]` -is found in the optional config - * finally, all optional packages handled via *micropip* or *mip* will also trigger various `Loading ...` and `Loaded ...` events so that users can actually see what is going on while the *app* is bootstrapping - -An example of this listener applied to a dialog cna be found in here: https://agiammarchi.pyscriptapps.com/kmeans-in-panel-copy/v1/ +The `py:progress` or `mpy:progress` event triggers on the main thread *during* +interpreter bootstrap (no matter if your code is running on main or in a +worker). + +The received `event.detail` is a string that indicates operations between +`Loading {what}` and `Loaded {what}`. So, the first event would be, for +example, `Loading Pyodide` and the last one per each bootstrap would be +`Loaded Pyodide`. + +In between all operations are `event.detail`s, such as: + + * `Loading files` and `Loaded files`, when `[files]` is found in the optional + config + * `Loading fetch` and `Loaded fetch`, when `[fetch]` is found in the optional + config + * `Loading JS modules` and `Loaded JS modules`, when `[js_modules.main]` or + `[js_modules.worker]` is found in the optional config + * finally, all optional packages handled via *micropip* or *mip* will also + trigger various `Loading ...` and `Loaded ...` events so that users can see + what is going on while PyScript is bootstrapping + +An example of this listener applied to a dialog can be [found in here](https://agiammarchi.pyscriptapps.com/kmeans-in-panel-copy/v1/). ### Packaging pointers From 9a75798d2c21e3b38535476ae2414144b7e0828f Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Fri, 13 Sep 2024 13:53:09 +0100 Subject: [PATCH 159/201] Bump version --- docs/beginning-pyscript.md | 8 ++++---- docs/user-guide/first-steps.md | 4 ++-- docs/user-guide/plugins.md | 10 +++++----- docs/user-guide/workers.md | 4 ++-- version.json | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/beginning-pyscript.md b/docs/beginning-pyscript.md index 12a7717..998b53d 100644 --- a/docs/beginning-pyscript.md +++ b/docs/beginning-pyscript.md @@ -117,8 +117,8 @@ module in the document's `` tag: Codestin Search App - - + + @@ -168,8 +168,8 @@ In the end, our HTML should look like this: Codestin Search App - - + +

Polyglot 🦜 💬 🇬🇧 ➡️ 🏴‍☠️

diff --git a/docs/user-guide/first-steps.md b/docs/user-guide/first-steps.md index b13ba18..d8a6444 100644 --- a/docs/user-guide/first-steps.md +++ b/docs/user-guide/first-steps.md @@ -20,9 +20,9 @@ CSS: - + - + diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md index 9c43cb1..bf776c6 100644 --- a/docs/user-guide/plugins.md +++ b/docs/user-guide/plugins.md @@ -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/2024.8.2/core.js"; +import { hooks } from "https://pyscript.net/releases/2024.9.1/core.js"; hooks.worker.onReady.add(() => { // NOT suggested, just an example! @@ -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/2024.8.2/core.js"; +import { hooks } from "https://pyscript.net/releases/2024.9.1/core.js"; // NO NO NO NO NO! ☠️ let i = 0; @@ -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/2024.8.2/core.js"; +import { hooks } from "https://pyscript.net/releases/2024.9.1/core.js"; // The `hooks.main` attribute defines plugins that run on the main thread. hooks.main.onReady.add((wrap, element) => { @@ -197,8 +197,8 @@ hooks.worker.onAfterRun.add(() => { - - + + + Codestin Search App diff --git a/version.json b/version.json index f0baa93..f2ada48 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2024.8.2" + "version": "2024.9.1" } From af8636c85f9f59d6125796ffb78dd58a834abfe0 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Thu, 26 Sep 2024 09:29:29 +0100 Subject: [PATCH 160/201] Correct erroneous function call for adding a class. --- docs/user-guide/dom.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user-guide/dom.md b/docs/user-guide/dom.md index b2b0a5b..1859cb8 100644 --- a/docs/user-guide/dom.md +++ b/docs/user-guide/dom.md @@ -225,7 +225,7 @@ from pyscript.web import page, div, p my_div = div() my_div.style["background-color"] = "red" -my_div.classes.append("a-css-class") +my_div.classes.add("a-css-class") my_p = p() my_p.content = "This is a paragraph." From 44cdd4a93b9dc4c1354841ce5d268f5d0399850b Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Fri, 27 Sep 2024 15:01:59 +0100 Subject: [PATCH 161/201] Version update --- docs/beginning-pyscript.md | 8 ++++---- docs/user-guide/first-steps.md | 4 ++-- docs/user-guide/plugins.md | 10 +++++----- docs/user-guide/workers.md | 4 ++-- version.json | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/beginning-pyscript.md b/docs/beginning-pyscript.md index 998b53d..f3799d4 100644 --- a/docs/beginning-pyscript.md +++ b/docs/beginning-pyscript.md @@ -117,8 +117,8 @@ module in the document's `` tag: Codestin Search App - - + + @@ -168,8 +168,8 @@ In the end, our HTML should look like this: Codestin Search App - - + +

Polyglot 🦜 💬 🇬🇧 ➡️ 🏴‍☠️

diff --git a/docs/user-guide/first-steps.md b/docs/user-guide/first-steps.md index d8a6444..871ec72 100644 --- a/docs/user-guide/first-steps.md +++ b/docs/user-guide/first-steps.md @@ -20,9 +20,9 @@ CSS: - + - + diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md index bf776c6..e0d05bd 100644 --- a/docs/user-guide/plugins.md +++ b/docs/user-guide/plugins.md @@ -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/2024.9.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2024.9.2/core.js"; hooks.worker.onReady.add(() => { // NOT suggested, just an example! @@ -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/2024.9.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2024.9.2/core.js"; // NO NO NO NO NO! ☠️ let i = 0; @@ -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/2024.9.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2024.9.2/core.js"; // The `hooks.main` attribute defines plugins that run on the main thread. hooks.main.onReady.add((wrap, element) => { @@ -197,8 +197,8 @@ hooks.worker.onAfterRun.add(() => { - - + + + Codestin Search App diff --git a/version.json b/version.json index f2ada48..a0867df 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2024.9.1" + "version": "2024.9.2" } From fda45ee787a956413a14dcb57a6b6b2791a2182a Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Fri, 27 Sep 2024 15:09:56 +0100 Subject: [PATCH 162/201] Add detail about config 'type' attribute to indicate the currently running interpreter. --- docs/api.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/api.md b/docs/api.md index cec8145..6e4c71a 100644 --- a/docs/api.md +++ b/docs/api.md @@ -56,8 +56,16 @@ from pyscript import config # It's just a dict. print(config.get("files")) +# This will be either "mpy" or "py" depending on the current interpreter. +print(config["type"]) ``` +!!! info + + The `config` object will always include a `type` attribute set to either + `mpy` or `py`, to indicate which version of Python your code is currently + running in. + !!! warning Changing the `config` dictionary at runtime has no effect on the actual From 6f0f42dc0d7a4c68ac1cbc1bbe7db6b1385f0d83 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Tue, 1 Oct 2024 09:29:29 +0100 Subject: [PATCH 163/201] Use correct command in docs. --- docs/developers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developers.md b/docs/developers.md index 9476814..ec18d10 100644 --- a/docs/developers.md +++ b/docs/developers.md @@ -228,7 +228,7 @@ is through this environment that you contribute to PyScript. * The integration tests for PyScript are started with: ```sh - make test-integration + make test ``` ## Documentation From 5ca780f372c2371dbf479f12aef6148ebbe16d93 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Tue, 1 Oct 2024 14:38:17 +0100 Subject: [PATCH 164/201] Add test related details. --- docs/developers.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/developers.md b/docs/developers.md index ec18d10..7ac7ab9 100644 --- a/docs/developers.md +++ b/docs/developers.md @@ -230,6 +230,28 @@ is through this environment that you contribute to PyScript. ```sh make test ``` + + (This essentially runs the `npm run test:integration` command in the right + place. This is defined in PyScript's `package.json` file.) + + Tests are found in the `core/tests` directory. These are organised into + three locations: + + 1. `python` - the Python based test suite to exercise Python code + **within** PyScript. + 2. `javascript` - JavaScript tests to exercise PyScript itself, in the + browser. + 3. `manual` - containing tests to run manually in a browser, due to the + complex nature of the tests. + + We use [Playwright](https://playwright.dev/) to automate the running of the + Python and JavaScript test suites. We use + [uPyTest](https://github.com/ntoll/upytest) as a test framework for the + Python test suite. uPyTest is a "PyTest inspired" framework for running + tests in the browser on both MicroPython and Pyodide. + + The automated (Playwright) tests are specified in the + `tests/integration.spec.js` file. ## Documentation From f16f9174607b43b1911f2b0c3a8117b4f7ce7414 Mon Sep 17 00:00:00 2001 From: webreflection Date: Fri, 4 Oct 2024 17:28:43 +0200 Subject: [PATCH 165/201] Added donkey export decription --- docs/api.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/docs/api.md b/docs/api.md index 6e4c71a..5e81afd 100644 --- a/docs/api.md +++ b/docs/api.md @@ -417,6 +417,33 @@ store = await storage("my-data-store", storage_class=MyStorage) # The store object is now an instance of MyStorage. ``` +### `@pyscript/core/donkey` + +Meant as *JS* related imports, you can `import { donkey } from '@pyscript/core/dist/core.js'` and automatically have both *pyscript* module running on your page and a utility to bootstrap a terminal based worker that could evaluate any Python code you need to. + +```js title="A donkey worker" +import { donkey } from '@pyscript/core/dist/core.js'; + +const { + process, // process(code) directly (code visible on the terminal) + execute, // execute(statement) in Python exec way + evaluate, // evaluate(expression) in Python eval way + clear, // clear() the terminal + reset, // reset() the terminal (including colors) + kill, // kill() the worker forever +} = donkey({ + type: 'py' || 'mpy', // the donkey interpreter to run + persistent: false, // use `true` to track globals and locals + terminal: '', // optionally set a target terminal container + config: {}, // the worker config (packages, files, etc.) +}); +``` + +About the **terminal** option, please note by default *PyScript* would create a target for that, so that if you don't want it visible on your page you can point to a *CSS* addressable container that is not visible (that is: a `#target` element that has a `display: none` as *CSS* property). + +With this primitive, and without even bothering with specialized *PyScript* tags, we hope anyone can try out of the box what is that *PyScript* enables on the Web! + + ### `@pyscript/core/dist/storage.js` The equivalent functionality based on the *JS* module can be found through our module. From 5cd6cebc1928c010495f56fe4ac35ad721c36f3a Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Mon, 7 Oct 2024 11:55:06 +0100 Subject: [PATCH 166/201] Copy edit. --- docs/api.md | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/docs/api.md b/docs/api.md index 5e81afd..e5dceb3 100644 --- a/docs/api.md +++ b/docs/api.md @@ -419,30 +419,39 @@ store = await storage("my-data-store", storage_class=MyStorage) ### `@pyscript/core/donkey` -Meant as *JS* related imports, you can `import { donkey } from '@pyscript/core/dist/core.js'` and automatically have both *pyscript* module running on your page and a utility to bootstrap a terminal based worker that could evaluate any Python code you need to. +Sometimes you need a Python worker ready and waiting to evaluate any code on +your behalf. This is the concept behind the JavaScript "donkey". We couldn't +think of a better way than "donkey" to describe something that is easy to +understand and shoulders the burden without complaint. This feature +means you're able to use PyScript without resorting to specialised +` + + @@ -168,8 +168,8 @@ In the end, our HTML should look like this: Codestin Search App - - + +

Polyglot 🦜 💬 🇬🇧 ➡️ 🏴‍☠️

diff --git a/docs/user-guide/first-steps.md b/docs/user-guide/first-steps.md index 871ec72..44b8f66 100644 --- a/docs/user-guide/first-steps.md +++ b/docs/user-guide/first-steps.md @@ -20,9 +20,9 @@ CSS: - + - + diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md index e0d05bd..493af3a 100644 --- a/docs/user-guide/plugins.md +++ b/docs/user-guide/plugins.md @@ -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/2024.9.2/core.js"; +import { hooks } from "https://pyscript.net/releases/2024.10.1/core.js"; hooks.worker.onReady.add(() => { // NOT suggested, just an example! @@ -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/2024.9.2/core.js"; +import { hooks } from "https://pyscript.net/releases/2024.10.1/core.js"; // NO NO NO NO NO! ☠️ let i = 0; @@ -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/2024.9.2/core.js"; +import { hooks } from "https://pyscript.net/releases/2024.10.1/core.js"; // The `hooks.main` attribute defines plugins that run on the main thread. hooks.main.onReady.add((wrap, element) => { @@ -197,8 +197,8 @@ hooks.worker.onAfterRun.add(() => { - - + + + Codestin Search App diff --git a/version.json b/version.json index a0867df..1c15121 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2024.9.2" + "version": "2024.10.1" } From 3b74aac3ced422eff753e3db30b178f33f9cce5d Mon Sep 17 00:00:00 2001 From: webreflection Date: Thu, 17 Oct 2024 18:20:49 +0200 Subject: [PATCH 168/201] Bring back the plugins field in the docs --- docs/user-guide/configuration.md | 40 ++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/docs/user-guide/configuration.md b/docs/user-guide/configuration.md index e1174a5..57ce73d 100644 --- a/docs/user-guide/configuration.md +++ b/docs/user-guide/configuration.md @@ -306,6 +306,46 @@ following valid forms: * An arbitrary URL to a Python package: `"https://.../package.whl"` * A file copied onto the browser based file system: `"emfs://.../package.whl"` +### Plugins + +The `plugins` option allows user to either augment, or exclude, the list of +plugins imported out of the box from *core* during bootstrap. + +While augmenting requires some knowledge about *core* internals, excluding +some plugin might be desired to avoid such plugin behavior and, in edge cases, +reduce the amount of network requests to bootstrap *PyScript*. + +It is possible to check the [list of plugins](https://github.com/pyscript/pyscript/blob/main/core/src/plugins.js) +we offer by default, where each *key* is used as plugin name and could be also +disabled using the `!pugin-name` convention, here an example: + +```TOML title="Specify plugins in TOML" +plugins = ["custom_plugin", "!error"] +``` + +```JSON title="Specify plugins in JSON" +{ + "plugins": ["custom_plugin", "!error"] +} +``` + +!!! info + + The `"!error"` syntax is a way to turn off a plugin built into PyScript + that is enabled by default. + + It is possible to turn off other plugins too using the very same + convention. + +!!! warning + + Please note `plugins` are currently a *core* only feature. If you need any + extra functionality out of the box *files* or *js_modules* are the current + way to provide more features without needing to file a *PR* in *core*. + + This means that the current `plugins` proposal is meant to disable our own + plugins but it has no usage to add 3rd party plugins right now. + ### JavaScript modules It's easy to import and use JavaScript modules in your Python code. This From 02deca53cce4d01619989408a76fec57d5445714 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Mon, 28 Oct 2024 10:49:57 +0000 Subject: [PATCH 169/201] Bump version to 2024-10-2. --- docs/beginning-pyscript.md | 8 ++++---- docs/user-guide/first-steps.md | 4 ++-- docs/user-guide/plugins.md | 10 +++++----- docs/user-guide/workers.md | 4 ++-- version.json | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/beginning-pyscript.md b/docs/beginning-pyscript.md index d2bdfb8..bbbaf18 100644 --- a/docs/beginning-pyscript.md +++ b/docs/beginning-pyscript.md @@ -117,8 +117,8 @@ module in the document's `` tag: Codestin Search App - - + + @@ -168,8 +168,8 @@ In the end, our HTML should look like this: Codestin Search App - - + +

Polyglot 🦜 💬 🇬🇧 ➡️ 🏴‍☠️

diff --git a/docs/user-guide/first-steps.md b/docs/user-guide/first-steps.md index 44b8f66..6ae35be 100644 --- a/docs/user-guide/first-steps.md +++ b/docs/user-guide/first-steps.md @@ -20,9 +20,9 @@ CSS: - + - + diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md index 493af3a..8e559f7 100644 --- a/docs/user-guide/plugins.md +++ b/docs/user-guide/plugins.md @@ -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/2024.10.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2024.10.2/core.js"; hooks.worker.onReady.add(() => { // NOT suggested, just an example! @@ -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/2024.10.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2024.10.2/core.js"; // NO NO NO NO NO! ☠️ let i = 0; @@ -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/2024.10.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2024.10.2/core.js"; // The `hooks.main` attribute defines plugins that run on the main thread. hooks.main.onReady.add((wrap, element) => { @@ -197,8 +197,8 @@ hooks.worker.onAfterRun.add(() => { - - + + + Codestin Search App diff --git a/version.json b/version.json index 1c15121..cffd93e 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2024.10.1" + "version": "2024.10.2" } From e454338b4980feeb86f241e66193d8dc7ed4ff22 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Mon, 4 Nov 2024 11:51:23 +0000 Subject: [PATCH 170/201] Bump version number. --- docs/beginning-pyscript.md | 8 ++++---- docs/user-guide/first-steps.md | 4 ++-- docs/user-guide/plugins.md | 10 +++++----- docs/user-guide/workers.md | 4 ++-- version.json | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/beginning-pyscript.md b/docs/beginning-pyscript.md index bbbaf18..460d4d9 100644 --- a/docs/beginning-pyscript.md +++ b/docs/beginning-pyscript.md @@ -117,8 +117,8 @@ module in the document's `` tag: Codestin Search App - - + + @@ -168,8 +168,8 @@ In the end, our HTML should look like this: Codestin Search App - - + +

Polyglot 🦜 💬 🇬🇧 ➡️ 🏴‍☠️

diff --git a/docs/user-guide/first-steps.md b/docs/user-guide/first-steps.md index 6ae35be..ddc0005 100644 --- a/docs/user-guide/first-steps.md +++ b/docs/user-guide/first-steps.md @@ -20,9 +20,9 @@ CSS: - + - + diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md index 8e559f7..e534880 100644 --- a/docs/user-guide/plugins.md +++ b/docs/user-guide/plugins.md @@ -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/2024.10.2/core.js"; +import { hooks } from "https://pyscript.net/releases/2024.11.1/core.js"; hooks.worker.onReady.add(() => { // NOT suggested, just an example! @@ -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/2024.10.2/core.js"; +import { hooks } from "https://pyscript.net/releases/2024.11.1/core.js"; // NO NO NO NO NO! ☠️ let i = 0; @@ -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/2024.10.2/core.js"; +import { hooks } from "https://pyscript.net/releases/2024.11.1/core.js"; // The `hooks.main` attribute defines plugins that run on the main thread. hooks.main.onReady.add((wrap, element) => { @@ -197,8 +197,8 @@ hooks.worker.onAfterRun.add(() => { - - + + + Codestin Search App diff --git a/version.json b/version.json index cffd93e..03caaca 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2024.10.2" + "version": "2024.11.1" } From c7bfe3617f285d1fb84ac2cc2a7a1124b69838be Mon Sep 17 00:00:00 2001 From: "Sterling G. Baird" Date: Fri, 22 Nov 2024 13:25:44 -0500 Subject: [PATCH 171/201] Update configuration.md with warning about CORS / redirect URLs https://github.com/pyscript/pyscript/discussions/2244#discussioncomment-11312534 --- docs/user-guide/configuration.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/user-guide/configuration.md b/docs/user-guide/configuration.md index 57ce73d..2b2b322 100644 --- a/docs/user-guide/configuration.md +++ b/docs/user-guide/configuration.md @@ -174,6 +174,12 @@ into the target directory in the browser's built in file system. If there is a duplication PyScript will raise an exception to help you find the problem. +!!! warning + **Use destination URLs instead of CORS / redirect URLs.** + + For example, `https://github.com/pyscript/ltk/raw/refs/heads/main/ltk/jquery.py` + redirects to `https://raw.githubusercontent.com/pyscript/ltk/refs/heads/main/ltk/jquery.py`. Use the latter. + !!! tip **For most people, most of the time, the simple URL to filename mapping, From 0ae16604a3e6717c0f210767688763a0f1f5fc09 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Fri, 6 Dec 2024 14:47:18 +0000 Subject: [PATCH 172/201] Add FAQ not about randomUUID related error. --- docs/faq.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/docs/faq.md b/docs/faq.md index 0cf9b8a..bd8a941 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -436,6 +436,37 @@ for the main thread to call functions defined in the worker in a non-blocking manner, thus allowing the worker to also work in an unblocked manner and react to such calls. We have resolved the mutual deadlock. +### TypeError: crypto.randomUUID is not a function + +If PyScript fails to start and you look in the browser console, you may +find the following error: + +!!! failure + + ``` + main.js:43 Uncaught TypeError: crypto.randomUUID is not a function + at main.js:43:26 + ``` + +#### When + +This happens because PyScript uses the `crypto.randomUUID` function, and the +web page isn't served correctly. + +#### Why + +This error is _created by the browser_ because `crypto.randomUUID` requires a +secure context or localhost to use the latest web standards that are part of +PyScript's core (such as `crypto.randomUUID`). + +Put simply, your code should be served from a domain secured +with TLS (i.e. the domain name starts with `https` - use a service like +[let's encrypt](https://letsencrypt.org/) to address this) or from `localhost` +if developing and viewing your site on your development machine. + +This is something PyScript can't fix. Rather, it's how the web works and you +should always ensure your code is served in a secure manner. + ## Helpful hints This section contains common hacks or hints to make using PyScript easier. From 7d04b26366455afd6fc8f4e137a2c4f1b66f23aa Mon Sep 17 00:00:00 2001 From: Neon22 <899355+Neon22@users.noreply.github.com> Date: Sat, 25 Jan 2025 23:53:27 +1300 Subject: [PATCH 173/201] Update terminal.md Added example on resizing the terminal to take up less on-screen space --- docs/user-guide/terminal.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/user-guide/terminal.md b/docs/user-guide/terminal.md index 4b14c29..374d04f 100644 --- a/docs/user-guide/terminal.md +++ b/docs/user-guide/terminal.md @@ -111,6 +111,15 @@ It's very simple to clear a PyTerminal: ``` +### Resize the terminal + +The terminal takes up a fair amount of room onscreen. It can be resized to use less. +Here it is 10 lines high. +```python title="Resizing the terminal in python" +if '__terminal__' in locals(): # has a terminal been created + __terminal__.resize(60, 10) # (width, height) +``` + ### Terminal colors Colors and most special characters work so you can make the text **bold** or From 28cb196c141ab568513d97b23f9b7ee7a07ee2ab Mon Sep 17 00:00:00 2001 From: Neon22 <899355+Neon22@users.noreply.github.com> Date: Sun, 26 Jan 2025 00:06:31 +1300 Subject: [PATCH 174/201] Update api.md Add example of manually setting handler without a decorator --- docs/api.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/api.md b/docs/api.md index e5dceb3..d7214dd 100644 --- a/docs/api.md +++ b/docs/api.md @@ -653,6 +653,9 @@ def click_handler(event): them. """ display("I've been clicked!") + +### Or manually setting handler without a decorator +when("click", "#my-button", handler=click_handler) ``` This functionality is related to the `py-*` or `mpy-*` [HTML attributes](#html-attributes). From 3a36a50aa585543e2ae30fd5d78c23d9d15624f1 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Wed, 5 Feb 2025 13:06:33 +0000 Subject: [PATCH 175/201] Bump version number. --- docs/beginning-pyscript.md | 8 ++++---- docs/user-guide/first-steps.md | 4 ++-- docs/user-guide/plugins.md | 10 +++++----- docs/user-guide/workers.md | 4 ++-- version.json | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/beginning-pyscript.md b/docs/beginning-pyscript.md index 460d4d9..ef46c59 100644 --- a/docs/beginning-pyscript.md +++ b/docs/beginning-pyscript.md @@ -117,8 +117,8 @@ module in the document's `` tag: Codestin Search App - - + + @@ -168,8 +168,8 @@ In the end, our HTML should look like this: Codestin Search App - - + +

Polyglot 🦜 💬 🇬🇧 ➡️ 🏴‍☠️

diff --git a/docs/user-guide/first-steps.md b/docs/user-guide/first-steps.md index ddc0005..0013235 100644 --- a/docs/user-guide/first-steps.md +++ b/docs/user-guide/first-steps.md @@ -20,9 +20,9 @@ CSS: - + - + diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md index e534880..4769a44 100644 --- a/docs/user-guide/plugins.md +++ b/docs/user-guide/plugins.md @@ -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/2024.11.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2025.2.1/core.js"; hooks.worker.onReady.add(() => { // NOT suggested, just an example! @@ -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/2024.11.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2025.2.1/core.js"; // NO NO NO NO NO! ☠️ let i = 0; @@ -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/2024.11.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2025.2.1/core.js"; // The `hooks.main` attribute defines plugins that run on the main thread. hooks.main.onReady.add((wrap, element) => { @@ -197,8 +197,8 @@ hooks.worker.onAfterRun.add(() => { - - + + + Codestin Search App diff --git a/version.json b/version.json index 03caaca..d4e0b62 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2024.11.1" + "version": "2025.2.1" } From 74ac97de28df97d76d17022e1535f28ea32774f2 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Wed, 5 Feb 2025 13:48:20 +0000 Subject: [PATCH 176/201] PyGame-CE docs. --- docs/user-guide/pygame-ce.md | 56 ++++++++++++++++++++++++++++++++++++ mkdocs.yml | 1 + 2 files changed, 57 insertions(+) create mode 100644 docs/user-guide/pygame-ce.md diff --git a/docs/user-guide/pygame-ce.md b/docs/user-guide/pygame-ce.md new file mode 100644 index 0000000..58eebdc --- /dev/null +++ b/docs/user-guide/pygame-ce.md @@ -0,0 +1,56 @@ +# PyGame Support + +!!! Danger + + **Support for PyGame-CE is experimental** and its behaviour is likely to + change as we get feedback and bug reports from the community. + + Please bear this in mind as you try PyGame-CE with PyScript, and all + feedback, bug reports and constructive critique is welcome via discord + or GitHub. + + +[PyGameCE](https://pyga.me/) is a Python library for building powerful games +(so says their website). They also say, to get started you just need to +`pip install pygame-ce`. + +Thanks to work in the upstream [Pyodide project](https://pyodide.org/) +PyGame-CE is available in PyScript and to get started all you need to do is: +`` Now you don't even need to +`pip install` the library! It comes with PyScript by default, and you can share +your games via a URL! + +!!! Info + + Please refer to + [PyGame-CE's extensive documentation](https://pyga.me/docs/) for how to + create a game. Some things may not work because we're running in a + browser context, but play around and let us know how you get on. + +## How it works + +When a `` element is found on the page a +Pyodide instance is bootstrapped with the `pygame-ce` package already included. +Differently from other scripts, `py-game` cannot currently work through a +worker and it uses an optional target attribute to define the `` +element id that will be used to render the game. If no target attribute is +defined, the script assumes there is a `` element already +on the page. + +A config attribute can be specified to add extra packages but right now that's +all it can do. + +This is an experiment, but: + +* It is possible to use regular PyScript to load the pygame-ce package and use + all the other features. But there be dragons! This helper simply allows + multiple games on a page and forces game logic to run on the main thread to + reduce confusion around attributes and features when the `pygame-ce` package + is meant to be used. Put simply, we make it relatively safe and easy to use. +* The fact `pygame-ce` is the default "game engine" does not mean in the future + PyScript won't have other engines also available. +* Once again, as this is an experiment, we welcome any kind of feedback, + suggestions, hints on how to improve or reports of what's missing. + +Other than that, please go make and share wonderful games. We can't wait to see +what you come up with. diff --git a/mkdocs.yml b/mkdocs.yml index 8733bc3..44eb83a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -74,6 +74,7 @@ nav: - The FFI in detail: user-guide/ffi.md - Python terminal: user-guide/terminal.md - Python editor: user-guide/editor.md + - PyGame-CE: user-guide/pygame-ce.md - Plugins: user-guide/plugins.md - Use Offline: user-guide/offline.md - Built-in APIs: api.md From 37540fe3a432c8ac7c3e2342c1f1d2c480e51dc6 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Thu, 6 Feb 2025 09:36:03 +0000 Subject: [PATCH 177/201] Fix the bullet point indentation on the examples page. --- docs/examples.md | 68 ++++++++++++++++++------------------------------ 1 file changed, 25 insertions(+), 43 deletions(-) diff --git a/docs/examples.md b/docs/examples.md index 06dc0a8..049ebc9 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -8,72 +8,54 @@ The examples are (links take you to the code): ### Simple: * [Hello world](https://pyscript.com/@examples/hello-world/latest) - * uses included datetime module. No additional packages. + * uses included datetime module. No additional packages. * [WebGL Icosahedron](https://pyscript.com/@examples/webgl-icosahedron/latest) - * uses [three.js](https://threejs.org/) imported as a module in toml) + * uses [three.js](https://threejs.org/) imported as a module in toml) * [Pandas dataframe fun](https://pyscript.com/@examples/pandas/latest) - * uses [pandas](https://pandas.pydata.org/) from pypi - * pyodide + * uses [pandas](https://pandas.pydata.org/) from pypi * [Matplotlib example](https://pyscript.com/@examples/matplotlib/latest) - * uses [matplotlib](https://matplotlib.org/) - * pyodide + * uses [matplotlib](https://matplotlib.org/) * [Todo](https://pyscript.com/@examples/todo-app/latest) - * uses pyweb. No additional packages. - * pyodide + * uses pyweb. No additional packages. * [Tic Tac Toe](https://pyscript.com/@examples/tic-tac-toe/latest) - * uses pyweb. No additional packages. - * pyodide + * uses pyweb. No additional packages. * [Pyscript Jokes](https://pyscript.com/@examples/pyscript-jokes/latest) - * uses pyweb and [pyjokes](https://pyjok.es/) - * pyodide + * uses pyweb and [pyjokes](https://pyjok.es/) * [D3 visualization](https://pyscript.com/@examples/d3-visualization/latest) - * uses [d3](https://d3js.org/) - * mixes javascript code with python code. imports d3 from javascript. - * pyodide + * uses [d3](https://d3js.org/) + * mixes javascript code with python code. imports d3 from javascript. * [Import antigravity](https://pyscript.com/@examples/antigravity/latest) - * uses svg simply - * pyodide + * uses svg simply * [API proxy tutorial](https://pyscript.com/@examples/api-proxy-tutorial/latest) - * uses fetch - * pyodide + * uses fetch * [API proxy and secrets tutorial](https://pyscript.com/@examples/api-proxy-and-secrets-tutorial/latest) - * uses fetch - * pyodide + * uses fetch ### More complex: * [Numpy fractals](https://pyscript.com/@examples/fractals-with-numpy-and-canvas/latest) - * uses [numpy](https://numpy.org/), [sympy](https://www.sympy.org/en/index.html) from pypi - * pyodide + * uses [numpy](https://numpy.org/), [sympy](https://www.sympy.org/en/index.html) from pypi * [Simple slider panel](https://pyscript.com/@examples/simple-panel/latest) - * uses [Panel](https://panel.holoviz.org/) and [Bokeh](https://bokeh.org/) from pypi and loads in index.html - * pyodide + * uses [Panel](https://panel.holoviz.org/) and [Bokeh](https://bokeh.org/) from pypi and loads in index.html * [Streaming data panel](https://pyscript.com/@examples/streaming-in-panel/latest) - * uses [Panel](https://panel.holoviz.org/), [Bokeh](https://bokeh.org/) [numpy](https://numpy.org/), [pandas](https://pandas.pydata.org/) from pypi - * loads bokeh, panel, tabulator in index.html - * pyodide + * uses [Panel](https://panel.holoviz.org/), [Bokeh](https://bokeh.org/) [numpy](https://numpy.org/), [pandas](https://pandas.pydata.org/) from pypi + * loads bokeh, panel, tabulator in index.html * [KMeans in a panel](https://pyscript.com/@examples/kmeans-in-panel/latest) * uses [Bokeh](https://bokeh.org/), [altair](https://altair-viz.github.io/), [numpy](https://numpy.org/), [pandas](https://pandas.pydata.org/), [scikit-learn](https://scikit-learn.org/stable/), [Panel](https://panel.holoviz.org/) from pypi - * loads panel, bootstrap, vega, tabulator, bokeh in index.html - * pyodide + * loads panel, bootstrap, vega, tabulator, bokeh in index.html * [New York Taxi panel (WebGL)](https://pyscript.com/@examples/nyc-taxi-panel-deckgl/latest) - * uses a mixture of pypi and direct load packages in index.html - * [Bokeh](https://bokeh.org/), [numpy](https://numpy.org/), [pandas](https://pandas.pydata.org/), [Panel](https://panel.holoviz.org/), [deck-gl](https://deck.gl/) - * deckGL, bokeh are loaded directly in index.html - * pyodide + * uses a mixture of pypi and direct load packages in index.html + * [Bokeh](https://bokeh.org/), [numpy](https://numpy.org/), [pandas](https://pandas.pydata.org/), [Panel](https://panel.holoviz.org/), [deck-gl](https://deck.gl/) + * deckGL, bokeh are loaded directly in index.html * [Folium geographical data](https://pyscript.com/@examples/folium/latest) - * uses [folium](https://python-visualization.github.io/folium/latest/), [pandas](https://pandas.pydata.org/) from pypi - * pyodide + * uses [folium](https://python-visualization.github.io/folium/latest/), [pandas](https://pandas.pydata.org/) from pypi * [Bokeh data plotting](https://pyscript.com/@examples/bokeh/latest) - * uses [pandas](https://pandas.pydata.org/), [Bokeh](https://bokeh.org/), [xyzservices](https://github.com/geopandas/xyzservices) from pypi - * pyodide + * uses [pandas](https://pandas.pydata.org/), [Bokeh](https://bokeh.org/), [xyzservices](https://github.com/geopandas/xyzservices) from pypi * [Altair data plotting](https://pyscript.com/@examples/altair/latest) - * uses [altair](https://altair-viz.github.io/), [pandas](https://pandas.pydata.org/), [vega_datasets](https://github.com/altair-viz/vega_datasets) from pypi - * pyodide + * uses [altair](https://altair-viz.github.io/), [pandas](https://pandas.pydata.org/), [vega_datasets](https://github.com/altair-viz/vega_datasets) from pypi * [Panel and hyplot](https://pyscript.com/@examples/panel-and-hvplot/latest) - * uses [Bokeh](https://bokeh.org/), [Panel](https://panel.holoviz.org/), [markdown-it-py](https://github.com/executablebooks/markdown-it-py), [numpy](https://numpy.org/), [pandas](https://pandas.pydata.org/), [hvplot](https://hvplot.holoviz.org/), [pyodide-http](https://pyodide.org/en/stable/usage/api/python-api/http.html) a fetch library. - * bokeh and panel are loaded in the index.html - * pyodide + * uses [Bokeh](https://bokeh.org/), [Panel](https://panel.holoviz.org/), [markdown-it-py](https://github.com/executablebooks/markdown-it-py), [numpy](https://numpy.org/), [pandas](https://pandas.pydata.org/), [hvplot](https://hvplot.holoviz.org/), [pyodide-http](https://pyodide.org/en/stable/usage/api/python-api/http.html) a fetch library. + * bokeh and panel are loaded in the index.html Notes: - No micropython examples - all are pyodide From db3f9cddd191f628e5f93f559c04b14452985de9 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Fri, 7 Feb 2025 08:53:20 +0000 Subject: [PATCH 178/201] Bump version to 2025.2.2 --- docs/beginning-pyscript.md | 8 ++++---- docs/user-guide/first-steps.md | 4 ++-- docs/user-guide/plugins.md | 10 +++++----- docs/user-guide/workers.md | 4 ++-- version.json | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/beginning-pyscript.md b/docs/beginning-pyscript.md index ef46c59..d153bdf 100644 --- a/docs/beginning-pyscript.md +++ b/docs/beginning-pyscript.md @@ -117,8 +117,8 @@ module in the document's `` tag: Codestin Search App - - + + @@ -168,8 +168,8 @@ In the end, our HTML should look like this: Codestin Search App - - + +

Polyglot 🦜 💬 🇬🇧 ➡️ 🏴‍☠️

diff --git a/docs/user-guide/first-steps.md b/docs/user-guide/first-steps.md index 0013235..7fcd843 100644 --- a/docs/user-guide/first-steps.md +++ b/docs/user-guide/first-steps.md @@ -20,9 +20,9 @@ CSS: - + - + diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md index 4769a44..baf094e 100644 --- a/docs/user-guide/plugins.md +++ b/docs/user-guide/plugins.md @@ -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.2.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2025.2.2/core.js"; hooks.worker.onReady.add(() => { // NOT suggested, just an example! @@ -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.2.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2025.2.2/core.js"; // NO NO NO NO NO! ☠️ let i = 0; @@ -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.2.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2025.2.2/core.js"; // The `hooks.main` attribute defines plugins that run on the main thread. hooks.main.onReady.add((wrap, element) => { @@ -197,8 +197,8 @@ hooks.worker.onAfterRun.add(() => { - - + + + Codestin Search App diff --git a/version.json b/version.json index d4e0b62..d05966c 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2025.2.1" + "version": "2025.2.2" } From 84d8a44643d2297162e3d90d982c8ad9e68248e4 Mon Sep 17 00:00:00 2001 From: Dan Yeaw Date: Wed, 12 Feb 2025 10:49:19 -0500 Subject: [PATCH 179/201] Fix paths in files config examples --- docs/user-guide/configuration.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/user-guide/configuration.md b/docs/user-guide/configuration.md index 57ce73d..f036330 100644 --- a/docs/user-guide/configuration.md +++ b/docs/user-guide/configuration.md @@ -131,7 +131,7 @@ The following JSON and TOML are equivalent: { "files": { "https://example.com/data.csv": "./data.csv", - "/code.py": "./subdir/code.py" + "./code.py": "./subdir/code.py" } } ``` @@ -139,7 +139,7 @@ The following JSON and TOML are equivalent: ```toml title="Fetch files onto the filesystem with TOML." [files] "https://example.com/data.csv" = "./data.csv" -"/code.py" = "./subdir/code.py" +"./code.py" = "./subdir/code.py" ``` If you make the target an empty string, the final "filename" part of the source @@ -151,7 +151,7 @@ examples could be equivalently re-written as: { "files": { "https://example.com/data.csv": "", - ... etc ... + "./code.py": "" } } ``` @@ -159,7 +159,7 @@ examples could be equivalently re-written as: ```toml title="TOML implied filename in the root directory." [files] "https://example.com/data.csv" = "" -... etc ... +"./code.py" = "" ``` If the source part of the configuration is either a `.zip` or `.tar.gz` file From e926abc475b1dee62cad778847f3b352bbbbaa0d Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Mon, 17 Feb 2025 10:03:58 +0000 Subject: [PATCH 180/201] bump version --- docs/beginning-pyscript.md | 8 ++++---- docs/user-guide/first-steps.md | 4 ++-- docs/user-guide/plugins.md | 10 +++++----- docs/user-guide/workers.md | 4 ++-- version.json | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/beginning-pyscript.md b/docs/beginning-pyscript.md index d153bdf..38da6ac 100644 --- a/docs/beginning-pyscript.md +++ b/docs/beginning-pyscript.md @@ -117,8 +117,8 @@ module in the document's `` tag: Codestin Search App - - + + @@ -168,8 +168,8 @@ In the end, our HTML should look like this: Codestin Search App - - + +

Polyglot 🦜 💬 🇬🇧 ➡️ 🏴‍☠️

diff --git a/docs/user-guide/first-steps.md b/docs/user-guide/first-steps.md index 7fcd843..abe37f8 100644 --- a/docs/user-guide/first-steps.md +++ b/docs/user-guide/first-steps.md @@ -20,9 +20,9 @@ CSS: - + - + diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md index baf094e..7aed1cb 100644 --- a/docs/user-guide/plugins.md +++ b/docs/user-guide/plugins.md @@ -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.2.2/core.js"; +import { hooks } from "https://pyscript.net/releases/2025.2.3/core.js"; hooks.worker.onReady.add(() => { // NOT suggested, just an example! @@ -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.2.2/core.js"; +import { hooks } from "https://pyscript.net/releases/2025.2.3/core.js"; // NO NO NO NO NO! ☠️ let i = 0; @@ -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.2.2/core.js"; +import { hooks } from "https://pyscript.net/releases/2025.2.3/core.js"; // The `hooks.main` attribute defines plugins that run on the main thread. hooks.main.onReady.add((wrap, element) => { @@ -197,8 +197,8 @@ hooks.worker.onAfterRun.add(() => { - - + + + Codestin Search App diff --git a/version.json b/version.json index d05966c..142d482 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2025.2.2" + "version": "2025.2.3" } From b0b3e7b134b58dc8e7bca8c6410cedda506bcc91 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Mon, 17 Feb 2025 13:14:08 +0000 Subject: [PATCH 181/201] Docs for pyscript.fs --- docs/api.md | 60 +++++++++++ docs/user-guide/configuration.md | 8 +- docs/user-guide/filesystem.md | 175 +++++++++++++++++++++++++++++++ mkdocs.yml | 1 + 4 files changed, 241 insertions(+), 3 deletions(-) create mode 100644 docs/user-guide/filesystem.md diff --git a/docs/api.md b/docs/api.md index e5dceb3..515e0e9 100644 --- a/docs/api.md +++ b/docs/api.md @@ -331,6 +331,66 @@ is explicitly specified and the runtime is Pyodide. The technical details of how this works are [described here](../user-guide/ffi#to_js). +### `pyscript.fs` + +!!! danger + + This API only works in Chromium based browsers. + +An API for mounting the user's local filesystem to a designated directory in +the browser's virtual filesystem. Please see +[the filesystem](../user-guide/filesystem) section of the user-guide for more +information. + +#### `pyscript.fs.mount` + +Mount a directory on the user's local filesystem into the browser's virtual +filesystem. If no previous transient user activation has taken place, this +function will result in a minimalist dialog to provide the +[transient user activation](https://developer.mozilla.org/en-US/docs/Glossary/Transient_activation). + +This asynchronous function takes four arguments: + +* `path` (required) - indicating the location on the in-browser filesystem to + which the user selected directory from the local filesystem will be mounted. +* `mode` (default: `"readwrite"`) - indicates how the code may interact with + the mounted filesystem. May also be just `"read"` for read-only access. +* `id` (default: `"pyscript"`) - indicate a unique name for the handler + associated with a directory on the user's local filesystem. +* `root` (default: `""`) - a hint to the browser for where to start picking the + path that should be mounted in Python. Valid values are: `desktop`, + `documents`, `downloads`, `music`, `pictures` or `videos` as per + [web standards](https://developer.mozilla.org/en-US/docs/Web/API/Window/showDirectoryPicker#startin). + +```python title="Mount a local directory to the '/local' directory in the browser's virtual filesystem" +from pyscript import fs + + +# May ask for permission from the user, and select the local target. +await fs.mount("/local") +``` + +#### `pyscript.fs.sync` + +Given a named `path` for a mount point on the browser's virtual filesystem, +asynchronously ensure the virtual and local directories are synchronised (i.e. +all changes made in the browser's mounted filesystem, are propagated to the +user's local filesystem). + +```python title="Synchronise the virtual and local filesystems." +await fs.sync("/local") +``` + +#### `pyscript.fs.unmount` + +Asynchronously unmount the named `path` from the browser's virtual filesystem. +This will free up memory. A call to [`fs.sync`](#pyscriptfssync) is +automatically made before unmounting. + +```python title="Unmount from the virtual filesystem." +await fs.unmount("/local") +``` + ### `pyscript.js_modules` It is possible to [define JavaScript modules to use within your Python code](../user-guide/configuration#javascript-modules). diff --git a/docs/user-guide/configuration.md b/docs/user-guide/configuration.md index f036330..7766403 100644 --- a/docs/user-guide/configuration.md +++ b/docs/user-guide/configuration.md @@ -121,9 +121,11 @@ version of Pyodide as specified in the previous examples: ### Files -The `files` option fetches arbitrary content from URLs onto the filesystem -available to Python, and emulated by the browser. Just map a valid URL to a -destination filesystem path. +The `files` option fetches arbitrary content from URLs onto the virtual +filesystem available to Python, and emulated by the browser. Just map a valid +URL to a destination filesystem path on the in-browser virtual filesystem. You +can find out more in the section about +[PyScript and filesystems](../filesystem/). The following JSON and TOML are equivalent: diff --git a/docs/user-guide/filesystem.md b/docs/user-guide/filesystem.md new file mode 100644 index 0000000..1dbc8d7 --- /dev/null +++ b/docs/user-guide/filesystem.md @@ -0,0 +1,175 @@ +# PyScript and Filesystems + +As you know, the filesystem is where you store files. For Python to work there +needs to be a filesystem in which Python packages, modules and data for your +apps can be found. When you `import` a library, or when you `open` a file, it +is on the filesystem that Python looks. + +However, things are not as they may seem. + +This section clarifies what PyScript means by a filesystem, and the way in +which PyScript interacts with such a concept. + +## Two filesystems + +PyScript interacts with two filesystems. + +1. The browser, thanks to + [Emscripten](https://emscripten.org/docs/api_reference/Filesystem-API.html), + provides a virtual in-memory filesystem. **This has nothing to do with your + device's local filesystem**, but is contained within the browser based + sandbox used by PyScript. The [files](../configuration/#files) + configuration API defines what is found on this filesystem. +2. PyScript provides an easy to use API for accessing your device's local + filesystem. It requires permission from the user to mount a folder from the + local filesystem onto a directory in the browser's virtual filesystem. Think + of it as gate-keeping a bridge to the outside world of the device's local + filesystem. + +!!! danger + + Access to the device's local filesystem **is only available in Chromium + based browsers**. + + Firefox and Safari do not support this capability, and so it is not + available to PyScript running in these browsers. + +## The in-browser filesystem + +The filesystem that both Pyodide and MicroPython use by default is the +[in-browser virtual filesystem](https://emscripten.org/docs/api_reference/Filesystem-API.html). +Opening files and importing modules takes place in relation to this sandboxed +environment, configured via the [files](../configuration/#files) entry in your +settings. + +```toml title="Filesystem configuration via TOML." +[files] +"https://example.com/myfile.txt": "" +``` + +```python title="Just use the resulting file 'as usual'." +# Interacting with the virtual filesystem, "as usual". +with open("myfile.txt", "r") as myfile: + print(myfile.read()) +``` + +Currently, each time you re-load the page, the filesystem is recreated afresh, +so any data stored by PyScript to this filesystem will be lost. + +!!! info + + In the future, we may make it possible to configure the in-browser virtual + filesystem as persistent across re-loads. + +[This article](https://emscripten.org/docs/porting/files/file_systems_overview.html) +gives an excellent overview of the browser based virtual filesystem's +implementation and architecture. + +The most important key concepts to remember are: + +* The PyScript filesystem is contained *within* the browser's sandbox. +* Each instance of a Python interpreter used by PyScript runs in a separate + sandbox, and so does NOT share virtual filesystems. +* All Python related filesytem operations work as expected with this + filesystem. +* The virtual filesystem is configured via the + [files](../configuration/#files) entry in your settings. +* The virtual filesystem is (currently) NOT persistent between page re-loads. +* Currently, the filesystem has a maximum capacity of 4GB of data (something + over which we have no control). + +## The device's local filesystem + +**Access to the device's local filesystem currently only works on Chromium +based browsers**. + +Your device (the laptop, mobile or tablet) that runs your browser has a +filesystem provided by a hard drive. Thanks to the +[`pyscript.fs` namespace in our API](../../api/#pyscriptfs), both MicroPython +and Pyodide (CPython) gain access to this filesystem should the user of +your code allow this to happen. + +This is a [transient activation](https://developer.mozilla.org/en-US/docs/Glossary/Transient_activation) +for the purposes of +[user activation of gated features](https://developer.mozilla.org/en-US/docs/Web/Security/User_activation). +Put simply, before your code gains access to their local filesystem, an +explicit agreement needs to be gathered from the user. Part of this process +involves asking the user to select a target directory on their local +filesystem, to which PyScript will be given access. + +The directory on their local filesystem, selected by the user, is then mounted +to a given directory inside the browser's virtual filesystem. In this way a +mapping is made between the sandboxed world of the browser, and the outside +world of the user's filesystem. + +Your code will then be able to perform all the usual filesystem related +operations provided by Python, within the mounted directory. However, **such +changes will NOT take effect on the local filesystem UNTIL your code +explicitly calls the `sync` function**. At this point, the state of the +in-browser virtual filesystem and the user's local filesystem are synchronised. + +The following code demonstrates the simplest use case: + +```python title="The core operations of the pyscript.fs API" +from pyscript import fs + +# Ask once for permission to mount any local folder +# into the virtual filesystem handled by Pyodide/MicroPython. +# The folder "/local" refers to the directory on the virtual +# filesystem to which the user-selected directory will be +# mounted. +await fs.mount("/local") + +# ... DO FILE RELATED OPERATIONS HERE ... + +# If changes were made, ensure these are persisted to the local filesystem's +# folder. +await fs.sync("/local") + +# If needed to free RAM or that specific path, sync and unmount +await fs.unmount("/local") +``` + +It is possible to use multiple different local directories with the same mount +point. This is important if your application provides some generic +functionality on data that might be in different local directories because +while the nature of the data might be similar, the subject is not. For +instance, you may have different models for a PyScript based LLM in different +directories, and may wish to switch between them at runtime using different +handlers (requiring their own transient action). In which case use +the following technique: + +```python title="Multiple local directories on the same mount point" +# Mount a local folder specifying a different handler. +# This requires a user explicit transient action (once). +await fs.mount("/local", id="v1") +# ... operate on that folder ... +await fs.unmount("/local") + +# Mount a local folder specifying a different handler. +# This also requires a user explicit transient action (once). +await fs.mount("/local", id="v2") +# ... operate on that folder ... +await fs.unmount("/local") + +# Go back to the original handler or a previous one. +# No transient action required now. +await fs.mount("/local", id="v1") +# ... operate again on that folder ... +``` + +In addition to the mount `path` and handler `id`, the `fs.mount` function can +take two further arguments: + +* `mode` (by default `"readwrite"`) indicates the sort of activity available to + the user. It can also be set to `read` for read-only access to the local + filesystem. This is a part of the + [web-standards](https://developer.mozilla.org/en-US/docs/Web/API/Window/showDirectoryPicker#mode) + for directory selection. +* `root` - (by default, `""`) is a hint to the browser for where to start + picking the path that should be mounted in Python. Valid values are: + `desktop`, `documents`, `downloads`, `music`, `pictures` or `videos` + [as per web standards](https://developer.mozilla.org/en-US/docs/Web/API/Window/showDirectoryPicker#startin). + +The `sync` and `unmount` functions only accept the mount `path` used in the +browser's local filesystem. diff --git a/mkdocs.yml b/mkdocs.yml index 44eb83a..3757deb 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -72,6 +72,7 @@ nav: - The DOM & JavaScript: user-guide/dom.md - Web Workers: user-guide/workers.md - The FFI in detail: user-guide/ffi.md + - PyScript and filesystems: user-guide/filesystem.md - Python terminal: user-guide/terminal.md - Python editor: user-guide/editor.md - PyGame-CE: user-guide/pygame-ce.md From a77ab667373431053eb9d0ca6f618c456b2b2dc2 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Mon, 17 Feb 2025 14:37:54 +0000 Subject: [PATCH 182/201] Fixes for Andrea. --- docs/api.md | 32 ++++++++++++++++++++++++++------ docs/user-guide/filesystem.md | 4 ++-- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/docs/api.md b/docs/api.md index 515e0e9..66a1f6e 100644 --- a/docs/api.md +++ b/docs/api.md @@ -345,9 +345,10 @@ information. #### `pyscript.fs.mount` Mount a directory on the user's local filesystem into the browser's virtual -filesystem. If no previous transient user activation has taken place, this -function will result in a minimalist dialog to provide the -[transient user activation](https://developer.mozilla.org/en-US/docs/Glossary/Transient_activation). +filesystem. If no previous +[transient user activation](https://developer.mozilla.org/en-US/docs/Glossary/Transient_activation) +has taken place, this function will result in a minimalist dialog to provide +the required transient user activation. This asynchronous function takes four arguments: @@ -356,7 +357,9 @@ This asynchronous function takes four arguments: * `mode` (default: `"readwrite"`) - indicates how the code may interact with the mounted filesystem. May also be just `"read"` for read-only access. * `id` (default: `"pyscript"`) - indicate a unique name for the handler - associated with a directory on the user's local filesystem. + associated with a directory on the user's local filesystem. This allows users + to select different folders and mount them at the same path in the + virtual filesystem. * `root` (default: `""`) - a hint to the browser for where to start picking the path that should be mounted in Python. Valid values are: `desktop`, `documents`, `downloads`, `music`, `pictures` or `videos` as per @@ -370,6 +373,23 @@ from pyscript import fs await fs.mount("/local") ``` +If the call to `fs.mount` happens after a click or other transient event, the +confirmation dialog will not be shown. + +```python title="Mounting without a transient event dialog." +from pyscript import fs + + +async def handler(event): + """ + The click event that calls this handler is already a transient event. + """ + await fs.mount("/local") + + +my_button.onclick = handler +``` + #### `pyscript.fs.sync` Given a named `path` for a mount point on the browser's virtual filesystem, @@ -384,8 +404,8 @@ await fs.sync("/local") #### `pyscript.fs.unmount` Asynchronously unmount the named `path` from the browser's virtual filesystem. -This will free up memory. A call to [`fs.sync`](#pyscriptfssync) is -automatically made before unmounting. +This will free up memory and allow you to re-use the path to mount a different +directory. ```python title="Unmount from the virtual filesystem." await fs.unmount("/local") diff --git a/docs/user-guide/filesystem.md b/docs/user-guide/filesystem.md index 1dbc8d7..a7c824b 100644 --- a/docs/user-guide/filesystem.md +++ b/docs/user-guide/filesystem.md @@ -3,7 +3,7 @@ As you know, the filesystem is where you store files. For Python to work there needs to be a filesystem in which Python packages, modules and data for your apps can be found. When you `import` a library, or when you `open` a file, it -is on the filesystem that Python looks. +is on the in-browser virtual filesystem that Python looks. However, things are not as they may seem. @@ -31,7 +31,7 @@ PyScript interacts with two filesystems. Access to the device's local filesystem **is only available in Chromium based browsers**. - Firefox and Safari do not support this capability, and so it is not + Firefox and Safari do not support this capability (yet), and so it is not available to PyScript running in these browsers. ## The in-browser filesystem From f4daf4d9f9abc4e0c779a840e22dfeb29728815d Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Mon, 17 Feb 2025 14:39:57 +0000 Subject: [PATCH 183/201] Minor nit --- docs/api.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/api.md b/docs/api.md index 66a1f6e..869535f 100644 --- a/docs/api.md +++ b/docs/api.md @@ -403,9 +403,9 @@ await fs.sync("/local") #### `pyscript.fs.unmount` -Asynchronously unmount the named `path` from the browser's virtual filesystem. -This will free up memory and allow you to re-use the path to mount a different -directory. +Asynchronously unmount the named `path` from the browser's virtual filesystem +after ensuring content is synchronized. This will free up memory and allow you +to re-use the path to mount a different directory. ```python title="Unmount from the virtual filesystem." await fs.unmount("/local") From 881124bf9701d384e936c09bca166c898679e354 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Mon, 17 Feb 2025 15:24:29 +0000 Subject: [PATCH 184/201] Add important warning about max FS size. --- docs/user-guide/filesystem.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/user-guide/filesystem.md b/docs/user-guide/filesystem.md index a7c824b..b82de37 100644 --- a/docs/user-guide/filesystem.md +++ b/docs/user-guide/filesystem.md @@ -29,7 +29,8 @@ PyScript interacts with two filesystems. !!! danger Access to the device's local filesystem **is only available in Chromium - based browsers**. + based browsers**. The maximum capacity for files shared in this way is + 4GB, and **if this size is exceeded may result in lost data**. Firefox and Safari do not support this capability (yet), and so it is not available to PyScript running in these browsers. From 3c1944973fa4cae013304b508de686fb38d265fb Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Mon, 17 Feb 2025 16:05:40 +0000 Subject: [PATCH 185/201] The donkey is an async donkey. --- docs/api.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/api.md b/docs/api.md index 85a9c87..4ef1526 100644 --- a/docs/api.md +++ b/docs/api.md @@ -499,17 +499,17 @@ store = await storage("my-data-store", storage_class=MyStorage) ### `@pyscript/core/donkey` -Sometimes you need a Python worker ready and waiting to evaluate any code on -your behalf. This is the concept behind the JavaScript "donkey". We couldn't -think of a better way than "donkey" to describe something that is easy to -understand and shoulders the burden without complaint. This feature +Sometimes you need an asynchronous Python worker ready and waiting to evaluate +any code on your behalf. This is the concept behind the JavaScript "donkey". We +couldn't think of a better way than "donkey" to describe something that is easy +to understand and shoulders the burden without complaint. This feature means you're able to use PyScript without resorting to specialised ` + + @@ -168,8 +168,8 @@ In the end, our HTML should look like this: Codestin Search App - - + +

Polyglot 🦜 💬 🇬🇧 ➡️ 🏴‍☠️

diff --git a/docs/user-guide/first-steps.md b/docs/user-guide/first-steps.md index abe37f8..f0c20fc 100644 --- a/docs/user-guide/first-steps.md +++ b/docs/user-guide/first-steps.md @@ -20,9 +20,9 @@ CSS: - + - + diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md index 7aed1cb..9a353f0 100644 --- a/docs/user-guide/plugins.md +++ b/docs/user-guide/plugins.md @@ -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.2.3/core.js"; +import { hooks } from "https://pyscript.net/releases/2025.2.4/core.js"; hooks.worker.onReady.add(() => { // NOT suggested, just an example! @@ -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.2.3/core.js"; +import { hooks } from "https://pyscript.net/releases/2025.2.4/core.js"; // NO NO NO NO NO! ☠️ let i = 0; @@ -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.2.3/core.js"; +import { hooks } from "https://pyscript.net/releases/2025.2.4/core.js"; // The `hooks.main` attribute defines plugins that run on the main thread. hooks.main.onReady.add((wrap, element) => { @@ -197,8 +197,8 @@ hooks.worker.onAfterRun.add(() => { - - + + + Codestin Search App diff --git a/version.json b/version.json index 142d482..439bf46 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2025.2.3" + "version": "2025.2.4" } From 95523a9a828fdbd94246e0508196418e98f17d11 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Thu, 27 Feb 2025 09:45:01 +0000 Subject: [PATCH 187/201] Add section on py-editor stop button. --- docs/assets/images/pyeditor-stop.gif | Bin 0 -> 316524 bytes docs/user-guide/editor.md | 15 +++++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 docs/assets/images/pyeditor-stop.gif diff --git a/docs/assets/images/pyeditor-stop.gif b/docs/assets/images/pyeditor-stop.gif new file mode 100644 index 0000000000000000000000000000000000000000..8c0f0b7b2e754aa50b7540a8d0d6a54d230b460f GIT binary patch literal 316524 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J5U`D@C{yiA4 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 z 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 z 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/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

3zH?~a})qO67?=fWtgux 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 + ### Setup Sometimes you need to create a pre-baked Pythonic context for a shared From 52489cad7d205ed2ad712d5a143e3b7f9baa2fb5 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Thu, 27 Feb 2025 09:51:02 +0000 Subject: [PATCH 188/201] Remove the warning needed about data loss for files > 4GB. This has been fixed. --- docs/user-guide/filesystem.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user-guide/filesystem.md b/docs/user-guide/filesystem.md index b82de37..b977a3f 100644 --- a/docs/user-guide/filesystem.md +++ b/docs/user-guide/filesystem.md @@ -30,7 +30,7 @@ PyScript interacts with two filesystems. Access to the device's local filesystem **is only available in Chromium based browsers**. The maximum capacity for files shared in this way is - 4GB, and **if this size is exceeded may result in lost data**. + 4GB. Firefox and Safari do not support this capability (yet), and so it is not available to PyScript running in these browsers. From b19414ac04011b8dd78af085bce77246d68ce308 Mon Sep 17 00:00:00 2001 From: Dan Yeaw Date: Fri, 28 Feb 2025 09:40:18 -0500 Subject: [PATCH 189/201] Add conda dev environment instructions --- docs/developers.md | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/docs/developers.md b/docs/developers.md index 7ac7ab9..f6f031a 100644 --- a/docs/developers.md +++ b/docs/developers.md @@ -38,14 +38,10 @@ compassion wins every time. All contributors are expected to follow our [code of conduct](conduct.md). -## Setup - -**You must have recent versions of [Python](https://python.org/), -[node.js](https://nodejs.org/en) and [npm](https://www.npmjs.com/) already -installed on your system.** - +## Setup The following steps create a working development environment for PyScript. It -is through this environment that you contribute to PyScript. +is through this environment that you contribute to PyScript. You can choose +between two options for setting up your environment. !!! danger @@ -89,6 +85,34 @@ is through this environment that you contribute to PyScript. deactivate ``` +### Option 2: Create a conda environment +**This option will install Python and NodeJS for you, so you don't need to have them +pre-installed on your system.** + +* If you prefer using [conda](https://docs.conda.io/en/latest/) for environment management, +you can create a conda environment that includes both Python and NodeJS: +* + ```sh + conda create --name pyscript python nodejs + conda activate pyscript + ``` + + !!! warning + + Replace `pyscript` with a meaningful name for the conda environment, that works for you. + +* This creates a new environment with both Python and NodeJS installed. The prompt in your +terminal will change to include the name of your conda environment indicating the sandbox is active. +* To deactivate the conda environment just type the following into your terminal: + + ```sh + conda deactivate + ``` + +* If you don't have conda installed, you can download and install +[Miniconda, Miniforge](https://docs.conda.io/projects/conda), or +[Anaconda](https://www.anaconda.com/download). + !!! info The rest of the instructions on this page assume you are working in **an From e14e54bb184ae70045e21dee9860bbc7dee75943 Mon Sep 17 00:00:00 2001 From: Dan Yeaw Date: Fri, 28 Feb 2025 16:19:43 -0500 Subject: [PATCH 190/201] Add docs for the media API --- docs/api.md | 113 ++++++++++++ docs/user-guide/media.md | 372 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 485 insertions(+) create mode 100644 docs/user-guide/media.md diff --git a/docs/api.md b/docs/api.md index 4ef1526..8a992d3 100644 --- a/docs/api.md +++ b/docs/api.md @@ -423,6 +423,119 @@ Such named modules will always then be available under the Please see the documentation (linked above) about restrictions and gotchas when configuring how JavaScript modules are made available to PyScript. +### `pyscript.media` + +The `pyscript.media` namespace provides classes and functions for interacting +with media devices and streams in a web browser. This module enables you to work +with cameras, microphones, and other media input/output devices directly from +Python code. + +#### `pyscript.media.Device` + +A class that represents a media input or output device, such as a microphone, +camera, or headset. + +```python title="Creating a Device object" +from pyscript.media import Device, list_devices + +# List all available media devices +devices = await list_devices() +# Get the first available device +my_device = devices[0] +``` + +The `Device` class has the following properties: + +* `id` - a unique string identifier for the represented device. +* `group` - a string group identifier for devices belonging to the same physical device. +* `kind` - an enumerated value: "videoinput", "audioinput", or "audiooutput". +* `label` - a string describing the device (e.g., "External USB Webcam"). + +The `Device` class also provides the following methods: + +##### `Device.load(audio=False, video=True)` + +A class method that loads a media stream with the specified options. + +```python title="Loading a media stream" +# Load a video stream (default) +stream = await Device.load() + +# Load an audio stream only +stream = await Device.load(audio=True, video=False) + +# Load with specific video constraints +stream = await Device.load(video={"width": 1280, "height": 720}) +``` + +Parameters: +* `audio` (bool, default: False) - Whether to include audio in the stream. +* `video` (bool or dict, default: True) - Whether to include video in the + stream. Can also be a dictionary of video constraints. + +Returns: +* A media stream object that can be used with HTML media elements. + +##### `get_stream()` + +An instance method that gets a media stream from this specific device. + +```python title="Getting a stream from a specific device" +# Find a video input device +video_devices = [d for d in devices if d.kind == "videoinput"] +if video_devices: + # Get a stream from the first video device + stream = await video_devices[0].get_stream() +``` + +Returns: +* A media stream object from the specific device. + +#### `pyscript.media.list_devices()` + +An async function that returns a list of all currently available media input and +output devices. + +```python title="Listing all media devices" +from pyscript.media import list_devices + +devices = await list_devices() +for device in devices: + print(f"Device: {device.label}, Kind: {device.kind}") +``` + +Returns: +* A list of `Device` objects representing the available media devices. + +!!! Note + + The returned list will omit any devices that are blocked by the document + Permission Policy or for which the user has not granted permission. + +### Simple Example + +```python title="Basic camera access" +from pyscript import document +from pyscript.media import Device + +async def init_camera(): + # Get a video stream + stream = await Device.load(video=True) + + # Set the stream as the source for a video element + video_el = document.getElementById("camera") + video_el.srcObject = stream + +# Initialize the camera +init_camera() +``` + +!!! warning + + Using media devices requires appropriate permissions from the user. + Browsers will typically show a permission dialog when `list_devices()` or + `Device.load()` is called. + ### `pyscript.storage` The `pyscript.storage` API wraps the browser's built-in diff --git a/docs/user-guide/media.md b/docs/user-guide/media.md new file mode 100644 index 0000000..91e45a7 --- /dev/null +++ b/docs/user-guide/media.md @@ -0,0 +1,372 @@ +# PyScript and Media Devices + +For web applications to interact with cameras, microphones, and other media +devices, there needs to be a way to access these hardware components through the +browser. PyScript provides a media API that enables your Python code to interact +with media devices directly from the browser environment. + +This section explains how PyScript interacts with media devices and how you can +use these capabilities in your applications. + +## Media Device Access + +PyScript interacts with media devices through the browser's [MediaDevices +API](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices). This API +provides access to connected media input devices like cameras and microphones, +as well as output devices like speakers. + +When using PyScript's media API, it's important to understand: + +1. Media access requires **explicit user permission**. The browser will show a + permission dialog when your code attempts to access cameras or microphones. +2. Media access is only available in **secure contexts** (HTTPS or localhost). +3. All media interactions happen within the **browser's sandbox**, following the + browser's security policies. + +## The `pyscript.media` API + +PyScript provides a Pythonic interface to media devices through the +`pyscript.media` namespace. This API includes two main components: + +1. The `Device` class - represents a media device and provides methods to + interact with it +2. The `list_devices()` function - discovers available media devices + +### Listing Available Devices + +To discover what media devices are available, use the `list_devices()` function: + +```python +from pyscript.media import list_devices + +async def show_available_devices(): + devices = await list_devices() + for device in devices: + print(f"Device: {device.label}, Type: {device.kind}, ID: {device.id}") + +# List all available devices +show_available_devices() +``` + +This function returns a list of `Device` objects, each representing a media +input or output device. Note that the browser will typically request permission +before providing this information. + +### Working with the Camera + +The most common use case is accessing the camera to display a video stream: + +```python +from pyscript import when +from pyscript.media import Device +from pyscript.web import page + +async def start_camera(): + # Get a video stream (defaults to video only, no audio) + stream = await Device.load(video=True) + + # Connect the stream to a video element in your HTML + video_element = page["#camera"][0]._dom_element + video_element.srcObject = stream + + return stream + +# Start the camera +camera_stream = start_camera() +``` + +The `Device.load()` method is a convenient way to access media devices without +first listing all available devices. You can specify options to control which +camera is used: + +```python +# Prefer the environment-facing camera (often the back camera on mobile) +stream = await Device.load(video={"facingMode": "environment"}) + +# Prefer the user-facing camera (often the front camera on mobile) +stream = await Device.load(video={"facingMode": "user"}) + +# Request specific resolution +stream = await Device.load(video={ + "width": {"ideal": 1280}, + "height": {"ideal": 720} +}) +``` + +### Capturing Images from the Camera + +To capture a still image from the video stream: + +```python +def capture_image(video_element): + # Get the video dimensions + width = video_element.videoWidth + height = video_element.videoHeight + + # Create a canvas to capture the frame + canvas = document.createElement("canvas") + canvas.width = width + canvas.height = height + + # Draw the current video frame to the canvas + ctx = canvas.getContext("2d") + ctx.drawImage(video_element, 0, 0, width, height) + + # Get the image as a data URL + image_data = canvas.toDataURL("image/png") + + return image_data +``` + +For applications that need to process images with libraries like OpenCV, you +need to convert the image data to a format these libraries can work with: + +```python +import numpy as np +import cv2 + +def process_frame_with_opencv(video_element): + # Get video dimensions + width = video_element.videoWidth + height = video_element.videoHeight + + # Create a canvas and capture the frame + canvas = document.createElement("canvas") + canvas.width = width + canvas.height = height + ctx = canvas.getContext("2d") + ctx.drawImage(video_element, 0, 0, width, height) + + # Get the raw pixel data + image_data = ctx.getImageData(0, 0, width, height).data + + # Convert to numpy array for OpenCV + frame = np.asarray(image_data, dtype=np.uint8).reshape((height, width, 4)) + + # Convert from RGBA to BGR (OpenCV's default format) + frame_bgr = cv2.cvtColor(frame, cv2.COLOR_RGBA2BGR) + + # Process the image with OpenCV + # ... + + return frame_bgr +``` + +### Managing Camera Resources + +It's important to properly manage media resources, especially when your +application no longer needs them. Cameras and microphones are shared resources, +and failing to release them can impact other applications or cause unexpected +behavior. + +### Stopping the Camera + +To stop the camera and release resources: + +```python +from pyscript.web import page + +def stop_camera(stream): + # Stop all tracks on the stream + if stream: + tracks = stream.getTracks() + for track in tracks: + track.stop() + + # Clear the video element's source + video_element = page["#camera"][0]._dom_element + if video_element: + video_element.srcObject = None +``` + +### Switching Between Cameras + +For devices with multiple cameras, you can implement camera switching: + +```python +from pyscript.media import Device, list_devices +from pyscript.web import page + +class CameraManager: + def __init__(self): + self.cameras = [] + self.current_index = 0 + self.active_stream = None + self.video_element = page["#camera"][0]._dom_element + + async def initialize(self): + # Get all video input devices + devices = await list_devices() + self.cameras = [d for d in devices if d.kind == "videoinput"] + + # Start with the first camera + if self.cameras: + await self.start_camera(self.cameras[0].id) + + async def start_camera(self, device_id=None): + # Stop any existing stream + await self.stop_camera() + + # Start a new stream + video_options = ( + {"deviceId": {"exact": device_id}} if device_id + else {"facingMode": "environment"} + ) + self.active_stream = await Device.load(video=video_options) + + # Connect to the video element + if self.video_element: + self.video_element.srcObject = self.active_stream + + async def stop_camera(self): + if self.active_stream: + tracks = self.active_stream.getTracks() + for track in tracks: + track.stop() + self.active_stream = None + + if self.video_element: + self.video_element.srcObject = None + + async def switch_camera(self): + if len(self.cameras) <= 1: + return + + # Move to the next camera + self.current_index = (self.current_index + 1) % len(self.cameras) + await self.start_camera(self.cameras[self.current_index].id) +``` + +## Working with Audio + +In addition to video, the PyScript media API can access audio inputs: + +```python +# Get access to the microphone (audio only) +audio_stream = await Device.load(audio=True, video=False) + +# Get both audio and video +av_stream = await Device.load(audio=True, video=True) +``` + +## Best Practices + +When working with media devices in PyScript, follow these best practices: + +### Permissions and User Experience + +1. **Request permissions contextually**: + - Only request camera/microphone access when needed + - Explain to users why you need access before requesting it + - Provide fallback options when permissions are denied + +2. **Clear user feedback**: + - Indicate when the camera is active + - Provide controls to pause/stop the camera + - Show loading states while the camera is initializing + +### Resource Management + +1. **Always clean up resources**: + - Stop media tracks when they're not needed + - Clear `srcObject` references from video elements + - Be especially careful in single-page applications + +2. **Handle errors gracefully**: + - Catch exceptions when requesting media access + - Provide meaningful error messages + - Offer alternatives when media access fails + +### Performance Optimization + +1. **Match resolution to needs**: + - Use lower resolutions when possible + - Consider mobile device limitations + - Adjust video constraints based on the device + +2. **Optimize image processing**: + - Process frames on demand rather than continuously + - Use efficient algorithms + - Consider downsampling for faster processing + +## Example Application: Simple Camera Capture + +Here's a simplified example that shows how to capture and display images from a +camera: + +```python +from pyscript import when, window +from pyscript.media import Device +from pyscript.web import page + +class CameraCapture: + def __init__(self): + # Get UI elements + self.video = page["#camera"][0] + self.video_element = self.video._dom_element + self.capture_button = page["#capture-button"] + self.snapshot = page["#snapshot"][0] + + # Start camera + self.initialize_camera() + + async def initialize_camera(self): + # Prefer environment-facing camera on mobile devices + stream = await Device.load(video={"facingMode": "environment"}) + self.video_element.srcObject = stream + + def take_snapshot(self): + """Capture a frame from the camera and display it""" + # Get video dimensions + width = self.video_element.videoWidth + height = self.video_element.videoHeight + + # Create canvas and capture frame + canvas = window.document.createElement("canvas") + canvas.width = width + canvas.height = height + + # Draw the current video frame to the canvas + ctx = canvas.getContext("2d") + ctx.drawImage(self.video_element, 0, 0, width, height) + + # Convert the canvas to a data URL and display it + image_data_url = canvas.toDataURL("image/png") + self.snapshot.setAttribute("src", image_data_url) + +# HTML structure needed: +# +# +# + +# Usage: +# camera = CameraCapture() +# +# @when("click", "#capture-button") +# def handle_capture(event): +# camera.take_snapshot() +``` + +This example demonstrates: +- Initializing a camera with the PyScript media API +- Accessing the camera stream and displaying it in a video element +- Capturing a still image from the video stream when requested +- Converting the captured frame to an image that can be displayed + +This simple pattern can serve as the foundation for various camera-based +applications and can be extended with image processing libraries as needed for +more complex use cases. + + +## Conclusion + +The PyScript media API provides a powerful way to access and interact with +cameras and microphones directly from Python code running in the browser. By +following the patterns and practices outlined in this guide, you can build +sophisticated media applications while maintaining good performance and user +experience. + +Remember that media access is a sensitive permission that requires user consent +and should be used responsibly. Always provide clear indications when media +devices are active and ensure proper cleanup of resources when they're no longer +needed. From 8fbe97b95e627d43005b963b8581ac71e996fd94 Mon Sep 17 00:00:00 2001 From: Dan Yeaw Date: Tue, 4 Mar 2025 15:44:14 -0500 Subject: [PATCH 191/201] Add media page to navigation --- mkdocs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/mkdocs.yml b/mkdocs.yml index 3757deb..4487b51 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -75,6 +75,7 @@ nav: - PyScript and filesystems: user-guide/filesystem.md - Python terminal: user-guide/terminal.md - Python editor: user-guide/editor.md + - Media: user-guide/media.md - PyGame-CE: user-guide/pygame-ce.md - Plugins: user-guide/plugins.md - Use Offline: user-guide/offline.md From 1aad1bdf281539960b76094a5fb281affb7c870b Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Tue, 11 Mar 2025 11:31:15 +0000 Subject: [PATCH 192/201] Bump version number. --- docs/beginning-pyscript.md | 8 ++++---- docs/user-guide/first-steps.md | 4 ++-- docs/user-guide/plugins.md | 10 +++++----- docs/user-guide/workers.md | 4 ++-- version.json | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/beginning-pyscript.md b/docs/beginning-pyscript.md index d9a63e7..de3d931 100644 --- a/docs/beginning-pyscript.md +++ b/docs/beginning-pyscript.md @@ -117,8 +117,8 @@ module in the document's `` tag: Codestin Search App - - + + @@ -168,8 +168,8 @@ In the end, our HTML should look like this: Codestin Search App - - + +

Polyglot 🦜 💬 🇬🇧 ➡️ 🏴‍☠️

diff --git a/docs/user-guide/first-steps.md b/docs/user-guide/first-steps.md index f0c20fc..a97a2cf 100644 --- a/docs/user-guide/first-steps.md +++ b/docs/user-guide/first-steps.md @@ -20,9 +20,9 @@ CSS: - + - + diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md index 9a353f0..e49af88 100644 --- a/docs/user-guide/plugins.md +++ b/docs/user-guide/plugins.md @@ -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.2.4/core.js"; +import { hooks } from "https://pyscript.net/releases/2025.3.1/core.js"; hooks.worker.onReady.add(() => { // NOT suggested, just an example! @@ -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.2.4/core.js"; +import { hooks } from "https://pyscript.net/releases/2025.3.1/core.js"; // NO NO NO NO NO! ☠️ let i = 0; @@ -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.2.4/core.js"; +import { hooks } from "https://pyscript.net/releases/2025.3.1/core.js"; // The `hooks.main` attribute defines plugins that run on the main thread. hooks.main.onReady.add((wrap, element) => { @@ -197,8 +197,8 @@ hooks.worker.onAfterRun.add(() => { - - + + + Codestin Search App diff --git a/version.json b/version.json index 439bf46..4dd7ba3 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2025.2.4" + "version": "2025.3.1" } From 8e9415975625e8495c8488f1b233ca730ef6247e Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Tue, 11 Mar 2025 11:36:30 +0000 Subject: [PATCH 193/201] Info about input function in the main thread and JS prompts. --- docs/user-guide/pygame-ce.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/user-guide/pygame-ce.md b/docs/user-guide/pygame-ce.md index 58eebdc..a81766e 100644 --- a/docs/user-guide/pygame-ce.md +++ b/docs/user-guide/pygame-ce.md @@ -40,6 +40,17 @@ on the page. A config attribute can be specified to add extra packages but right now that's all it can do. +!!! Info + + Sometimes you need to gather text based user input when starting a game. + The usual way to do this is via the builtin `input` function. + + Because PyGame-CE **only runs on the main thread**, the only way to block + your code while it waits for user `input` is to use a + [JavaScript prompt](https://developer.mozilla.org/en-US/docs/Web/API/Window/prompt) + instead of input typed in via a terminal. PyScript handles this + automatically for you if you use the `input` function. + This is an experiment, but: * It is possible to use regular PyScript to load the pygame-ce package and use From 870a7d6afe1a3f96f6c1a1dcd3856d9624f20608 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Wed, 21 May 2025 14:36:38 +0100 Subject: [PATCH 194/201] Bump version to 2025-5-1 --- docs/beginning-pyscript.md | 8 ++++---- docs/user-guide/first-steps.md | 4 ++-- docs/user-guide/plugins.md | 10 +++++----- docs/user-guide/workers.md | 4 ++-- version.json | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/beginning-pyscript.md b/docs/beginning-pyscript.md index de3d931..e0d5e67 100644 --- a/docs/beginning-pyscript.md +++ b/docs/beginning-pyscript.md @@ -117,8 +117,8 @@ module in the document's `` tag: Codestin Search App - - + + @@ -168,8 +168,8 @@ In the end, our HTML should look like this: Codestin Search App - - + +

Polyglot 🦜 💬 🇬🇧 ➡️ 🏴‍☠️

diff --git a/docs/user-guide/first-steps.md b/docs/user-guide/first-steps.md index a97a2cf..b5ed91b 100644 --- a/docs/user-guide/first-steps.md +++ b/docs/user-guide/first-steps.md @@ -20,9 +20,9 @@ CSS: - + - + diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md index e49af88..3463118 100644 --- a/docs/user-guide/plugins.md +++ b/docs/user-guide/plugins.md @@ -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.3.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2025.5.1/core.js"; hooks.worker.onReady.add(() => { // NOT suggested, just an example! @@ -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.3.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2025.5.1/core.js"; // NO NO NO NO NO! ☠️ let i = 0; @@ -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.3.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2025.5.1/core.js"; // The `hooks.main` attribute defines plugins that run on the main thread. hooks.main.onReady.add((wrap, element) => { @@ -197,8 +197,8 @@ hooks.worker.onAfterRun.add(() => { - - + + + Codestin Search App diff --git a/version.json b/version.json index 4dd7ba3..4191267 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2025.3.1" + "version": "2025.5.1" } From f74cba5f8bb42bef3df6700d131494410350f649 Mon Sep 17 00:00:00 2001 From: Jason Winnebeck Date: Thu, 19 Jun 2025 16:20:29 -0400 Subject: [PATCH 195/201] pygame-ce getting started and timing tutorial Small update to configuration section to note that `` applies only to py/mpy type scripts. Major additions to `pygame-ce.md` on how to get started by explaining the changes needed from "stock" pygame-ce code to run in pyscript, and specifically ways to allow the same code to run cross-platform (locally and in pyscript online). --- docs/user-guide/configuration.md | 8 +- docs/user-guide/pygame-ce.md | 260 ++++++++++++++++++++++++++++++- 2 files changed, 264 insertions(+), 4 deletions(-) diff --git a/docs/user-guide/configuration.md b/docs/user-guide/configuration.md index b8f9a0a..80cb476 100644 --- a/docs/user-guide/configuration.md +++ b/docs/user-guide/configuration.md @@ -61,8 +61,8 @@ If you use JSON, you can make it the value of the `config` attribute: ``` For historical and convenience reasons we still support the inline -specification of configuration information via a _single_ `` or -`` tag in your HTML document: +specification of configuration information for `py` and `mpy` type scripts via a +_single_ `` or `` tag in your HTML document: ```HTML title="Inline configuration via the <py-config> tag." @@ -76,6 +76,10 @@ specification of configuration information via a _single_ `` or Should you use `` or ``, **there must be only one of these tags on the page per interpreter**. + + Additionally, `` only works for `py`/`mpy` type scripts and is not used + with [`py-game`](../pygame-ce) or [`py-editor`](../editor). For these set the config + attribute method. ## Options diff --git a/docs/user-guide/pygame-ce.md b/docs/user-guide/pygame-ce.md index a81766e..e2940c9 100644 --- a/docs/user-guide/pygame-ce.md +++ b/docs/user-guide/pygame-ce.md @@ -27,6 +27,262 @@ your games via a URL! create a game. Some things may not work because we're running in a browser context, but play around and let us know how you get on. +## Getting Started + +Here are some notes on using PyGame-CE specifically in a browser context with +pyscript versus running locally per +[PyGame-CE's documentation](https://pyga.me/docs/). + +1. You can use [pyscript.com](https://pyscript.com) as mentioned in + [Beginning PyScript](../beginning-pyscript.md) for an easy starting + environment. +2. Pyscript's PyGame-CE is under development, so make sure to use the latest + version by checking the `index.html` and latest version on this website. If + using [pyscript.com](https://pyscript.com), the latest version is not always + used in a new project. +3. The game loop needs to allow the browser to run to update the canvas used as + the game's screen. In the simplest projects, the quickest way to do that is + to replace `clock.tick(fps)` with `await asyncio.sleep(1/fps)`, but there + are better ways (discussed later). +4. If you have multiple Python source files or media such as images or sounds, + you need to use the [config attribute](configuration.md) to load the + files into the PyScript environment. The below example shows how to do this. +5. The integrated version of Python and PyGame-CE may not be the latest. In the + browser's console when PyGame-CE starts you can see the versions, and for + example if 2.4.1 is included, you can't use a function marked in the + documentation as "since 2.5". + +### Example + +This is the example quickstart taken from the [Python Pygame +Introduction](https://pyga.me/docs/tutorials/en/intro-to-pygame.html) on the +PyGame-CE website, modified only to add `await asyncio.sleep(1/60)` (and the +required `import asyncio`) to limit the game to roughly 60 fps. + +Note: since the `await` is not in an `async` function, it cannot run using +Python on your local machine, but a solution is +[discussed later](#running-locally). + + +```python title="quickstart.py" +import asyncio +import sys, pygame + +pygame.init() + +size = width, height = 320, 240 +speed = [2, 2] +black = 0, 0, 0 + +screen = pygame.display.set_mode(size) +ball = pygame.image.load("intro_ball.gif") +ballrect = ball.get_rect() + +while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: sys.exit() + + ballrect = ballrect.move(speed) + if ballrect.left < 0 or ballrect.right > width: + speed[0] = -speed[0] + if ballrect.top < 0 or ballrect.bottom > height: + speed[1] = -speed[1] + + screen.fill(black) + screen.blit(ball, ballrect) + pygame.display.flip() + await asyncio.sleep(1/60) +``` + +To run this game with PyScript, use the following HTML file, ensuring a call +to the Python program and a `` element where the graphics +will be placed. Make sure to update the pyscript release to the latest version. + +```html title="index.html" + + + + + Codestin Search App + + + + + + + + + + +``` + +!!! Info + + The `style="image-rendering: pixelated` on the canvas preserves the + pixelated look on high-DPI screens or when zoomed-in. Remove it to have a + "smoothed" look. + +Lastly, you need to define the `pyscript.toml` file to expose any files that +your game loads -- in this case, `intro_ball.gif` +[(download from pygame GitHub)](https://github.com/pygame-community/pygame-ce/blob/80fe4cb9f89aef96f586f68d269687572e7843f6/docs/reST/tutorials/assets/intro_ball.gif?raw=true). + +```toml title="pyscript.toml" +[files] +"intro_ball.gif" = "" +``` + +Now you only need to serve the 3 files to a browser. If using +[pyscript.com](https://pyscript.com) you only need to ensure the content of the +files, click save then run and view the preview tab. Or, if you are on a machine +with Python installed you can do it from a command line running in the same +directory as the project: + +``` +python -m http.server -b 127.0.0.1 8000 +``` + +This will start a website accessible only to your machine (`-b 127.0.0.1` limits +access only to "localhost" -- your own machine). After running this, you can +visit [http://localhost:8000/](http://localhost:8000/) to run the game in your +browser. + +Congratulations! Now you know the basics of updating games to run in PyScript. +You can continue to develop your game in the typical PyGame-CE way. + +## Running Locally + +Placing an `await` call in the main program script as in the example is not +technically valid Python as it should be in an `async` function. In the +environment executed by PyScript, the code runs in an `async` context so this +works; however, you will notice you cannot run the `quickstart.py` on your +local machine with Python. To fix that, you need to add just a little more +code: + +Place the entire game in a function called `run_game` so that function can be +declared as `async`, allowing it to use `await` in any environment. Import the +`asyncio` package and add the `try ... except` code at the end. Now when running +in the browser, `asyncio.create_task` is used, but when running locally +`asyncio.run` is used. Now you can develop and run locally but also support +publish to the web via PyScript. + +```python +import asyncio +import sys, pygame + +async def run_game(): + pygame.init() + + # Game init ... + + while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: sys.exit() + + # Game logic ... + + await asyncio.sleep(1/60) + +try: + asyncio.get_running_loop() # succeeds if in async context + asyncio.create_task(run_game()) +except RuntimeError: + asyncio.run(run_game()) # start async context as we're not in one +``` + +!!! Info + + In the web version, the `sys.exit()` was never used because the `QUIT` + event is not generated, but in the local version, responding to the event + is mandatory. + +## Advanced Timing + +While the `await asyncio.sleep(1/60)` is a quick way to approximate 60 FPS, +like all sleep-based timing methods in games this is not precise. Generating +the frame itself takes time, so sleeping 1/60th of a second means total frame +time is longer and actual FPS will be less than 60. Our usage of `clock.tick()` +and `dt` in the earlier code ensures the ball will move at the correct rate, +but performance will not be ideal. + +A better way is to do this is to run your game at the same frame rate as the +display (usually 60, but can be 75, 100, 144, or higher on some displays). When +running in the browser, the proper way to do this is with the JavaScript API +called `requestAnimationFrame`. Using the FFI (foreign function interface) +capabilities of PyScript, we can request the browser's JavaScript runtime to +call the game. The main issue of this method is it requires work to separate the +game setup from the game's execution, which may require more advanced Python +code such as `global` or `class`. However, one benefit is that the `asyncio` +usages are gone. + + +When running locally, you get the same effect from the `vsync=1` parameter on +`pygame.display.set_mode` as `pygame.display.flip()` will pause until the screen +has displayed the frame. In the web version, the `vsync=1` will do nothing, +`flip` will not block, leaving the browser itself to control the timing using +`requestAnimationFrame` by calling `run_one_frame` (via `on_animation_frame`) +each time the display updates. + +Additionally, since frame lengths will be different on each machine, we need to +account for this by creating and using a `dt` variable by using a +`pygame.time.Clock`. We update the speed to be in pixels per second and multiply +by `dt` (in seconds) to get the number of pixels to move. + +The code will look like this: + +```python +import sys, pygame + +pygame.init() + +size = width, height = 320, 240 +speed = pygame.Vector2(150, 150) # use Vector2 so we can multiply with dt +black = 0, 0, 0 + +screen = pygame.display.set_mode(size, vsync=1) # Added vsync=1 +ball = pygame.image.load("intro_ball.gif") +ballrect = ball.get_rect() +clock = pygame.time.Clock() # New clock defined + +def run_one_frame(): + for event in pygame.event.get(): + if event.type == pygame.QUIT: sys.exit() + + # in this 300 is for maximum frame rate only, in case vsync is not working + dt = clock.tick(300) / 1000 + + ballrect.move_ip(speed * dt) # use move_ip to avoid the need for "global" + # Remaining game code unchanged ... + + pygame.display.flip() + + +# PyScript-specific code to use requestAnimationFrame in browser +try: + from pyscript import window + from pyscript import ffi + # Running in PyScript + def on_animation_frame(dt): + # For consistency, we use dt from pygame's clock even in browser + run_one_frame() + window.requestAnimationFrame(raf_proxy) + raf_proxy = ffi.create_proxy(on_animation_frame) + on_animation_frame(0) + +except ImportError: + # Local Execution + while True: + run_one_frame() +``` + +A benefit of `vsync` / `requestAnimationFrame` method is that if the game is +running too slowly, frames will naturally be skipped. A drawback is that in the +case of skipped frames and different displays, `dt` will be different. This can +cause problems depending on your game's physics code; the potential solutions +are not unique to the PyScript situation and can be found elsewhere online as an +exercise for the reader. For example, the above example on some machines the +ball will get "stuck" in the sides. In case of issues the `asyncio.sleep` method +without `dt` is easier to deal with for the beginning developer. + ## How it works When a `` element is found on the page a @@ -37,8 +293,8 @@ element id that will be used to render the game. If no target attribute is defined, the script assumes there is a `` element already on the page. -A config attribute can be specified to add extra packages but right now that's -all it can do. +A config attribute can be specified to add extra packages or bring in additional +files such as images and sounds but right now that's all it can do. !!! Info From ffce2b4d549b6466b9fbabe7e42668b14e254dfa Mon Sep 17 00:00:00 2001 From: Jason Winnebeck Date: Fri, 20 Jun 2025 08:57:28 -0400 Subject: [PATCH 196/201] Minor fixes of configuration and pygame-ce doc * `configuration.md` fix grammar ("For these set the config attribute method" -> "For these use the config attribute method") * `pygame-ce.md` Removed "Our usage of `clock.tick()` and `dt` in the earlier code" which referenced removed code that existed earlier. --- docs/user-guide/configuration.md | 2 +- docs/user-guide/pygame-ce.md | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/user-guide/configuration.md b/docs/user-guide/configuration.md index 80cb476..ba2d14c 100644 --- a/docs/user-guide/configuration.md +++ b/docs/user-guide/configuration.md @@ -78,7 +78,7 @@ _single_ `` or `` tag in your HTML document: these tags on the page per interpreter**. Additionally, `` only works for `py`/`mpy` type scripts and is not used - with [`py-game`](../pygame-ce) or [`py-editor`](../editor). For these set the config + with [`py-game`](../pygame-ce) or [`py-editor`](../editor). For these use the config attribute method. ## Options diff --git a/docs/user-guide/pygame-ce.md b/docs/user-guide/pygame-ce.md index e2940c9..0220f2a 100644 --- a/docs/user-guide/pygame-ce.md +++ b/docs/user-guide/pygame-ce.md @@ -200,9 +200,7 @@ except RuntimeError: While the `await asyncio.sleep(1/60)` is a quick way to approximate 60 FPS, like all sleep-based timing methods in games this is not precise. Generating the frame itself takes time, so sleeping 1/60th of a second means total frame -time is longer and actual FPS will be less than 60. Our usage of `clock.tick()` -and `dt` in the earlier code ensures the ball will move at the correct rate, -but performance will not be ideal. +time is longer and actual FPS will be less than 60. A better way is to do this is to run your game at the same frame rate as the display (usually 60, but can be 75, 100, 144, or higher on some displays). When @@ -223,7 +221,7 @@ has displayed the frame. In the web version, the `vsync=1` will do nothing, each time the display updates. Additionally, since frame lengths will be different on each machine, we need to -account for this by creating and using a `dt` variable by using a +account for this by creating and using a `dt` (delta time) variable by using a `pygame.time.Clock`. We update the speed to be in pixels per second and multiply by `dt` (in seconds) to get the number of pixels to move. From 48a0db8dce8ecd3317edbef7027ca9ba2a0299b8 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Tue, 1 Jul 2025 12:28:17 +0100 Subject: [PATCH 197/201] Bump version. --- docs/beginning-pyscript.md | 8 ++++---- docs/user-guide/first-steps.md | 4 ++-- docs/user-guide/plugins.md | 10 +++++----- docs/user-guide/pygame-ce.md | 4 ++-- docs/user-guide/workers.md | 4 ++-- version.json | 2 +- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/beginning-pyscript.md b/docs/beginning-pyscript.md index e0d5e67..9f9fc65 100644 --- a/docs/beginning-pyscript.md +++ b/docs/beginning-pyscript.md @@ -117,8 +117,8 @@ module in the document's `` tag: Codestin Search App - - + + @@ -168,8 +168,8 @@ In the end, our HTML should look like this: Codestin Search App - - + +

Polyglot 🦜 💬 🇬🇧 ➡️ 🏴‍☠️

diff --git a/docs/user-guide/first-steps.md b/docs/user-guide/first-steps.md index b5ed91b..9210c26 100644 --- a/docs/user-guide/first-steps.md +++ b/docs/user-guide/first-steps.md @@ -20,9 +20,9 @@ CSS: - + - + diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md index 3463118..4dc0c6d 100644 --- a/docs/user-guide/plugins.md +++ b/docs/user-guide/plugins.md @@ -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.5.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2025.7.1/core.js"; hooks.worker.onReady.add(() => { // NOT suggested, just an example! @@ -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.5.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2025.7.1/core.js"; // NO NO NO NO NO! ☠️ let i = 0; @@ -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.5.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2025.7.1/core.js"; // The `hooks.main` attribute defines plugins that run on the main thread. hooks.main.onReady.add((wrap, element) => { @@ -197,8 +197,8 @@ hooks.worker.onAfterRun.add(() => { - - + + + + diff --git a/docs/user-guide/workers.md b/docs/user-guide/workers.md index 9e2cc16..d439cd5 100644 --- a/docs/user-guide/workers.md +++ b/docs/user-guide/workers.md @@ -282,9 +282,9 @@ Here's how: - + - + Codestin Search App diff --git a/version.json b/version.json index 4191267..ddd025c 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2025.5.1" + "version": "2025.7.1" } From 7fc8c8ac975c6f8a3fda3576c754b95767a77f54 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Tue, 1 Jul 2025 12:52:01 +0100 Subject: [PATCH 198/201] Update configuration as discussed. --- docs/user-guide/configuration.md | 38 ++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/docs/user-guide/configuration.md b/docs/user-guide/configuration.md index ba2d14c..5a0fdb7 100644 --- a/docs/user-guide/configuration.md +++ b/docs/user-guide/configuration.md @@ -318,6 +318,22 @@ following valid forms: * An arbitrary URL to a Python package: `"https://.../package.whl"` * A file copied onto the browser based file system: `"emfs://.../package.whl"` +#### Package Cache + +For performance reasons, PyScript caches packages so that a delay resulting +from downloading the packages is only noticable on first load - after which, +PyScript will fall back on packages previously downloaded and held in the +browser's local cache. + +The behaviour of caching can be configured via the `packages_cache` setting. If +this setting is not used, PyScript will cache packages. Otherwise, override +PyScript's behaviour by setting `packages_cache` to one of these two values: + +* `never` - PyScript will not cache packages. +* `passthrough` - this only works with Pyodide (see [this wiki](https://deepwiki.com/cloudflare/pyodide/3-package-system)), + and will cause Pyodide to download packages in a parallel manner rather than + the default linear fashion. However, these packages will not be cached. + ### Plugins The `plugins` option allows user to either augment, or exclude, the list of @@ -518,6 +534,28 @@ experimental_create_proxy = "auto" [raise an issue](https://github.com/pyscript/pyscript/issues) with a reproducable example, and we'll investigate. +### experimental_ffi_timeout + +When bootstrapping a worker, the worker is told to use a cache for round-trip +operations (for example, `my_object.foo.bar.baz` causes a round-trip to the +main thread for each dot `.` in this chain of references). By caching the +dotted references performance can be improved by reducing the number of +round trips PyScript makes. + +However, not everything can be cached (those APIs or objects with side-effects +won't work; for example DOM element based APIs etc). + +The `experimental_ffi_timeout` setting defines the maximum lifetime of that +cache. If it's less than 0 (the default), there is no cache whatsoever. Zero +means to clean up the cache on the next iteration of the event loop. A positive +number is the maximum number of milliseconds the cache will be kept alive. + +### debug + +When using Pyodide, if the `debug` setting is set to `true`, then Pyodide will +run in debug mode. See Pyodide's documentation for details of what this +entails. + ### Custom Sometimes plugins or apps need bespoke configuration options. From f2c59293e977b25c60ac603eddf22e5db05ff843 Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Tue, 1 Jul 2025 13:40:16 +0100 Subject: [PATCH 199/201] Fix nits. --- docs/user-guide/configuration.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/user-guide/configuration.md b/docs/user-guide/configuration.md index 5a0fdb7..ea69be2 100644 --- a/docs/user-guide/configuration.md +++ b/docs/user-guide/configuration.md @@ -537,8 +537,8 @@ experimental_create_proxy = "auto" ### experimental_ffi_timeout When bootstrapping a worker, the worker is told to use a cache for round-trip -operations (for example, `my_object.foo.bar.baz` causes a round-trip to the -main thread for each dot `.` in this chain of references). By caching the +operations (for example, `window.my_object.foo.bar.baz` causes a round-trip to +the main thread for each dot `.` in this chain of references). By caching the dotted references performance can be improved by reducing the number of round trips PyScript makes. @@ -550,6 +550,10 @@ cache. If it's less than 0 (the default), there is no cache whatsoever. Zero means to clean up the cache on the next iteration of the event loop. A positive number is the maximum number of milliseconds the cache will be kept alive. +In this experimental phase, we suggest trying `0`, `30` or a value that won't +likely bypass the browser rendering of 60fps. Of course, `1000` (i.e. a second) +would be a fun, if greedy, experiment. + ### debug When using Pyodide, if the `debug` setting is set to `true`, then Pyodide will From e18b4b1097d0107aec472f97314ac64a58ede6e4 Mon Sep 17 00:00:00 2001 From: Dan Yeaw Date: Tue, 1 Jul 2025 17:20:09 -0400 Subject: [PATCH 200/201] Add outdated version warning --- mkdocs.yml | 1 + overrides/main.html | 8 ++++++++ 2 files changed, 9 insertions(+) create mode 100644 overrides/main.html diff --git a/mkdocs.yml b/mkdocs.yml index 4487b51..d62e421 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -2,6 +2,7 @@ site_name: PyScript theme: name: material + custom_dir: overrides logo: assets/images/pyscript-black.svg diff --git a/overrides/main.html b/overrides/main.html new file mode 100644 index 0000000..d4c2203 --- /dev/null +++ b/overrides/main.html @@ -0,0 +1,8 @@ +{% extends "base.html" %} + +{% block outdated %} + You're not viewing the latest version. +
+ Click here to go to latest. + +{% endblock %} From 84be34c37ade113e4b1e83bc8b6d74f0499522ef Mon Sep 17 00:00:00 2001 From: "Nicholas H.Tollervey" Date: Fri, 4 Jul 2025 08:31:12 +0100 Subject: [PATCH 201/201] Bump to 2025.7.2 --- docs/beginning-pyscript.md | 8 ++++---- docs/user-guide/first-steps.md | 4 ++-- docs/user-guide/plugins.md | 10 +++++----- docs/user-guide/pygame-ce.md | 4 ++-- docs/user-guide/workers.md | 4 ++-- version.json | 2 +- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/beginning-pyscript.md b/docs/beginning-pyscript.md index 9f9fc65..779e597 100644 --- a/docs/beginning-pyscript.md +++ b/docs/beginning-pyscript.md @@ -117,8 +117,8 @@ module in the document's `` tag: Codestin Search App - - + + @@ -168,8 +168,8 @@ In the end, our HTML should look like this: Codestin Search App - - + +

Polyglot 🦜 💬 🇬🇧 ➡️ 🏴‍☠️

diff --git a/docs/user-guide/first-steps.md b/docs/user-guide/first-steps.md index 9210c26..6a01580 100644 --- a/docs/user-guide/first-steps.md +++ b/docs/user-guide/first-steps.md @@ -20,9 +20,9 @@ CSS: - + - + diff --git a/docs/user-guide/plugins.md b/docs/user-guide/plugins.md index 4dc0c6d..d0d2825 100644 --- a/docs/user-guide/plugins.md +++ b/docs/user-guide/plugins.md @@ -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.7.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2025.7.2/core.js"; hooks.worker.onReady.add(() => { // NOT suggested, just an example! @@ -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.7.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2025.7.2/core.js"; // NO NO NO NO NO! ☠️ let i = 0; @@ -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.7.1/core.js"; +import { hooks } from "https://pyscript.net/releases/2025.7.2/core.js"; // The `hooks.main` attribute defines plugins that run on the main thread. hooks.main.onReady.add((wrap, element) => { @@ -197,8 +197,8 @@ hooks.worker.onAfterRun.add(() => { - - + + + + diff --git a/docs/user-guide/workers.md b/docs/user-guide/workers.md index d439cd5..cfc7a8c 100644 --- a/docs/user-guide/workers.md +++ b/docs/user-guide/workers.md @@ -282,9 +282,9 @@ Here's how: - + - + Codestin Search App diff --git a/version.json b/version.json index ddd025c..370255b 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2025.7.1" + "version": "2025.7.2" }