8000 Add docs for py-event* (#1300) · ocdex/pyscript@543a272 · GitHub
[go: up one dir, main page]

Skip to content

Commit 543a272

Browse files
marimeirelesdj-fiorexpre-commit-ci[bot]
authored
Add docs for py-event* (pyscript#1300)
* Fix markdown Add event-handlers.md * Address changes from Jeff + Antonion and add it to index * how tos don't exist anymore theyre now guides * Restore p on contributing * Adding changelog * Aadd space * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Carmelo <carmelofiorello@gmail.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent a62aba8 commit 543a272

File tree

5 files changed

+211
-8
lines changed

5 files changed

+211
-8
lines changed

CONTRIBUTING.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,21 @@ Thank you for wanting to contribute to the PyScript project!
44

55
## Table of contents
66

7+
- [Contributing to PyScript](#contributing-to-pyscript)
8+
- [Table of contents](#table-of-contents)
79
- [Code of Conduct](#code-of-conduct)
810
- [Contributing](#contributing)
911
- [Reporting bugs](#reporting-bugs)
12+
- [Creating useful issues](#creating-useful-issues)
1013
- [Reporting security issues](#reporting-security-issues)
1114
- [Asking questions](#asking-questions)
1215
- [Setting up your local environment and developing](#setting-up-your-local-environment-and-developing)
16+
- [Developing](#developing)
17+
- [Rebasing changes](#rebasing-changes)
18+
- [Building the docs](#building-the-docs)
1319
- [Places to start](#places-to-start)
1420
- [Setting up your local environment and developing](#setting-up-your-local-environment-and-developing)
21+
- [Submitting a change](#submitting-a-change)
1522
- [License terms for contributions](#license-terms-for-contributions)
1623
- [Becoming a maintainer](#becoming-a-maintainer)
1724
- [Trademarks](#trademarks)
@@ -43,7 +50,7 @@ If you have questions about the project, using PyScript, or anything else, pleas
4350

4451
## Places to start
4552

46-
If you would like to contribute to PyScript, but you aren't sure where to begin, here are some suggestions.
53+
If you would like to contribute to PyScript, but you aren't sure where to begin, here are some suggestions:
4754

4855
- **Read over the existing documentation.** Are there things missing, or could they be clearer? Make some changes/additions to those documents.
4956
- **Review the open issues.** Are they clear? Can you reproduce them? You can add comments, clarifications, or additions to those issues. If you think you have an idea of how to address the issue, submit a fix!

docs/changelog.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,12 @@ Enhancements
3535
- migrated from *rollup* to *esbuild* to create artifacts
3636
- updated `@codemirror` dependency to its latest
3737

38-
2023.03.1
38+
Docs
39+
----
40+
41+
- Add docs for event handlers
42+
43+
2023.01.1
3944
=========
4045

4146

docs/guides/event-handlers.md

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
# Event handlers in PyScript
2+
3+
PyScript offer two ways to subscribe to Javascript event handlers:
4+
5+
## Subscribe to event with `py-*` attributes
6+
7+
The value of the attribute contains python code which will be executed when the event is fired. A very common pattern is to call a function which does further work, for example:
8+
9+
```html
10+
<button id="noParam" py-click="say_hello_no_param()">
11+
No Event - No Params py-click
12+
</button>
13+
<button id="withParam" py-click="say_hello_with_param('World')">
14+
No Event - With Params py-click
15+
</button>
16+
```
17+
18+
```python
19+
<py-script>
20+
def say_hello_no_param():
21+
print("Hello!")
22+
23+
def say_hello_with_param(name):
24+
print("Hello " + name + "!")
25+
</py-script>
26+
```
27+
28+
Note that py-\* attributes need a _function call_
29+
30+
Supported py-\* attributes can be seen in the [PyScript API reference](<[../api-reference.md](https://github.com/pyscript/pyscript/blob/66b57bf812dcc472ed6ffee075ace5ced89bbc7c/pyscriptjs/src/components/pyscript.ts#L119-L260)>).
31+
32+
## Subscribe to event with `addEventListener`
33+
34+
You can also subscribe to an event using the `addEventListener` method of the DOM element. This is useful if you want to pass event object to the event handler.
35+
36+
```html
37+
<button id="two">add_event_listener passes event</button>
38+
```
39+
40+
```python
41+
<py-script>
42+
from js import console, document
43+
from pyodide.ffi.wrappers import add_event_listener
44+
45+
def hello_args(*args):
46+
console.log(f"Hi! I got some args! {args}")
47+
48+
add_event_listener(document.getElementById("two"), "click", hello_args)
49+
</py-script>
50+
```
51+
52+
or using the `addEventListener` method of the DOM element:
53+
54+
```html
55+
<button id="three">add_event_listener passes event</button>
56+
```
57+
58+
```python
59+
<py-script>
60+
from js import console, document
61+
from pyodide.ffi import create_proxy
62+
63+
def hello_args(*args):
64+
console.log(f"Hi! I got some args! {args}")
65+
66+
document.getElementById("three").addEventListener("click", create_proxy(hello_args))
67+
</py-script>
68+
```
69+
70+
or using the PyScript Element class:
71+
72+
```html
73+
<button id="four">add_event_listener passes event</button>
74+
```
75+
76+
```python
77+
<py-script>
78+
from js import console
79+
from pyodide.ffi import create_proxy
80+
81+
def hello_args(*args):
82+
console.log(f"Hi! I got some args! {args}")
83+
84+
Element("four").element.addEventListener("click", create_proxy(hello_args))
85+
</py-script>
86+
```
87+
88+
## JavaScript to PyScript and From PyScript to JavaScript
89+
90+
If you're wondering about how to pass objects from JavaScript to PyScript and/or the other way around head over to the [Passing Objects](passing-objects.md) page.
91+
92+
93+
### Exporting all Global Python Objects
94+
95+
We can use our new `createObject` function to "export" the entire Python global object dictionary as a JavaScript object:
96+
97+
```python
98+
<py-script>
99+
from js import createObject
100+
from pyodide.ffi import create_proxy
101+
createObject(create_proxy(globals()), "pyodideGlobals")
102+
</py-script>
103+
```
104+
105+
This will make all Python global variables available in JavaScript with `pyodideGlobals.get('my_variable_name')`.
106+
107+
(Since PyScript tags evaluate _after_ all JavaScript on the page, we can't just dump a `console.log(...)` into a `<script>` tag, since that tag will evaluate before any PyScript has a chance to. We need to delay accessing the Python variable in JavaScript until after the Python code has a chance to run. The following example uses a button with `id="do-math"` to achieve this, but any method would be valid.)
108+
109+
```python
110+
<py-script>
111+
# create some Python objects:
112+
symbols = {'pi': 3.1415926, 'e': 2.7182818}
113+
114+
def rough_exponential(x):
115+
return symbols['e']**x
116+
117+
class Circle():
118+
def __init__(self, radius):
119+
self.radius = radius
120+
121+
@property
122+
def area:
123+
return symbols['pi'] * self.radius**2
124+
</py-script>
125+
```
126+
127+
```html
128+
<input type="button" value="Log Python Variables" id="do-mmath" />
129+
<script>
130+
document.getElementById("do-math").addEventListener("click", () => {
131+
const exp = pyodideGlobals.get("rough_exponential");
132+
console.log("e squared is about ${exp(2)}");
133+
const c = pyodideGlobals.get("Circle")(4);
134+
console.log("The area of c is ${c.area}");
135+
});
136+
</script>
137+
```
138+
139+
### Exporting Individual Python Objects
140+
141+
We can also export individual Python objects to the JavaScript global scope if we wish.
142+
143+
(As above, the following example uses a button to delay the execution of the `<script>` until after the PyScript has run.)
144+
145+
```python
146+
<py-script>
147+
import js
148+
from pyodide.ffi import create_proxy
149+
150+
# Create 3 python objects
151+
language = "Python 3"
152+
animals = ['dog', 'cat', 'bird']
153+
multiply3 = lambda a, b, c: a * b * c
154+
155+
# js object can be named the same as Python objects...
156+
js.createObject(language, "language")
157+
158+
# ...but don't have to be
159+
js.createObject(create_proxy(animals), "animals_from_py")
160+
161+
# functions are objects too, in both Python and Javascript
162+
js.createObject(create_proxy(multiply3), "multiply")
163+
</py-script>
164+
```
165+
166+
```html
167+
<input type="button" value="Log Python Variables" id="log-python-variables" />
168+
<script>
169+
document
170+
.getElementById("log-python-variables")
171+
.addEventListener("click", () => {
172+
console.log(`Nice job using ${language}`);
173+
for (const animal of animals_from_py) {
174+
console.log(`Do you like ${animal}s? `);
175+
}
176+
console.log(`2 times 3 times 4 is ${multiply(2, 3, 4)}`);
177+
});
178+
</script>
179+
```

docs/guides/http-requests.md

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ for dealing with the response, such as `json()` or `status`. See the
3535
[FetchResponse documentation](https://pyodide.org/en/stable/usage/api/python-api/http.html#pyodide.http.FetchResponse)
3636
for more information.
3737

38-
# Example
38+
## Example
39+
3940
We will make async HTTP requests to [JSONPlaceholder](https://jsonplaceholder.typicode.com/)'s fake API using `pyfetch`.
4041
First we write a helper function in pure Python that makes a request and returns the response. This function
4142
makes it easier to make specific types of requests with the most common parameters.
@@ -70,6 +71,7 @@ async def request(url: str, method: str = "GET", body: Optional[str] = None,
7071
response = await pyfetch(url, **kwargs)
7172
return response
7273
```
74+
7375
This function is a wrapper for `pyfetch`, which is a wrapper for the `fetch` API. It is a coroutine function,
7476
so it must be awaited. It also has type hints, which are not required, but are useful for IDEs and other tools.
7577
The basic idea is that the `PyScript` will import and call this function, then await the response. Therefore,
@@ -160,7 +162,8 @@ concluding html code.
160162
The very first thing to notice is the `py-config` tag. This tag is used to import Python files into the `PyScript`.
161163
In this case, we are importing the `request.py` file, which contains the `request` function we wrote above.
162164

163-
### `py-script` tag for making async HTTP requests.
165+
### `py-script` tag for making async HTTP requests
166+
164167
Next, the `py-script` tag contains the actual Python code where we import `asyncio` and `json`,
165168
which are required or helpful for the `request` function.
166169
The `# GET`, `# POST`, `# PUT`, `# DELETE` blocks show examples of how to use the `request` function to make basic
@@ -169,6 +172,7 @@ HTTP requests. The `await` keyword is required not only for the `request` functi
169172
faster ones.
170173

171174
### HTTP Requests
175+
172176
HTTP requests are a very common way to communicate with a server. They are used for everything from getting data from
173177
a database, to sending emails, to authorization, and more. Due to safety concerns, files loaded from the
174178
local file system are not accessible by `PyScript`. Therefore, the proper way to load data into `PyScript` is also
@@ -182,31 +186,38 @@ function or to `pyfetch`. See the
182186
HTTP requests are defined by standards-setting bodies in [RFC 1945](https://www.rfc-editor.org/info/rfc1945) and
183187
[RFC 9110](https://www.rfc-editor.org/info/rfc9110).
184188

185-
# Conclusion
189+
## Conclusion
190+
186191
This tutorial demonstrates how to make HTTP requests using `pyfetch` and the `FetchResponse` objects. Importing Python
187192
code/files into the `PyScript` using the `py-config` tag is also covered.
188193

189194
Although a simple example, the principals here can be used to create complex web applications inside of `PyScript`,
190195
or load data into `PyScript` for use by an application, all served as a static HTML page, which is pretty amazing!
191196

197+
## API Quick Reference
192198

193-
# API Quick Reference
194199
## pyodide.http.pyfetch
195-
### Usage
200+
201+
### pyfetch Usage
202+
196203
```python
197204
await pyodide.http.pyfetch(url: str, **kwargs: Any) -> FetchResponse
198205
```
206+
199207
Use `pyfetch` to make HTTP requests in `PyScript`. This is a wrapper around the `fetch` API. Returns a `FetchResponse`.
200208

201209
- [`pyfetch` Docs.](https://pyodide.org/en/stable/usage/api/python-api/http.html#pyodide.http.pyfetch)
202210

203211
## pyodide.http.FetchResponse
204-
### Usage
212+
213+
### FetchResponse Usage
214+
205215
```python
206216
response: pyodide.http.FetchResponse = await <pyfetch call>
207217
status = response.status
208218
json = await response.json()
209219
```
220+
210221
Class for handling HTTP responses. This is a wrapper around the `JavaScript` fetch `Response`. Contains common (async)
211222
methods and properties for handling HTTP responses, such as `json()`, `url`, `status`, `headers`, etc.
212223

docs/guides/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ passing-objects
1818
http-requests
1919
asyncio
2020
custom-plugins
21+
event-handlers
2122
```

0 commit comments

Comments
 (0)
0