home-fasthtml / docs /api /jupyter.html.md
AItool's picture
Upload 210 files
036b3a6 verified
# Jupyter compatibility
<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->
``` python
from httpx import get, AsyncClient
```
## Helper functions
------------------------------------------------------------------------
<a
href="https://github.com/AnswerDotAI/fasthtml/blob/main/fasthtml/jupyter.py#L21"
target="_blank" style="float:right; font-size:smaller">source</a>
### nb_serve
> nb_serve (app, log_level='error', port=8000, host='0.0.0.0', **kwargs)
*Start a Jupyter compatible uvicorn server with ASGI `app` on `port`
with `log_level`*
------------------------------------------------------------------------
<a
href="https://github.com/AnswerDotAI/fasthtml/blob/main/fasthtml/jupyter.py#L31"
target="_blank" style="float:right; font-size:smaller">source</a>
### nb_serve_async
> nb_serve_async (app, log_level='error', port=8000, host='0.0.0.0',
> **kwargs)
*Async version of
[`nb_serve`](https://www.fastht.ml/docs/api/jupyter.html#nb_serve)*
------------------------------------------------------------------------
<a
href="https://github.com/AnswerDotAI/fasthtml/blob/main/fasthtml/jupyter.py#L39"
target="_blank" style="float:right; font-size:smaller">source</a>
### is_port_free
> is_port_free (port, host='localhost')
*Check if `port` is free on `host`*
------------------------------------------------------------------------
<a
href="https://github.com/AnswerDotAI/fasthtml/blob/main/fasthtml/jupyter.py#L50"
target="_blank" style="float:right; font-size:smaller">source</a>
### wait_port_free
> wait_port_free (port, host='localhost', max_wait=3)
*Wait for `port` to be free on `host`*
## Using FastHTML in Jupyter
------------------------------------------------------------------------
<a
href="https://github.com/AnswerDotAI/fasthtml/blob/main/fasthtml/components.py#L128"
target="_blank" style="float:right; font-size:smaller">source</a>
### show
> show (*s, iframe=False, height='auto', style=None)
*Same as fasthtml.components.show, but also adds `htmx.process()`*
------------------------------------------------------------------------
<a
href="https://github.com/AnswerDotAI/fasthtml/blob/main/fasthtml/jupyter.py#L65"
target="_blank" style="float:right; font-size:smaller">source</a>
### render_ft
> render_ft ()
------------------------------------------------------------------------
<a
href="https://github.com/AnswerDotAI/fasthtml/blob/main/fasthtml/jupyter.py#L70"
target="_blank" style="float:right; font-size:smaller">source</a>
### htmx_config_port
> htmx_config_port (port=8000)
------------------------------------------------------------------------
<a
href="https://github.com/AnswerDotAI/fasthtml/blob/main/fasthtml/jupyter.py#L81"
target="_blank" style="float:right; font-size:smaller">source</a>
### JupyUvi
> JupyUvi (app, log_level='error', host='0.0.0.0', port=8000, start=True,
> **kwargs)
*Start and stop a Jupyter compatible uvicorn server with ASGI `app` on
`port` with `log_level`*
Creating an object of this class also starts the Uvicorn server. It runs
in a separate thread, so you can use normal HTTP client functions in a
notebook.
``` python
app = FastHTML()
rt = app.route
@app.route
def index(): return 'hi'
port = 8000
server = JupyUvi(app, port=port)
```
<script>
document.body.addEventListener('htmx:configRequest', (event) => {
if(event.detail.path.includes('://')) return;
htmx.config.selfRequestsOnly=false;
event.detail.path = `${location.protocol}//${location.hostname}:8000${event.detail.path}`;
});
</script>
``` python
get(f'http://localhost:{port}').text
```
'hi'
You can stop the server, modify routes, and start the server again
without restarting the notebook or recreating the server or application.
``` python
server.stop()
```
``` python
app = FastHTML()
rt = app.route
@app.route
async def index(): return 'hi'
server = JupyUvi(app, port=port, start=False)
await server.start_async()
```
<script>
document.body.addEventListener('htmx:configRequest', (event) => {
if(event.detail.path.includes('://')) return;
htmx.config.selfRequestsOnly=false;
event.detail.path = `${location.protocol}//${location.hostname}:8000${event.detail.path}`;
});
</script>
``` python
print((await AsyncClient().get(f'http://localhost:{port}')).text)
```
hi
------------------------------------------------------------------------
<a
href="https://github.com/AnswerDotAI/fasthtml/blob/main/fasthtml/jupyter.py#L101"
target="_blank" style="float:right; font-size:smaller">source</a>
### JupyUviAsync
> JupyUviAsync (app, log_level='error', host='0.0.0.0', port=8000,
> **kwargs)
*Start and stop an async Jupyter compatible uvicorn server with ASGI
`app` on `port` with `log_level`*
``` python
server = JupyUviAsync(app, port=port)
await server.start()
```
<script>
document.body.addEventListener('htmx:configRequest', (event) => {
if(event.detail.path.includes('://')) return;
htmx.config.selfRequestsOnly=false;
event.detail.path = `${location.protocol}//${location.hostname}:8000${event.detail.path}`;
});
</script>
``` python
async with AsyncClient() as client:
r = await client.get(f'http://localhost:{port}')
print(r.text)
```
hi
``` python
server.stop()
```
### Using a notebook as a web app
You can also run an HTMX web app directly in a notebook. To make this
work, you have to add the default FastHTML headers to the DOM of the
notebook with `show(*def_hdrs())`. Additionally, you might find it
convenient to use *auto_id* mode, in which the ID of an `FT` object is
automatically generated if not provided.
``` python
fh_cfg['auto_id' ]=True
```
After importing `fasthtml.jupyter` and calling
[`render_ft()`](https://www.fastht.ml/docs/api/jupyter.html#render_ft),
FT components render directly in the notebook.
``` python
show(*def_hdrs())
render_ft()
```
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<script src="https://unpkg.com/[email protected]/dist/htmx.min.js"></script><script src="https://cdn.jsdelivr.net/gh/answerdotai/[email protected]/fasthtml.js"></script><script src="https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js"></script><script src="https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js"></script><script id="_7KKmEIAnRE_-M4c4Lf5dJg">if (window.htmx) htmx.process(document.body)</script>
``` python
(c := Div('Cogito ergo sum'))
```
<div id="_NNvXojeGS-eH1SZLG-pE4Q">
<div id="_vzHRxQNEQiaSQnLdUFq2Mg">
Cogito ergo sum
</div>
<script id="_SN7to4-bQ5O09J6vs2UvNA">if (window.htmx) htmx.process(document.body)</script>
</div>
Handlers are written just like a regular web app:
``` python
server = JupyUvi(app, port=port)
```
<script>
document.body.addEventListener('htmx:configRequest', (event) => {
if(event.detail.path.includes('://')) return;
htmx.config.selfRequestsOnly=false;
event.detail.path = `${location.protocol}//${location.hostname}:8000${event.detail.path}`;
});
</script>
``` python
@rt
def hoho(): return P('loaded!'), Div('hee hee', id=c, hx_swap_oob='true')
```
All the usual `hx_*` attributes can be used:
``` python
P('not loaded', hx_get=hoho, hx_trigger='load')
```
<div id="_l0IdURqdSRu46RNQQPmMvA">
<p hx-get="/hoho" hx-trigger="load" id="_WUPc1vlnQUStT30OWNXAHQ">
not loaded
</p>
<script id="_o4Z4wNOxQXum9LI9N-YhRw">if (window.htmx) htmx.process(document.body)</script>
</div>
FT components can be used directly both as `id` values and as
`hx_target` values.
``` python
(c := Div(''))
```
<div id="_C4mtvDiLQPyjFBL_N9guOQ">
<div id="_dazDkLiNRi_5IRjKxnDApQ">
</div>
<script id="_wBaWxkrPTeyFjAjoTOAjaw">if (window.htmx) htmx.process(document.body)</script>
</div>
``` python
@rt
def foo(): return Div('foo bar')
P('hi', hx_get=foo, hx_trigger='load', hx_target=c)
```
<div id="_mmZ8zN0IQRWcwaaJuPD17g">
<p hx-get="/foo" hx-trigger="load" hx-target="#_dazDkLiNRi_5IRjKxnDApQ" id="_21sjPwFeSPKp3vncj4YJrQ">
hi
</p>
<script id="_iy4Ov4wQRsuuB6ekh8semw">if (window.htmx) htmx.process(document.body)</script>
</div>
``` python
server.stop()
```
### Running apps in an IFrame
Using an IFrame can be a good idea to get complete isolation of the
styles and scripts in an app. The
[`HTMX`](https://www.fastht.ml/docs/api/jupyter.html#htmx) function
creates an auto-sizing IFrame for a web app.
------------------------------------------------------------------------
<a
href="https://github.com/AnswerDotAI/fasthtml/blob/main/fasthtml/jupyter.py#L114"
target="_blank" style="float:right; font-size:smaller">source</a>
### HTMX
> HTMX (path='', app=None, host='localhost', port=8000, height='auto',
> link=False, iframe=True)
*An iframe which displays the HTMX application in a notebook.*
``` python
@rt
def index():
return Div(
P(A('Click me', hx_get=update, hx_target='#result')),
P(A('No me!', hx_get=update, hx_target='#result')),
Div(id='result'))
@rt
def update(): return Div(P('Hi!'),P('There!'))
```
``` python
server.start()
```
``` python
# Run the notebook locally to see the HTMX iframe in action
HTMX()
```
<iframe src="http://localhost:8000" style="width: 100%; height: auto; border: none;" onload="{
let frame = this;
window.addEventListener('message', function(e) {
if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
}, false);
}" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe>
``` python
server.stop()
```
------------------------------------------------------------------------
<a
href="https://github.com/AnswerDotAI/fasthtml/blob/main/fasthtml/jupyter.py#L135"
target="_blank" style="float:right; font-size:smaller">source</a>
### ws_client
> ws_client (app, nm='', host='localhost', port=8000, ws_connect='/ws',
> frame=True, link=True, **kwargs)