Skip to content

Commit ea0c9a0

Browse files
authored
Merge pull request #135 from pyscript/2024-8-1
2024 8 1
2 parents 126d9d6 + a25b637 commit ea0c9a0

File tree

8 files changed

+201
-131
lines changed

8 files changed

+201
-131
lines changed

docs/api.md

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -413,29 +413,34 @@ store = await storage("my-data-store", storage_class=MyStorage)
413413

414414
### `pyscript.web`
415415

416-
TODO: Use `display(element)` not `element.display()`.
417-
418416
The classes and references in this namespace provide a Pythonic way to interact
419417
with the DOM. An explanation for how to idiomatically use this API can be found
420418
[in the user guide](../user-guide/dom/#pyscriptweb)
421419

422-
#### `pyscript.web.dom`
420+
#### `pyscript.web.page`
423421

424-
This object has two attributes and a single method:
422+
This object represents a web page. It has four attributes and two methods:
425423

424+
* `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.
426425
* `head` - a reference to a Python object representing the [document's head](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head).
427426
* `body` - a reference to a Python object representing the [document's body](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/body).
427+
* `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.
428428
* `find` - a method that takes a single [selector](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_selectors)
429429
argument and returns a collection of Python objects representing the matching
430430
elements.
431+
* `append` - a shortcut for `page.body.append` (to add new elements to the
432+
page).
433+
434+
You may also shortcut the `find` method by enclosing a CSS selector in square
435+
brackets: `page["#my-thing"]`.
431436

432437
These are provided as a convenience so you have several simple and obvious
433-
options for accessing the content of the page (DOM).
438+
options for accessing and changing the content of the page.
434439

435440
All the Python objects returned by these attributes and method are instances of
436-
classes defined in the `pyscript.web.elements` namespace.
441+
classes relating to HTML elements defined in the `pyscript.web` namespace.
437442

438-
#### `pyscript.web.elements.*`
443+
#### `pyscript.web.*`
439444

440445
There are many classes in this namespace. Each is a one-to-one mapping of any
441446
HTML element name to a Python class representing the HTML element of that

docs/beginning-pyscript.md

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

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

docs/faq.md

Lines changed: 28 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ encounter.
4949

5050
### SharedArrayBuffer
5151

52-
This is the first and most common error users may encounter with PyScript.
52+
This is the first and most common error users may encounter with PyScript:
5353

5454
!!! failure
5555

@@ -58,52 +58,35 @@ This is the first and most common error users may encounter with PyScript.
5858
you see this message:
5959

6060
```
61-
Unable to use SharedArrayBuffer due insecure environment.
62-
Please read requirements in MDN: ...
61+
Unable to use `window` or `document` -> https://docs.pyscript.net/latest/faq/#sharedarraybuffer
6362
```
6463

65-
The error contains
66-
[a link to MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer#security_requirements)
67-
but it's the amount of content provided on this topic is overwhelming.
68-
6964
#### When
7065

71-
This error happens when **the server delivering your PyScript application is
72-
incorrectly configured**. It fails to provide the correct headers to handle
73-
security concerns for web workers, or you're not using
74-
[mini-coi](https://github.com/WebReflection/mini-coi#readme) as an alternative
75-
solution. (These requirements are explored
76-
[in the worker page](../user-guide/workers#http-headers).)
77-
78-
**And** at least one of the following scenarios is true:
79-
80-
* There is a `worker` attribute in the *py* or *mpy* script element and the
81-
[sync_main_only](https://pyscript.github.io/polyscript/#extra-config-features)
82-
flag is not present or not `true`.
83-
* There is a `<script type="py-editor">` that uses a *worker* behind the
84-
scenes.
85-
* There is an explicit `PyWorker` or `MPWorker` bootstrapping somewhere in your
86-
code.
87-
88-
!!! info
66+
This happens when you're unable to access objects in the main thread (`window`
67+
and `document`) from code running in a web worker.
8968

90-
If `sync_main_only` is `true` then interactions between the main thread and
91-
workers are limited to one way calls from the main thread to methods
92-
exposed by workers.
69+
This error happens because **the server delivering your PyScript application is
70+
incorrectly configured** or **a `service-worker` attribute has not been used in
71+
your `script` element**.
9372

94-
If `sync_main_only = true`, the following caveats apply:
73+
Specifically, one of the following three problem situations applies to your
74+
code:
9575

96-
* It is not possible to manipulate the DOM or do anything meaningful on the
97-
main thread **from a worker**. This is because Atomics cannot guarantee
98-
sync-like locks between a worker and the main thread.
99-
* Only a worker's `pyscript.sync` methods are exposed, and they can only be
100-
awaited from the main thread.
101-
* The worker can only `await` main thread references one after the other, so
102-
developer experience is degraded when one needs to interact with the
103-
main thread.
76+
* Because of the way your web server is configured, the browser limits the use
77+
of a technology called "Atomics" (you don't need to know how it works, just
78+
that it may be limited by the browser). If there is a `worker` attribute in
79+
your `script` element, and your Python code uses the `window` or `document`
80+
objects (that actually exist on the main thread), then the browser limitation
81+
on Atomics will cause the failure, unless you reconfigure your server.
82+
* There is a `<script type="py-editor">` (that must always use a worker behind
83+
the scenes) and no fallback has been provided via a `service-worker`
84+
attribute on that element.
85+
* There is an explicit `PyWorker` or `MPWorker` instance **bootstrapping
86+
somewhere in your code** and no `service_worker` fallback has been provided.
10487

105-
If your project simply bootstraps on the main thread, none of this is relevant
106-
because no worker requires such special features.
88+
All these cases have been documented with code examples and possible solutions
89+
in our section on [web workers](../user-guide/workers/).
10790

10891
#### Why
10992

@@ -122,21 +105,19 @@ CPU. It idles until the referenced index of the shared buffer changes,
122105
effectively never blocking the main thread while still pausing its own
123106
execution until the buffer's index is changed.
124107

125-
As overwhelming or complicated as this might sounds, these two fundamental
108+
As overwhelming or complicated as this might sound, these two fundamental
126109
primitives make main ↔ worker interoperability an absolute wonder in term of
127110
developer experience. Therefore, we encourage folks to prefer using workers
128111
over running Python in the main thread. This is especially so when using
129112
Pyodide related projects, because of its heavier bootstrap or computation
130113
requirements. Using workers ensures the main thread (and thus, the user
131114
interface) remains unblocked.
132115

133-
Unfortunately, due to security concerns and potential attacks to shared
134-
buffers, each server or page needs to allow extra security to prevent malicious
135-
software to read or write into these buffers. But be assured that if you own
136-
your code, your project, and you trust the modules or 3rd party code you need
137-
and use, **there are less likely to be security concerns around this topic
138-
within your project**. This situation is simply an unfortunate "*one rule catch
139-
all*" standard any server can either enable or disable as it pleases.
116+
Unfortunately, we can patch, polyfill, or workaround, these primitives but
117+
we cannot change their intrinsic nature and limitations defined by web
118+
standards. However, there are various solutions for working around such
119+
limitations. Please read our [web workers](..//user-guide/workers/)
120+
section to learn more.
140121

141122
### Borrowed proxy
142123

docs/user-guide/dom.md

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -99,39 +99,45 @@ There are three core concepts to remember:
9999
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)
100100
as those used by native browser methods like `qurerySelector` or
101101
`querySelectorAll`.
102-
* Use classes in the `pyscript.web.elements` namespace to create and organise
102+
* Use classes in the `pyscript.web` namespace to create and organise
103103
new elements on the web page.
104104
* Collections of elements allow you to access and change attributes en-mass.
105105
Such collections are returned from `find` queries and are also used for the
106106
[children](https://developer.mozilla.org/en-US/docs/Web/API/Element/children)
107107
of an element.
108108

109-
You have several options for accessing the content of the page (i.e. the DOM),
110-
and these can be found in the `pyscript.web.dom` object. The `head` and `body`
111-
attributes reference the page's head and body. Furthermore, the `find` method
112-
can be used to return collections of elements matching your CSS query. Finally,
113-
all elements have a `find` method that searches within their children for
114-
elements matching your CSS query.
109+
You have several options for accessing the content of the page, and these are
110+
all found in the `pyscript.web.page` object. The `html`, `head` and `body`
111+
attributes reference the page's top-level html, head and body. As a convenience
112+
the `page`'s `title` attribute can be used to get and set the web page's title
113+
(usually shown in the browser's tab). The `append` method is a shortcut for
114+
adding content to the page's `body`. Whereas, the `find` method is used to
115+
return collections of elements matching a CSS query. You may also shortcut
116+
`find` via a CSS query in square brackets. Finally, all elements have a `find`
117+
method that searches within their children for elements matching your CSS
118+
query.
115119

116120
```python
117-
from pyscript.web import dom
121+
from pyscript.web import page
118122

119123

120124
# Print all the child elements of the document's head.
121-
print(dom.head.children)
125+
print(page.head.children)
122126
# Find all the paragraphs in the DOM.
123-
paragraphs = dom.find("p")
127+
paragraphs = page.find("p")
128+
# Or use square brackets.
129+
paragraphs = page["p"]
124130
```
125131

126132
The object returned from a query, or used as a reference to an element's
127133
children is iterable:
128134

129135
```python
130-
from pyscript.web import dom
136+
from pyscript.web import page
131137

132138

133139
# Get all the paragraphs in the DOM.
134-
paragraphs = dom.find("p")
140+
paragraphs = page["p"]
135141

136142
# Print the inner html of each paragraph.
137143
for p in paragraphs:
@@ -141,38 +147,36 @@ for p in paragraphs:
141147
Alternatively, it is also indexable / sliceable:
142148

143149
```python
144-
from pyscript.web import dom
150+
from pyscript.web import page
145151

146152

147153
# Get an ElementCollection of all the paragraphs in the DOM
148-
paragraphs = dom.find("p")
154+
paragraphs = page["p"]
149155

150156
# Only the final two paragraphs.
151157
for p in paragraphs[-2:]:
152158
print(p.html)
153159
```
154160

155-
It also makes available the following read and writable attributes related to
156-
all contained elements:
161+
You have access to all the standard attributes related to HTML elements (for
162+
example, the `innerHTML` or `value`), along with a couple of convenient ways
163+
to interact with classes and CSS styles:
157164

158165
* `classes` - the list of classes associated with the elements.
159-
* `innerHTML` - the innerHTML of each element.
160166
* `style` - a dictionary like object for interacting with CSS style rules.
161-
* `value` - the `value` attribute associated with each element.
162167

163168
For example, to continue the example above, `paragraphs.innerHTML` will return
164169
a list of all the values of the `innerHTML` attribute on each contained
165170
element. Alternatively, set an attribute for all elements contained in the
166171
collection like this: `paragraphs.style["background-color"] = "blue"`.
167172

168-
It's possible to create new elements to add to the DOM:
173+
It's possible to create new elements to add to the page:
169174

170175
```python
171-
from pyscript.web import dom
172-
from pyscript.web.elements import *
176+
from pyscript.web import page, div, select, option, button, span, br
173177

174178

175-
dom.body.append(
179+
page.append(
176180
div(
177181
div("Hello!", classes="a-css-class", id="hello"),
178182
select(
@@ -206,7 +210,7 @@ dom.body.append(
206210
```
207211

208212
This example demonstrates a declaritive way to add elements to the body of the
209-
DOM. Notice how the first (unnamed) arguments to an element are its children.
213+
page. Notice how the first (unnamed) arguments to an element are its children.
210214
The named arguments (such as `id`, `classes` and `style`) refer to attributes
211215
of the underlying HTML element. If you'd rather be explicit about the children
212216
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
216220
programming:
217221

218222
```python
219-
from pyscript.web import dom
220-
from pyscript.web.elements import *
221-
223+
from pyscript.web import page, div, p
222224

223225

224226
my_div = div()
@@ -238,10 +240,10 @@ element references from `pyscript.web`:
238240

239241
```python
240242
from pyscript import when
241-
from pyscript.web import dom
243+
from pyscript.web import page
242244

243245

244-
btn = dom.find("#my-button")
246+
btn = page["#my-button"]
245247

246248

247249
@when("click", btn)

docs/user-guide/first-steps.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ CSS:
2020
<meta charset="UTF-8">
2121
<meta name="viewport" content="width=device-width,initial-scale=1.0">
2222
<!-- PyScript CSS -->
23-
<link rel="stylesheet" href="https://pyscript.net/releases/2024.7.1/core.css">
23+
<link rel="stylesheet" href="https://pyscript.net/releases/2024.8.1/core.css">
2424
<!-- This script tag bootstraps PyScript -->
25-
<script type="module" src="https://pyscript.net/releases/2024.7.1/core.js"></script>
25+
<script type="module" src="https://pyscript.net/releases/2024.8.1/core.js"></script>
2626
</head>
2727
<body>
2828
<!-- your code goes here... -->
@@ -80,13 +80,18 @@ attributes:
8080
* `worker` - a flag to indicate your Python code is to be run on a
8181
[web worker](workers.md) instead of the "main thread" that looks after the user
8282
interface.
83-
* `target` - The id or selector of the element where calls to
83+
* `target` - the id or selector of the element where calls to
8484
[`display()`](../../api/#pyscriptdisplay) should write their values.
85-
* `terminal` - A traditional [terminal](terminal.md) is shown on the page.
85+
* `terminal` - a traditional [terminal](terminal.md) is shown on the page.
8686
As with conventional Python, `print` statements output here. **If the
8787
`worker` flag is set the terminal becomes interactive** (e.g. use
8888
the `input` statement to gather characters typed into the terminal by the
8989
user).
90+
* `service-worker` - an optional attribute that allows you to slot in a custom
91+
[service worker](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API)
92+
(such as `mini-coi.js`) to fix header related problems that limit the use
93+
of web workers. This rather technical requirement is fully explained in
94+
the [section on web workers](../workers/#option-2-service-worker-attribute).
9095

9196
!!! warning
9297

docs/user-guide/plugins.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ For example, this will work because all references are contained within the
9999
registered function:
100100

101101
```js
102-
import { hooks } from "https://pyscript.net/releases/2024.7.1/core.js";
102+
import { hooks } from "https://pyscript.net/releases/2024.8.1/core.js";
103103

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

115115
```js
116-
import { hooks } from "https://pyscript.net/releases/2024.7.1/core.js";
116+
import { hooks } from "https://pyscript.net/releases/2024.8.1/core.js";
117117

118118
// NO NO NO NO NO! ☠️
119119
let i = 0;
@@ -146,7 +146,7 @@ the page.
146146

147147
```js title="log.js - a plugin that simply logs to the console."
148148
// import the hooks from PyScript first...
149-
import { hooks } from "https://pyscript.net/releases/2024.7.1/core.js";
149+
import { hooks } from "https://pyscript.net/releases/2024.8.1/core.js";
150150

151151
// The `hooks.main` attribute defines plugins that run on the main thread.
152152
hooks.main.onReady.add((wrap, element) => {
@@ -196,8 +196,8 @@ hooks.worker.onAfterRun.add(() => {
196196
<!-- JS plugins should be available before PyScript bootstraps -->
197197
<script type="module" src="./log.js"></script>
198198
<!-- PyScript -->
199-
<link rel="stylesheet" href="https://pyscript.net/releases/2024.7.1/core.css">
200-
<script type="module" src="https://pyscript.net/releases/2024.7.1/core.js"></script>
199+
<link rel="stylesheet" href="https://pyscript.net/releases/2024.8.1/core.css">
200+
<script type="module" src="https://pyscript.net/releases/2024.8.1/core.js"></script>
201201
</head>
202202
<body>
203203
<script type="mpy">

0 commit comments

Comments
 (0)