python-fasthtml 0.12.32__tar.gz → 0.12.34__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.32/python_fasthtml.egg-info → python_fasthtml-0.12.34}/PKG-INFO +1 -1
- python_fasthtml-0.12.34/fasthtml/__init__.py +2 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/fasthtml/_modidx.py +1 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/fasthtml/cli.py +1 -1
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/fasthtml/components.py +4 -3
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/fasthtml/core.py +17 -7
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/fasthtml/jupyter.py +5 -2
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34/python_fasthtml.egg-info}/PKG-INFO +1 -1
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/settings.ini +1 -1
- python_fasthtml-0.12.32/fasthtml/__init__.py +0 -2
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/CONTRIBUTING.md +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/LICENSE +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/MANIFEST.in +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/README.md +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/fasthtml/authmw.py +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/fasthtml/basics.py +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/fasthtml/common.py +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/fasthtml/components.pyi +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/fasthtml/core.pyi +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/fasthtml/fastapp.py +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/fasthtml/ft.py +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/fasthtml/js.py +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/fasthtml/katex.js +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/fasthtml/live_reload.py +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/fasthtml/oauth.py +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/fasthtml/pico.py +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/fasthtml/starlette.py +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/fasthtml/stripe_otp.py +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/fasthtml/svg.py +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/fasthtml/toaster.py +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/fasthtml/xtend.py +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/fasthtml/xtend.pyi +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/pyproject.toml +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/python_fasthtml.egg-info/SOURCES.txt +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/python_fasthtml.egg-info/dependency_links.txt +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/python_fasthtml.egg-info/entry_points.txt +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/python_fasthtml.egg-info/not-zip-safe +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/python_fasthtml.egg-info/requires.txt +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/python_fasthtml.egg-info/top_level.txt +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/setup.cfg +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/setup.py +0 -0
- {python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/tests/test_toaster.py +0 -0
|
@@ -46,6 +46,7 @@ d = { 'settings': { 'branch': 'main',
|
|
|
46
46
|
'fasthtml.core.FastHTML._endp': ('api/core.html#fasthtml._endp', 'fasthtml/core.py'),
|
|
47
47
|
'fasthtml.core.FastHTML.add_route': ('api/core.html#fasthtml.add_route', 'fasthtml/core.py'),
|
|
48
48
|
'fasthtml.core.FastHTML.devtools_json': ('api/core.html#fasthtml.devtools_json', 'fasthtml/core.py'),
|
|
49
|
+
'fasthtml.core.FastHTML.get_client': ('api/core.html#fasthtml.get_client', 'fasthtml/core.py'),
|
|
49
50
|
'fasthtml.core.FastHTML.route': ('api/core.html#fasthtml.route', 'fasthtml/core.py'),
|
|
50
51
|
'fasthtml.core.FastHTML.set_lifespan': ('api/core.html#fasthtml.set_lifespan', 'fasthtml/core.py'),
|
|
51
52
|
'fasthtml.core.FastHTML.setup_ws': ('api/core.html#fasthtml.setup_ws', 'fasthtml/core.py'),
|
|
@@ -36,7 +36,7 @@ def railway_deploy(
|
|
|
36
36
|
):
|
|
37
37
|
"""Deploy a FastHTML app to Railway"""
|
|
38
38
|
nm,ver = check_output("railway --version".split()).decode().split()
|
|
39
|
-
assert nm
|
|
39
|
+
assert nm.startswith('railway'), f'Unexpected railway version string: {nm}'
|
|
40
40
|
if ver2tuple(ver)<(3,8): return print("Please update your railway CLI version to 3.8 or higher")
|
|
41
41
|
cp = run("railway status --json".split(), capture_output=True)
|
|
42
42
|
if not cp.returncode:
|
|
@@ -127,6 +127,7 @@ def File(fname):
|
|
|
127
127
|
# %% ../nbs/api/01_components.ipynb
|
|
128
128
|
def show(ft, *rest, iframe=False, height='auto', style=None):
|
|
129
129
|
"Renders FT Components into HTML within a Jupyter notebook."
|
|
130
|
+
if isinstance(ft, str): ft = Safe(ft)
|
|
130
131
|
if rest: ft = (ft,)+rest
|
|
131
132
|
res = to_xml(ft)
|
|
132
133
|
if iframe:
|
|
@@ -206,14 +207,14 @@ _re_h2x_attr_key = re.compile(r'^[A-Za-z_-][\w-]*$')
|
|
|
206
207
|
def html2ft(html, attr1st=False):
|
|
207
208
|
"""Convert HTML to an `ft` expression"""
|
|
208
209
|
rev_map = {'class': 'cls', 'for': 'fr'}
|
|
209
|
-
|
|
210
|
+
|
|
210
211
|
def _parse(elm, lvl=0, indent=4):
|
|
211
|
-
if isinstance(elm, str): return repr(elm.strip()) if elm.strip() else ''
|
|
212
|
+
if isinstance(elm, str): return repr(elm.strip("\n")) if elm.strip() else ''
|
|
212
213
|
if isinstance(elm, list): return '\n'.join(_parse(o, lvl) for o in elm)
|
|
213
214
|
tag_name = elm.name.capitalize().replace("-", "_")
|
|
214
215
|
if tag_name=='[document]': return _parse(list(elm.children), lvl)
|
|
215
216
|
cts = elm.contents
|
|
216
|
-
cs = [repr(c.strip()) if isinstance(c, str) else _parse(c, lvl+1)
|
|
217
|
+
cs = [repr(c.strip("\n")) if isinstance(c, str) else _parse(c, lvl+1)
|
|
217
218
|
for c in cts if str(c).strip()]
|
|
218
219
|
attrs, exotic_attrs = [], {}
|
|
219
220
|
for key, value in sorted(elm.attrs.items(), key=lambda x: x[0]=='class'):
|
|
@@ -12,7 +12,7 @@ __all__ = ['empty', 'htmx_hdrs', 'fh_cfg', 'htmx_resps', 'htmx_exts', 'htmxsrc',
|
|
|
12
12
|
'unqid']
|
|
13
13
|
|
|
14
14
|
# %% ../nbs/api/00_core.ipynb
|
|
15
|
-
import json,uuid,inspect,types,signal,asyncio,threading,inspect,random,contextlib
|
|
15
|
+
import json,uuid,inspect,types,signal,asyncio,threading,inspect,random,contextlib,httpx,itsdangerous
|
|
16
16
|
|
|
17
17
|
from fastcore.utils import *
|
|
18
18
|
from fastcore.xml import *
|
|
@@ -30,7 +30,6 @@ from urllib.parse import urlencode, parse_qs, quote, unquote
|
|
|
30
30
|
from copy import copy,deepcopy
|
|
31
31
|
from warnings import warn
|
|
32
32
|
from dateutil import parser as dtparse
|
|
33
|
-
from httpx import ASGITransport, AsyncClient
|
|
34
33
|
from anyio import from_thread
|
|
35
34
|
from uuid import uuid4, UUID
|
|
36
35
|
from base64 import b85encode,b64encode
|
|
@@ -449,8 +448,8 @@ def _resp(req, resp, cls=empty, status_code=200):
|
|
|
449
448
|
if cls in (Any,FT): cls=empty
|
|
450
449
|
if isinstance(resp, FileResponse) and not os.path.exists(resp.path): raise HTTPException(404, resp.path)
|
|
451
450
|
resp,kw = _part_resp(req, resp)
|
|
452
|
-
if cls is not empty: return cls(resp, status_code=status_code, **kw)
|
|
453
451
|
if isinstance(resp, Response): return resp
|
|
452
|
+
if cls is not empty: return cls(resp, status_code=status_code, **kw)
|
|
454
453
|
if _is_ft_resp(resp):
|
|
455
454
|
cts = _xt_cts(req, resp)
|
|
456
455
|
return HTMLResponse(cts, status_code=status_code, **kw)
|
|
@@ -566,7 +565,7 @@ class FastHTML(Starlette):
|
|
|
566
565
|
same_site='lax', sess_https_only=False, sess_domain=None, key_fname='.sesskey',
|
|
567
566
|
body_wrap=noop_body, htmlkw=None, nb_hdrs=False, canonical=True, **bodykw):
|
|
568
567
|
middleware,before,after = map(_list, (middleware,before,after))
|
|
569
|
-
self.title,self.canonical = title,canonical
|
|
568
|
+
self.title,self.canonical,self.session_cookie,self.key_fname = title,canonical,session_cookie,key_fname
|
|
570
569
|
hdrs,ftrs,exts = map(listify, (hdrs,ftrs,exts))
|
|
571
570
|
exts = {k:htmx_exts[k] for k in exts}
|
|
572
571
|
htmlkw = htmlkw or {}
|
|
@@ -580,9 +579,9 @@ class FastHTML(Starlette):
|
|
|
580
579
|
on_startup,on_shutdown = listify(on_startup) or None,listify(on_shutdown) or None
|
|
581
580
|
self.lifespan,self.hdrs,self.ftrs = lifespan,hdrs,ftrs
|
|
582
581
|
self.body_wrap,self.before,self.after,self.htmlkw,self.bodykw = body_wrap,before,after,htmlkw,bodykw
|
|
583
|
-
secret_key = get_key(secret_key, key_fname)
|
|
582
|
+
self.secret_key = get_key(secret_key, key_fname)
|
|
584
583
|
if sess_cls:
|
|
585
|
-
sess = Middleware(sess_cls, secret_key=secret_key,session_cookie=session_cookie,
|
|
584
|
+
sess = Middleware(sess_cls, secret_key=self.secret_key,session_cookie=session_cookie,
|
|
586
585
|
max_age=max_age, path=sess_path, same_site=same_site,
|
|
587
586
|
https_only=sess_https_only, domain=sess_domain)
|
|
588
587
|
middleware.append(sess)
|
|
@@ -727,7 +726,7 @@ def serve(
|
|
|
727
726
|
class Client:
|
|
728
727
|
"A simple httpx ASGI client that doesn't require `async`"
|
|
729
728
|
def __init__(self, app, url="http://testserver"):
|
|
730
|
-
self.cli = AsyncClient(transport=ASGITransport(app), base_url=url)
|
|
729
|
+
self.cli = httpx.AsyncClient(transport=httpx.ASGITransport(app), base_url=url)
|
|
731
730
|
|
|
732
731
|
def _sync(self, method, url, **kwargs):
|
|
733
732
|
async def _request(): return await self.cli.request(method, url, **kwargs)
|
|
@@ -894,3 +893,14 @@ def devtools_json(self:FastHTML, path=None, uuid=None):
|
|
|
894
893
|
@self.route(devtools_loc)
|
|
895
894
|
def devtools():
|
|
896
895
|
return dict(workspace=dict(root=path, uuid=uuid))
|
|
896
|
+
|
|
897
|
+
# %% ../nbs/api/00_core.ipynb
|
|
898
|
+
@patch
|
|
899
|
+
def get_client(self:FastHTML, asink=False, **kw):
|
|
900
|
+
"Get an httpx client with session cookes set from `**kw`"
|
|
901
|
+
signer = itsdangerous.TimestampSigner(self.secret_key)
|
|
902
|
+
data = b64encode(dumps(kw).encode())
|
|
903
|
+
data = signer.sign(data)
|
|
904
|
+
client = httpx.AsyncClient() if asink else httpx.Client()
|
|
905
|
+
client.cookies.update({self.session_cookie: data.decode()})
|
|
906
|
+
return client
|
|
@@ -62,9 +62,12 @@ def show(*s, **kwargs):
|
|
|
62
62
|
return _show(*s, **kwargs)
|
|
63
63
|
|
|
64
64
|
# %% ../nbs/api/06_jupyter.ipynb
|
|
65
|
-
def render_ft():
|
|
65
|
+
def render_ft(**kw):
|
|
66
|
+
"Call once in a notebook or solveit dialog to auto-render components"
|
|
66
67
|
@patch
|
|
67
|
-
def _repr_markdown_(self:FT):
|
|
68
|
+
def _repr_markdown_(self:FT):
|
|
69
|
+
scr_proc = Script('if (window.htmx) htmx.process(document.body)')
|
|
70
|
+
return to_xml(Div(self, scr_proc, **kw))
|
|
68
71
|
|
|
69
72
|
# %% ../nbs/api/06_jupyter.ipynb
|
|
70
73
|
def htmx_config_port(port=8000):
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[DEFAULT]
|
|
2
2
|
repo = fasthtml
|
|
3
3
|
lib_name = python-fasthtml
|
|
4
|
-
version = 0.12.
|
|
4
|
+
version = 0.12.34
|
|
5
5
|
min_python = 3.10
|
|
6
6
|
license = apache2
|
|
7
7
|
requirements = fastcore>=1.8.1 python-dateutil starlette>0.33 oauthlib itsdangerous uvicorn[standard]>=0.30 httpx fastlite>=0.1.1 python-multipart beautifulsoup4
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/python_fasthtml.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{python_fasthtml-0.12.32 → python_fasthtml-0.12.34}/python_fasthtml.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|