python-fasthtml 0.12.39__tar.gz → 0.12.41__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_fasthtml-0.12.39/python_fasthtml.egg-info → python_fasthtml-0.12.41}/PKG-INFO +10 -25
- python_fasthtml-0.12.41/fasthtml/__init__.py +2 -0
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/fasthtml/_modidx.py +8 -1
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/fasthtml/cli.py +5 -5
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/fasthtml/components.py +20 -20
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/fasthtml/core.py +84 -82
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/fasthtml/js.py +10 -10
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/fasthtml/jupyter.py +17 -16
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/fasthtml/oauth.py +65 -41
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/fasthtml/pico.py +11 -11
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/fasthtml/starlette.py +1 -1
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/fasthtml/stripe_otp.py +18 -18
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/fasthtml/svg.py +19 -19
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/fasthtml/xtend.py +41 -41
- python_fasthtml-0.12.41/pyproject.toml +41 -0
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41/python_fasthtml.egg-info}/PKG-INFO +10 -25
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/python_fasthtml.egg-info/SOURCES.txt +0 -3
- python_fasthtml-0.12.39/fasthtml/__init__.py +0 -2
- python_fasthtml-0.12.39/pyproject.toml +0 -11
- python_fasthtml-0.12.39/python_fasthtml.egg-info/not-zip-safe +0 -1
- python_fasthtml-0.12.39/settings.ini +0 -43
- python_fasthtml-0.12.39/setup.py +0 -57
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/CONTRIBUTING.md +0 -0
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/LICENSE +0 -0
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/MANIFEST.in +0 -0
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/README.md +0 -0
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/fasthtml/authmw.py +0 -0
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/fasthtml/basics.py +0 -0
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/fasthtml/common.py +0 -0
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/fasthtml/components.pyi +0 -0
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/fasthtml/core.pyi +0 -0
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/fasthtml/fastapp.py +0 -0
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/fasthtml/ft.py +0 -0
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/fasthtml/katex.js +0 -0
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/fasthtml/live_reload.py +0 -0
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/fasthtml/toaster.py +0 -0
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/fasthtml/xtend.pyi +0 -0
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/python_fasthtml.egg-info/dependency_links.txt +0 -0
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/python_fasthtml.egg-info/entry_points.txt +0 -0
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/python_fasthtml.egg-info/requires.txt +0 -0
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/python_fasthtml.egg-info/top_level.txt +0 -0
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/setup.cfg +0 -0
- {python_fasthtml-0.12.39 → python_fasthtml-0.12.41}/tests/test_toaster.py +0 -0
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-fasthtml
|
|
3
|
-
Version: 0.12.
|
|
3
|
+
Version: 0.12.41
|
|
4
4
|
Summary: The fastest way to create an HTML app
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Keywords: nbdev
|
|
10
|
-
Classifier: Development Status :: 4 - Beta
|
|
11
|
-
Classifier: Intended Audience :: Developers
|
|
5
|
+
Author-email: Jeremy Howard and contributors <github@jhoward.fastmail.fm>
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Project-URL: Repository, https://github.com/AnswerDotAI/fasthtml
|
|
8
|
+
Project-URL: Documentation, https://www.fastht.ml/docs/
|
|
9
|
+
Keywords: nbdev,jupyter,notebook,python
|
|
12
10
|
Classifier: Natural Language :: English
|
|
13
|
-
Classifier:
|
|
14
|
-
Classifier:
|
|
15
|
-
Classifier: Programming Language :: Python :: 3
|
|
16
|
-
Classifier: Programming Language :: Python :: 3
|
|
17
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
15
|
Requires-Python: >=3.10
|
|
19
16
|
Description-Content-Type: text/markdown
|
|
20
17
|
License-File: LICENSE
|
|
@@ -34,19 +31,7 @@ Requires-Dist: lxml; extra == "dev"
|
|
|
34
31
|
Requires-Dist: pysymbol_llm; extra == "dev"
|
|
35
32
|
Requires-Dist: monsterui; extra == "dev"
|
|
36
33
|
Requires-Dist: PyJWT; extra == "dev"
|
|
37
|
-
Dynamic: author
|
|
38
|
-
Dynamic: author-email
|
|
39
|
-
Dynamic: classifier
|
|
40
|
-
Dynamic: description
|
|
41
|
-
Dynamic: description-content-type
|
|
42
|
-
Dynamic: home-page
|
|
43
|
-
Dynamic: keywords
|
|
44
|
-
Dynamic: license
|
|
45
34
|
Dynamic: license-file
|
|
46
|
-
Dynamic: provides-extra
|
|
47
|
-
Dynamic: requires-dist
|
|
48
|
-
Dynamic: requires-python
|
|
49
|
-
Dynamic: summary
|
|
50
35
|
|
|
51
36
|
# FastHTML
|
|
52
37
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Autogenerated by nbdev
|
|
2
2
|
|
|
3
3
|
d = { 'settings': { 'branch': 'main',
|
|
4
|
-
'doc_baseurl': '/docs
|
|
4
|
+
'doc_baseurl': '/docs',
|
|
5
5
|
'doc_host': 'https://www.fastht.ml',
|
|
6
6
|
'git_url': 'https://github.com/AnswerDotAI/fasthtml',
|
|
7
7
|
'lib_path': 'fasthtml'},
|
|
@@ -203,10 +203,17 @@ d = { 'settings': { 'branch': 'main',
|
|
|
203
203
|
'fasthtml.oauth._AppClient': ('api/oauth.html#_appclient', 'fasthtml/oauth.py'),
|
|
204
204
|
'fasthtml.oauth._AppClient.__init__': ('api/oauth.html#_appclient.__init__', 'fasthtml/oauth.py'),
|
|
205
205
|
'fasthtml.oauth._AppClient.get_info': ('api/oauth.html#_appclient.get_info', 'fasthtml/oauth.py'),
|
|
206
|
+
'fasthtml.oauth._AppClient.get_info_async': ( 'api/oauth.html#_appclient.get_info_async',
|
|
207
|
+
'fasthtml/oauth.py'),
|
|
206
208
|
'fasthtml.oauth._AppClient.parse_response': ( 'api/oauth.html#_appclient.parse_response',
|
|
207
209
|
'fasthtml/oauth.py'),
|
|
210
|
+
'fasthtml.oauth._AppClient.parse_response_async': ( 'api/oauth.html#_appclient.parse_response_async',
|
|
211
|
+
'fasthtml/oauth.py'),
|
|
208
212
|
'fasthtml.oauth._AppClient.retr_id': ('api/oauth.html#_appclient.retr_id', 'fasthtml/oauth.py'),
|
|
209
213
|
'fasthtml.oauth._AppClient.retr_info': ('api/oauth.html#_appclient.retr_info', 'fasthtml/oauth.py'),
|
|
214
|
+
'fasthtml.oauth._AppClient.retr_info_async': ( 'api/oauth.html#_appclient.retr_info_async',
|
|
215
|
+
'fasthtml/oauth.py'),
|
|
216
|
+
'fasthtml.oauth._arun': ('api/oauth.html#_arun', 'fasthtml/oauth.py'),
|
|
210
217
|
'fasthtml.oauth.get_host': ('api/oauth.html#get_host', 'fasthtml/oauth.py'),
|
|
211
218
|
'fasthtml.oauth.load_creds': ('api/oauth.html#load_creds', 'fasthtml/oauth.py'),
|
|
212
219
|
'fasthtml.oauth.redir_url': ('api/oauth.html#redir_url', 'fasthtml/oauth.py'),
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/09_cli.ipynb.
|
|
2
2
|
|
|
3
|
-
# %% auto 0
|
|
3
|
+
# %% auto #0
|
|
4
4
|
__all__ = ['railway_link', 'railway_deploy']
|
|
5
5
|
|
|
6
|
-
# %% ../nbs/api/09_cli.ipynb
|
|
6
|
+
# %% ../nbs/api/09_cli.ipynb #acfbc502
|
|
7
7
|
from fastcore.utils import *
|
|
8
8
|
from fastcore.script import call_parse, bool_arg
|
|
9
9
|
from subprocess import check_output, run
|
|
10
10
|
|
|
11
11
|
import json
|
|
12
12
|
|
|
13
|
-
# %% ../nbs/api/09_cli.ipynb
|
|
13
|
+
# %% ../nbs/api/09_cli.ipynb #11d71cfc
|
|
14
14
|
@call_parse
|
|
15
15
|
def railway_link():
|
|
16
16
|
"Link the current directory to the current project's Railway service"
|
|
@@ -23,12 +23,12 @@ def railway_link():
|
|
|
23
23
|
cmd = f"railway link -e {env} -p {prj} -s {svc}"
|
|
24
24
|
res = check_output(cmd.split())
|
|
25
25
|
|
|
26
|
-
# %% ../nbs/api/09_cli.ipynb
|
|
26
|
+
# %% ../nbs/api/09_cli.ipynb #586830f6
|
|
27
27
|
def _run(a, **kw):
|
|
28
28
|
print('#', ' '.join(a))
|
|
29
29
|
run(a)
|
|
30
30
|
|
|
31
|
-
# %% ../nbs/api/09_cli.ipynb
|
|
31
|
+
# %% ../nbs/api/09_cli.ipynb #b84fd5ff
|
|
32
32
|
@call_parse
|
|
33
33
|
def railway_deploy(
|
|
34
34
|
name:str, # The project name to deploy
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/01_components.ipynb.
|
|
4
4
|
|
|
5
|
-
# %% auto 0
|
|
5
|
+
# %% auto #0
|
|
6
6
|
__all__ = ['named', 'html_attrs', 'hx_attrs', 'hx_evts', 'js_evts', 'hx_attrs_annotations', 'hx_evt_attrs', 'js_evt_attrs',
|
|
7
7
|
'evt_attrs', 'attrmap_x', 'ft_html', 'ft_hx', 'File', 'show', 'fill_form', 'fill_dataclass', 'find_inputs',
|
|
8
8
|
'html2ft', 'sse_message', 'A', 'Abbr', 'Address', 'Area', 'Article', 'Aside', 'Audio', 'B', 'Base', 'Bdi',
|
|
@@ -16,7 +16,7 @@ __all__ = ['named', 'html_attrs', 'hx_attrs', 'hx_evts', 'js_evts', 'hx_attrs_an
|
|
|
16
16
|
'Tbody', 'Td', 'Template', 'Textarea', 'Tfoot', 'Th', 'Thead', 'Time', 'Title', 'Tr', 'Track', 'U', 'Ul',
|
|
17
17
|
'Var', 'Video', 'Wbr']
|
|
18
18
|
|
|
19
|
-
# %% ../nbs/api/01_components.ipynb
|
|
19
|
+
# %% ../nbs/api/01_components.ipynb #8e2d405b
|
|
20
20
|
from dataclasses import dataclass, asdict, is_dataclass, make_dataclass, replace, astuple, MISSING
|
|
21
21
|
from bs4 import BeautifulSoup, Comment
|
|
22
22
|
from typing import Literal, Mapping, Optional
|
|
@@ -32,19 +32,19 @@ import types, json
|
|
|
32
32
|
try: from IPython import display
|
|
33
33
|
except ImportError: display=None
|
|
34
34
|
|
|
35
|
-
# %% ../nbs/api/01_components.ipynb
|
|
35
|
+
# %% ../nbs/api/01_components.ipynb #dc101f0f
|
|
36
36
|
@patch
|
|
37
37
|
def __str__(self:FT): return self.id if self.id else to_xml(self, indent=False)
|
|
38
38
|
|
|
39
|
-
# %% ../nbs/api/01_components.ipynb
|
|
39
|
+
# %% ../nbs/api/01_components.ipynb #a10500cb
|
|
40
40
|
@patch
|
|
41
41
|
def __radd__(self:FT, b): return f'{b}{self}'
|
|
42
42
|
|
|
43
|
-
# %% ../nbs/api/01_components.ipynb
|
|
43
|
+
# %% ../nbs/api/01_components.ipynb #992319c5
|
|
44
44
|
@patch
|
|
45
45
|
def __add__(self:FT, b): return f'{self}{b}'
|
|
46
46
|
|
|
47
|
-
# %% ../nbs/api/01_components.ipynb
|
|
47
|
+
# %% ../nbs/api/01_components.ipynb #0ff9acc3
|
|
48
48
|
named = set('a button form frame iframe img input map meta object param select textarea'.split())
|
|
49
49
|
html_attrs = 'id cls title style accesskey contenteditable dir draggable enterkeyhint hidden inert inputmode lang popover spellcheck tabindex translate'.split()
|
|
50
50
|
hx_attrs = 'get post put delete patch trigger target swap swap_oob include select select_oob indicator push_url confirm disable replace_url vals disabled_elt ext headers history history_elt indicator inherit params preserve prompt replace_url request sync validate'
|
|
@@ -70,19 +70,19 @@ hx_evt_attrs = ['hx_on__'+camel2snake(o).replace(':','_') for o in hx_evts.split
|
|
|
70
70
|
js_evt_attrs = ['hx_on_'+o for o in js_evts.split()]
|
|
71
71
|
evt_attrs = js_evt_attrs+hx_evt_attrs
|
|
72
72
|
|
|
73
|
-
# %% ../nbs/api/01_components.ipynb
|
|
73
|
+
# %% ../nbs/api/01_components.ipynb #f904f825
|
|
74
74
|
def attrmap_x(o):
|
|
75
75
|
if o.startswith('_at_'): o = '@'+o[4:]
|
|
76
76
|
return attrmap(o)
|
|
77
77
|
|
|
78
|
-
# %% ../nbs/api/01_components.ipynb
|
|
78
|
+
# %% ../nbs/api/01_components.ipynb #ee041be0
|
|
79
79
|
fh_cfg['attrmap']=attrmap_x
|
|
80
80
|
fh_cfg['valmap' ]=valmap
|
|
81
81
|
fh_cfg['ft_cls' ]=FT
|
|
82
82
|
fh_cfg['auto_id']=False
|
|
83
83
|
fh_cfg['auto_name']=True
|
|
84
84
|
|
|
85
|
-
# %% ../nbs/api/01_components.ipynb
|
|
85
|
+
# %% ../nbs/api/01_components.ipynb #c8ade6b4
|
|
86
86
|
def ft_html(tag: str, *c, id=None, cls=None, title=None, style=None, attrmap=None, valmap=None, ft_cls=None, **kwargs):
|
|
87
87
|
ds,c = partition(c, risinstance(Mapping))
|
|
88
88
|
for d in ds: kwargs = {**kwargs, **d}
|
|
@@ -97,7 +97,7 @@ def ft_html(tag: str, *c, id=None, cls=None, title=None, style=None, attrmap=Non
|
|
|
97
97
|
if fh_cfg['auto_name'] and tag in named and id and 'name' not in kw: kw['name'] = kw['id']
|
|
98
98
|
return ft_cls(tag,c,kw, void_=tag in voids)
|
|
99
99
|
|
|
100
|
-
# %% ../nbs/api/01_components.ipynb
|
|
100
|
+
# %% ../nbs/api/01_components.ipynb #d5158b3d
|
|
101
101
|
@use_kwargs(hx_attrs+evt_attrs, keep=True)
|
|
102
102
|
def ft_hx(tag: str, *c, target_id=None, hx_vals=None, hx_target=None, **kwargs):
|
|
103
103
|
if hx_vals: kwargs['hx_vals'] = json.dumps(hx_vals) if isinstance (hx_vals,dict) else hx_vals
|
|
@@ -105,7 +105,7 @@ def ft_hx(tag: str, *c, target_id=None, hx_vals=None, hx_target=None, **kwargs):
|
|
|
105
105
|
if target_id: kwargs['hx_target'] = '#'+target_id
|
|
106
106
|
return ft_html(tag, *c, **kwargs)
|
|
107
107
|
|
|
108
|
-
# %% ../nbs/api/01_components.ipynb
|
|
108
|
+
# %% ../nbs/api/01_components.ipynb #ede9b44d
|
|
109
109
|
_g = globals()
|
|
110
110
|
_all_ = [
|
|
111
111
|
'A', 'Abbr', 'Address', 'Area', 'Article', 'Aside', 'Audio', 'B', 'Base', 'Bdi', 'Bdo', 'Blockquote', 'Body', 'Br',
|
|
@@ -119,12 +119,12 @@ _all_ = [
|
|
|
119
119
|
'Td', 'Template', 'Textarea', 'Tfoot', 'Th', 'Thead', 'Time', 'Title', 'Tr', 'Track', 'U', 'Ul', 'Var', 'Video', 'Wbr']
|
|
120
120
|
for o in _all_: _g[o] = partial(ft_hx, o.lower())
|
|
121
121
|
|
|
122
|
-
# %% ../nbs/api/01_components.ipynb
|
|
122
|
+
# %% ../nbs/api/01_components.ipynb #fab04fb3
|
|
123
123
|
def File(fname):
|
|
124
124
|
"Use the unescaped text in file `fname` directly"
|
|
125
125
|
return NotStr(Path(fname).read_text())
|
|
126
126
|
|
|
127
|
-
# %% ../nbs/api/01_components.ipynb
|
|
127
|
+
# %% ../nbs/api/01_components.ipynb #7861dfe6
|
|
128
128
|
def show(ft, *rest, iframe=False, height='auto', style=None):
|
|
129
129
|
"Renders FT Components into HTML within a Jupyter notebook."
|
|
130
130
|
if isinstance(ft, str): ft = Safe(ft)
|
|
@@ -138,7 +138,7 @@ def show(ft, *rest, iframe=False, height='auto', style=None):
|
|
|
138
138
|
warnings.simplefilter("ignore", UserWarning)
|
|
139
139
|
display.display(display.HTML(res))
|
|
140
140
|
|
|
141
|
-
# %% ../nbs/api/01_components.ipynb
|
|
141
|
+
# %% ../nbs/api/01_components.ipynb #1df362c7
|
|
142
142
|
def _fill_item(item, obj):
|
|
143
143
|
if not isinstance(item,FT): return item
|
|
144
144
|
tag,cs,attr = item.list
|
|
@@ -168,20 +168,20 @@ def _fill_item(item, obj):
|
|
|
168
168
|
if option: option.selected = '1'
|
|
169
169
|
return FT(tag,cs,attr,void_=item.void_)
|
|
170
170
|
|
|
171
|
-
# %% ../nbs/api/01_components.ipynb
|
|
171
|
+
# %% ../nbs/api/01_components.ipynb #f0c83f26
|
|
172
172
|
def fill_form(form:FT, obj)->FT:
|
|
173
173
|
"Fills named items in `form` using attributes in `obj`"
|
|
174
174
|
if is_dataclass(obj): obj = asdict(obj)
|
|
175
175
|
elif not isinstance(obj,dict): obj = obj.__dict__
|
|
176
176
|
return _fill_item(form, obj)
|
|
177
177
|
|
|
178
|
-
# %% ../nbs/api/01_components.ipynb
|
|
178
|
+
# %% ../nbs/api/01_components.ipynb #8b171490
|
|
179
179
|
def fill_dataclass(src, dest):
|
|
180
180
|
"Modifies dataclass in-place and returns it"
|
|
181
181
|
for nm,val in asdict(src).items(): setattr(dest, nm, val)
|
|
182
182
|
return dest
|
|
183
183
|
|
|
184
|
-
# %% ../nbs/api/01_components.ipynb
|
|
184
|
+
# %% ../nbs/api/01_components.ipynb #c9594f70
|
|
185
185
|
def find_inputs(e, tags='input', **kw):
|
|
186
186
|
"Recursively find all elements in `e` with `tags` and attrs matching `kw`"
|
|
187
187
|
if not isinstance(e, (list,tuple,FT)): return []
|
|
@@ -195,14 +195,14 @@ def find_inputs(e, tags='input', **kw):
|
|
|
195
195
|
for o in cs: inputs += find_inputs(o, tags, **kw)
|
|
196
196
|
return inputs
|
|
197
197
|
|
|
198
|
-
# %% ../nbs/api/01_components.ipynb
|
|
198
|
+
# %% ../nbs/api/01_components.ipynb #1d8a28b1
|
|
199
199
|
def __getattr__(tag):
|
|
200
200
|
if tag.startswith('_') or tag[0].islower(): raise AttributeError
|
|
201
201
|
tag = tag.replace("_", "-")
|
|
202
202
|
def _f(*c, target_id=None, **kwargs): return ft_hx(tag, *c, target_id=target_id, **kwargs)
|
|
203
203
|
return _f
|
|
204
204
|
|
|
205
|
-
# %% ../nbs/api/01_components.ipynb
|
|
205
|
+
# %% ../nbs/api/01_components.ipynb #afb0f65c
|
|
206
206
|
_re_h2x_attr_key = re.compile(r'^[A-Za-z_-][\w-]*$')
|
|
207
207
|
def html2ft(html, attr1st=False):
|
|
208
208
|
"""Convert HTML to an `ft` expression"""
|
|
@@ -243,7 +243,7 @@ def html2ft(html, attr1st=False):
|
|
|
243
243
|
for c in soup.find_all(string=risinstance(Comment)): c.extract()
|
|
244
244
|
return _parse(soup, 1)
|
|
245
245
|
|
|
246
|
-
# %% ../nbs/api/01_components.ipynb
|
|
246
|
+
# %% ../nbs/api/01_components.ipynb #c6203402
|
|
247
247
|
def sse_message(elm, event='message'):
|
|
248
248
|
"Convert element `elm` into a format suitable for SSE streaming"
|
|
249
249
|
data = '\n'.join(f'data: {o}' for o in to_xml(elm).splitlines())
|