python-fasthtml 0.12.18__tar.gz → 0.12.20__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.
Files changed (42) hide show
  1. {python_fasthtml-0.12.18/python_fasthtml.egg-info → python_fasthtml-0.12.20}/PKG-INFO +1 -1
  2. python_fasthtml-0.12.20/fasthtml/__init__.py +2 -0
  3. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/fasthtml/_modidx.py +2 -1
  4. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/fasthtml/components.py +4 -3
  5. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/fasthtml/components.pyi +1 -1
  6. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/fasthtml/core.py +23 -13
  7. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/fasthtml/core.pyi +4 -4
  8. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/fasthtml/fastapp.py +2 -1
  9. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20/python_fasthtml.egg-info}/PKG-INFO +1 -1
  10. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/settings.ini +1 -1
  11. python_fasthtml-0.12.18/fasthtml/__init__.py +0 -2
  12. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/CONTRIBUTING.md +0 -0
  13. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/LICENSE +0 -0
  14. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/MANIFEST.in +0 -0
  15. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/README.md +0 -0
  16. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/fasthtml/authmw.py +0 -0
  17. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/fasthtml/basics.py +0 -0
  18. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/fasthtml/cli.py +0 -0
  19. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/fasthtml/common.py +0 -0
  20. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/fasthtml/ft.py +0 -0
  21. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/fasthtml/js.py +0 -0
  22. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/fasthtml/jupyter.py +0 -0
  23. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/fasthtml/katex.js +0 -0
  24. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/fasthtml/live_reload.py +0 -0
  25. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/fasthtml/oauth.py +0 -0
  26. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/fasthtml/pico.py +0 -0
  27. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/fasthtml/starlette.py +0 -0
  28. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/fasthtml/stripe_otp.py +0 -0
  29. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/fasthtml/svg.py +0 -0
  30. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/fasthtml/toaster.py +0 -0
  31. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/fasthtml/xtend.py +0 -0
  32. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/fasthtml/xtend.pyi +0 -0
  33. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/pyproject.toml +0 -0
  34. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/python_fasthtml.egg-info/SOURCES.txt +0 -0
  35. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/python_fasthtml.egg-info/dependency_links.txt +0 -0
  36. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/python_fasthtml.egg-info/entry_points.txt +0 -0
  37. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/python_fasthtml.egg-info/not-zip-safe +0 -0
  38. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/python_fasthtml.egg-info/requires.txt +0 -0
  39. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/python_fasthtml.egg-info/top_level.txt +0 -0
  40. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/setup.cfg +0 -0
  41. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/setup.py +0 -0
  42. {python_fasthtml-0.12.18 → python_fasthtml-0.12.20}/tests/test_toaster.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-fasthtml
3
- Version: 0.12.18
3
+ Version: 0.12.20
4
4
  Summary: The fastest way to create an HTML app
5
5
  Home-page: https://github.com/AnswerDotAI/fasthtml
6
6
  Author: Jeremy Howard and contributors
@@ -0,0 +1,2 @@
1
+ __version__ = "0.12.20"
2
+ from .core import *
@@ -47,6 +47,8 @@ d = { 'settings': { 'branch': 'main',
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
49
  'fasthtml.core.FastHTML.route': ('api/core.html#fasthtml.route', 'fasthtml/core.py'),
50
+ 'fasthtml.core.FastHTML.set_lifespan': ('api/core.html#fasthtml.set_lifespan', 'fasthtml/core.py'),
51
+ 'fasthtml.core.FastHTML.setup_ws': ('api/core.html#fasthtml.setup_ws', 'fasthtml/core.py'),
50
52
  'fasthtml.core.FastHTML.static_route': ('api/core.html#fasthtml.static_route', 'fasthtml/core.py'),
51
53
  'fasthtml.core.FastHTML.static_route_exts': ('api/core.html#fasthtml.static_route_exts', 'fasthtml/core.py'),
52
54
  'fasthtml.core.FastHTML.ws': ('api/core.html#fasthtml.ws', 'fasthtml/core.py'),
@@ -118,7 +120,6 @@ d = { 'settings': { 'branch': 'main',
118
120
  'fasthtml.core.reg_re_param': ('api/core.html#reg_re_param', 'fasthtml/core.py'),
119
121
  'fasthtml.core.respond': ('api/core.html#respond', 'fasthtml/core.py'),
120
122
  'fasthtml.core.serve': ('api/core.html#serve', 'fasthtml/core.py'),
121
- 'fasthtml.core.setup_ws': ('api/core.html#setup_ws', 'fasthtml/core.py'),
122
123
  'fasthtml.core.signal_shutdown': ('api/core.html#signal_shutdown', 'fasthtml/core.py'),
123
124
  'fasthtml.core.snake2hyphens': ('api/core.html#snake2hyphens', 'fasthtml/core.py'),
124
125
  'fasthtml.core.unqid': ('api/core.html#unqid', 'fasthtml/core.py'),
@@ -19,7 +19,7 @@ __all__ = ['named', 'html_attrs', 'hx_attrs', 'hx_evts', 'js_evts', 'hx_attrs_an
19
19
  # %% ../nbs/api/01_components.ipynb
20
20
  from dataclasses import dataclass, asdict, is_dataclass, make_dataclass, replace, astuple, MISSING
21
21
  from bs4 import BeautifulSoup, Comment
22
- from typing import Literal, Optional
22
+ from typing import Literal, Mapping, Optional
23
23
 
24
24
  from fastcore.utils import *
25
25
  from fastcore.xml import *
@@ -84,7 +84,7 @@ fh_cfg['auto_name']=True
84
84
 
85
85
  # %% ../nbs/api/01_components.ipynb
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
- ds,c = partition(c, risinstance(dict))
87
+ ds,c = partition(c, risinstance(Mapping))
88
88
  for d in ds: kwargs = {**kwargs, **d}
89
89
  if ft_cls is None: ft_cls = fh_cfg.ft_cls
90
90
  if attrmap is None: attrmap=fh_cfg.attrmap
@@ -217,7 +217,8 @@ def html2ft(html, attr1st=False):
217
217
  for c in cts if str(c).strip()]
218
218
  attrs, exotic_attrs = [], {}
219
219
  for key, value in sorted(elm.attrs.items(), key=lambda x: x[0]=='class'):
220
- if isinstance(value,(tuple,list)): value = " ".join(value)
220
+ if value is None or value == True: value = True # handle boolean attributes
221
+ elif isinstance(value,(tuple,list)): value = " ".join(value)
221
222
  key, value = rev_map.get(key, key), value or True
222
223
  if _re_h2x_attr_key.match(key): attrs.append(f'{key.replace("-", "_")}={value!r}')
223
224
  else: exotic_attrs[key] = value
@@ -2,7 +2,7 @@
2
2
  __all__ = ['named', 'html_attrs', 'hx_attrs', 'hx_evts', 'js_evts', 'hx_attrs_annotations', 'hx_evt_attrs', 'js_evt_attrs', 'evt_attrs', 'attrmap_x', 'ft_html', 'ft_hx', 'File', 'show', 'fill_form', 'fill_dataclass', 'find_inputs', 'html2ft', 'sse_message', 'A', 'Abbr', 'Address', 'Area', 'Article', 'Aside', 'Audio', 'B', 'Base', 'Bdi', 'Bdo', 'Blockquote', 'Body', 'Br', 'Button', 'Canvas', 'Caption', 'Cite', 'Code', 'Col', 'Colgroup', 'Data', 'Datalist', 'Dd', 'Del', 'Details', 'Dfn', 'Dialog', 'Div', 'Dl', 'Dt', 'Em', 'Embed', 'Fencedframe', 'Fieldset', 'Figcaption', 'Figure', 'Footer', 'Form', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'Head', 'Header', 'Hgroup', 'Hr', 'I', 'Iframe', 'Img', 'Input', 'Ins', 'Kbd', 'Label', 'Legend', 'Li', 'Link', 'Main', 'Map', 'Mark', 'Menu', 'Meta', 'Meter', 'Nav', 'Noscript', 'Object', 'Ol', 'Optgroup', 'Option', 'Output', 'P', 'Picture', 'PortalExperimental', 'Pre', 'Progress', 'Q', 'Rp', 'Rt', 'Ruby', 'S', 'Samp', 'Script', 'Search', 'Section', 'Select', 'Slot', 'Small', 'Source', 'Span', 'Strong', 'Style', 'Sub', 'Summary', 'Sup', 'Table', 'Tbody', 'Td', 'Template', 'Textarea', 'Tfoot', 'Th', 'Thead', 'Time', 'Title', 'Tr', 'Track', 'U', 'Ul', 'Var', 'Video', 'Wbr']
3
3
  from dataclasses import dataclass, asdict, is_dataclass, make_dataclass, replace, astuple, MISSING
4
4
  from bs4 import BeautifulSoup, Comment
5
- from typing import Literal, Optional
5
+ from typing import Literal, Mapping, Optional
6
6
  from fastcore.utils import *
7
7
  from fastcore.xml import *
8
8
  from fastcore.meta import use_kwargs, delegates
@@ -8,10 +8,10 @@ __all__ = ['empty', 'htmx_hdrs', 'fh_cfg', 'htmx_resps', 'htmx_exts', 'htmxsrc',
8
8
  'HtmxHeaders', 'HttpHeader', 'HtmxResponseHeaders', 'form2dict', 'parse_form', 'JSONResponse', 'flat_xt',
9
9
  'Beforeware', 'EventStream', 'signal_shutdown', 'uri', 'decode_uri', 'flat_tuple', 'noop_body', 'respond',
10
10
  'is_full_page', 'Redirect', 'get_key', 'qp', 'def_hdrs', 'FastHTML', 'nested_name', 'serve', 'Client',
11
- 'RouteFuncs', 'APIRouter', 'cookie', 'reg_re_param', 'MiddlewareBase', 'FtResponse', 'unqid', 'setup_ws']
11
+ 'RouteFuncs', 'APIRouter', 'cookie', 'reg_re_param', 'MiddlewareBase', 'FtResponse', 'unqid']
12
12
 
13
13
  # %% ../nbs/api/00_core.ipynb
14
- import json,uuid,inspect,types,signal,asyncio,threading,inspect
14
+ import json,uuid,inspect,types,signal,asyncio,threading,inspect,random,contextlib
15
15
 
16
16
  from fastcore.utils import *
17
17
  from fastcore.xml import *
@@ -31,7 +31,7 @@ from warnings import warn
31
31
  from dateutil import parser as dtparse
32
32
  from httpx import ASGITransport, AsyncClient
33
33
  from anyio import from_thread
34
- from uuid import uuid4
34
+ from uuid import uuid4, UUID
35
35
  from base64 import b85encode,b64encode
36
36
 
37
37
  from .starlette import *
@@ -465,7 +465,7 @@ htmx_exts = {
465
465
  "multi-swap": "https://cdn.jsdelivr.net/npm/htmx-ext-multi-swap@2.0.0/multi-swap.js",
466
466
  "path-deps": "https://cdn.jsdelivr.net/npm/htmx-ext-path-deps@2.0.0/path-deps.js",
467
467
  "remove-me": "https://cdn.jsdelivr.net/npm/htmx-ext-remove-me@2.0.0/remove-me.js",
468
- "ws": "https://cdn.jsdelivr.net/npm/htmx-ext-ws@2.0.2/ws.js",
468
+ "ws": "https://cdn.jsdelivr.net/npm/htmx-ext-ws@2.0.3/ws.js",
469
469
  "chunked-transfer": "https://cdn.jsdelivr.net/npm/htmx-ext-transfer-encoding-chunked@0.4.0/transfer-encoding-chunked.js"
470
470
  }
471
471
 
@@ -568,12 +568,14 @@ class FastHTML(Starlette):
568
568
  excs = {k:_wrap_ex(v, k, hdrs, ftrs, htmlkw, bodykw, body_wrap=body_wrap) for k,v in exception_handlers.items()}
569
569
  super().__init__(debug, routes, middleware=middleware, exception_handlers=excs, on_startup=on_startup, on_shutdown=on_shutdown, lifespan=lifespan)
570
570
 
571
- def add_route(self, route):
572
- route.methods = [m.upper() for m in listify(route.methods)]
573
- self.router.routes = [r for r in self.router.routes if not
574
- (r.path==route.path and r.name == route.name and
575
- ((route.methods is None) or (set(r.methods) == set(route.methods))))]
576
- self.router.routes.append(route)
571
+ # %% ../nbs/api/00_core.ipynb
572
+ @patch
573
+ def add_route(self:FastHTML, route):
574
+ route.methods = [m.upper() for m in listify(route.methods)]
575
+ self.router.routes = [r for r in self.router.routes if not
576
+ (r.path==route.path and r.name == route.name and
577
+ ((route.methods is None) or (set(r.methods) == set(route.methods))))]
578
+ self.router.routes.append(route)
577
579
 
578
580
  # %% ../nbs/api/00_core.ipynb
579
581
  all_meths = 'get post put delete patch head trace options'.split()
@@ -656,6 +658,12 @@ def route(self:FastHTML, path:str=None, methods=None, name=None, include_in_sche
656
658
 
657
659
  for o in all_meths: setattr(FastHTML, o, partialmethod(FastHTML.route, methods=o))
658
660
 
661
+ # %% ../nbs/api/00_core.ipynb
662
+ @patch
663
+ def set_lifespan(self:FastHTML, value):
664
+ if inspect.isasyncgenfunction(value): value = contextlib.asynccontextmanager(value)
665
+ self.router.lifespan_context = value
666
+
659
667
  # %% ../nbs/api/00_core.ipynb
660
668
  def serve(
661
669
  appname=None, # Name of the module
@@ -810,8 +818,9 @@ class FtResponse:
810
818
  return self.cls(cts, status_code=self.status_code, headers=headers, media_type=self.media_type, background=tasks)
811
819
 
812
820
  # %% ../nbs/api/00_core.ipynb
813
- def unqid():
814
- res = b64encode(uuid4().bytes)
821
+ def unqid(seeded=False):
822
+ id4 = UUID(int=random.getrandbits(128), version=4) if seeded else uuid4()
823
+ res = b64encode(id4.bytes)
815
824
  return '_' + res.decode().rstrip('=').translate(str.maketrans('+/', '_-'))
816
825
 
817
826
  # %% ../nbs/api/00_core.ipynb
@@ -821,7 +830,8 @@ def _add_ids(s):
821
830
  for c in s.children: _add_ids(c)
822
831
 
823
832
  # %% ../nbs/api/00_core.ipynb
824
- def setup_ws(app, f=noop):
833
+ @patch
834
+ def setup_ws(app:FastHTML, f=noop):
825
835
  conns = {}
826
836
  async def on_connect(scope, send): conns[scope.client] = send
827
837
  async def on_disconnect(scope): conns.pop(scope.client)
@@ -1,6 +1,6 @@
1
1
  """The `FastHTML` subclass of `Starlette`, along with the `RouterX` and `RouteX` classes it automatically uses."""
2
2
  __all__ = ['empty', 'htmx_hdrs', 'fh_cfg', 'htmx_resps', 'htmx_exts', 'htmxsrc', 'fhjsscr', 'surrsrc', 'scopesrc', 'viewport', 'charset', 'cors_allow', 'iframe_scr', 'all_meths', 'devtools_loc', 'parsed_date', 'snake2hyphens', 'HtmxHeaders', 'HttpHeader', 'HtmxResponseHeaders', 'form2dict', 'parse_form', 'JSONResponse', 'flat_xt', 'Beforeware', 'EventStream', 'signal_shutdown', 'uri', 'decode_uri', 'flat_tuple', 'noop_body', 'respond', 'is_full_page', 'Redirect', 'get_key', 'qp', 'def_hdrs', 'FastHTML', 'nested_name', 'serve', 'Client', 'RouteFuncs', 'APIRouter', 'cookie', 'reg_re_param', 'MiddlewareBase', 'FtResponse', 'unqid', 'setup_ws']
3
- import json, uuid, inspect, types, signal, asyncio, threading, inspect
3
+ import json, uuid, inspect, types, signal, asyncio, threading, inspect, random
4
4
  from fastcore.utils import *
5
5
  from fastcore.xml import *
6
6
  from fastcore.meta import use_kwargs_dict
@@ -18,7 +18,7 @@ from warnings import warn
18
18
  from dateutil import parser as dtparse
19
19
  from httpx import ASGITransport, AsyncClient
20
20
  from anyio import from_thread
21
- from uuid import uuid4
21
+ from uuid import uuid4, UUID
22
22
  from base64 import b85encode, b64encode
23
23
  from .starlette import *
24
24
 
@@ -242,7 +242,7 @@ iframe_scr = Script(NotStr("\n function sendmsg() {\n window.parent.po
242
242
 
243
243
  class FastHTML(Starlette):
244
244
 
245
- def __init__(self, debug=False, routes=None, middleware=None, title: str='FastHTML page', exception_handlers=None, on_startup=None, on_shutdown=None, lifespan=None, hdrs=None, ftrs=None, exts=None, before=None, after=None, surreal=True, htmx=True, default_hdrs=True, sess_cls=SessionMiddleware, secret_key=None, session_cookie='session_', max_age=365 * 24 * 3600, sess_path='/', same_site='lax', sess_https_only=False, sess_domain=None, key_fname='.sesskey', body_wrap=noop_body, htmlkw=None, nb_hdrs=False, **bodykw):
245
+ def __init__(self, debug=False, routes=None, middleware=None, title: str='FastHTML page', exception_handlers=None, on_startup=None, on_shutdown=None, lifespan=None, hdrs=None, ftrs=None, exts=None, before=None, after=None, surreal=True, htmx=True, default_hdrs=True, sess_cls=SessionMiddleware, secret_key=None, session_cookie='session_', max_age=365 * 24 * 3600, sess_path='/', same_site='lax', sess_https_only=False, sess_domain=None, key_fname='.sesskey', body_wrap=noop_body, htmlkw=None, nb_hdrs=False, canonical=True, **bodykw):
246
246
  ...
247
247
 
248
248
  def add_route(self, route):
@@ -365,7 +365,7 @@ class FtResponse:
365
365
  def __response__(self, req):
366
366
  ...
367
367
 
368
- def unqid():
368
+ def unqid(seeded=False):
369
369
  ...
370
370
 
371
371
  def _add_ids(s):
@@ -36,6 +36,7 @@ def fast_app(
36
36
  middleware:Optional[tuple]=None, # Standard Starlette middleware
37
37
  live:bool=False, # Enable live reloading
38
38
  debug:bool=False, # Passed to Starlette, indicating if debug tracebacks should be returned on errors
39
+ title:str="FastHTML page", # Default page title
39
40
  routes:Optional[tuple]=None, # Passed to Starlette
40
41
  exception_handlers:Optional[dict]=None, # Passed to Starlette
41
42
  on_startup:Optional[callable]=None, # Passed to Starlette
@@ -67,7 +68,7 @@ def fast_app(
67
68
  h = (picolink,) if pico or (pico is None and default_hdrs) else ()
68
69
  if hdrs: h += tuple(hdrs)
69
70
 
70
- app = _app_factory(hdrs=h, ftrs=ftrs, before=before, middleware=middleware, live=live, debug=debug, routes=routes, exception_handlers=exception_handlers,
71
+ app = _app_factory(hdrs=h, ftrs=ftrs, before=before, middleware=middleware, live=live, debug=debug, title=title, routes=routes, exception_handlers=exception_handlers,
71
72
  on_startup=on_startup, on_shutdown=on_shutdown, lifespan=lifespan, default_hdrs=default_hdrs, secret_key=secret_key, canonical=canonical,
72
73
  session_cookie=session_cookie, max_age=max_age, sess_path=sess_path, same_site=same_site, sess_https_only=sess_https_only,
73
74
  sess_domain=sess_domain, key_fname=key_fname, exts=exts, surreal=surreal, htmx=htmx, htmlkw=htmlkw,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-fasthtml
3
- Version: 0.12.18
3
+ Version: 0.12.20
4
4
  Summary: The fastest way to create an HTML app
5
5
  Home-page: https://github.com/AnswerDotAI/fasthtml
6
6
  Author: Jeremy Howard and contributors
@@ -1,7 +1,7 @@
1
1
  [DEFAULT]
2
2
  repo = fasthtml
3
3
  lib_name = python-fasthtml
4
- version = 0.12.18
4
+ version = 0.12.20
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
@@ -1,2 +0,0 @@
1
- __version__ = "0.12.18"
2
- from .core import *