python-fasthtml 0.5.3__tar.gz → 0.6.0__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 (39) hide show
  1. {python-fasthtml-0.5.3/python_fasthtml.egg-info → python-fasthtml-0.6.0}/PKG-INFO +2 -2
  2. python-fasthtml-0.6.0/fasthtml/__init__.py +2 -0
  3. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/fasthtml/_modidx.py +3 -1
  4. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/fasthtml/components.py +4 -1
  5. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/fasthtml/components.pyi +1 -1
  6. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/fasthtml/core.py +29 -13
  7. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/fasthtml/core.pyi +40 -4
  8. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/fasthtml/xtend.pyi +7 -6
  9. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0/python_fasthtml.egg-info}/PKG-INFO +2 -2
  10. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/python_fasthtml.egg-info/requires.txt +1 -1
  11. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/settings.ini +2 -2
  12. python-fasthtml-0.5.3/fasthtml/__init__.py +0 -2
  13. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/CONTRIBUTING.md +0 -0
  14. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/LICENSE +0 -0
  15. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/MANIFEST.in +0 -0
  16. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/README.md +0 -0
  17. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/fasthtml/authmw.py +0 -0
  18. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/fasthtml/basics.py +0 -0
  19. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/fasthtml/cli.py +0 -0
  20. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/fasthtml/common.py +0 -0
  21. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/fasthtml/fastapp.py +0 -0
  22. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/fasthtml/ft.py +0 -0
  23. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/fasthtml/js.py +0 -0
  24. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/fasthtml/katex.js +0 -0
  25. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/fasthtml/live_reload.py +0 -0
  26. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/fasthtml/oauth.py +0 -0
  27. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/fasthtml/pico.py +0 -0
  28. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/fasthtml/starlette.py +0 -0
  29. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/fasthtml/svg.py +0 -0
  30. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/fasthtml/toaster.py +0 -0
  31. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/fasthtml/xtend.py +0 -0
  32. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/python_fasthtml.egg-info/SOURCES.txt +0 -0
  33. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/python_fasthtml.egg-info/dependency_links.txt +0 -0
  34. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/python_fasthtml.egg-info/entry_points.txt +0 -0
  35. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/python_fasthtml.egg-info/not-zip-safe +0 -0
  36. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/python_fasthtml.egg-info/top_level.txt +0 -0
  37. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/setup.cfg +0 -0
  38. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/setup.py +0 -0
  39. {python-fasthtml-0.5.3 → python-fasthtml-0.6.0}/tests/test_toaster.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-fasthtml
3
- Version: 0.5.3
3
+ Version: 0.6.0
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
@@ -15,7 +15,7 @@ Classifier: License :: OSI Approved :: Apache Software License
15
15
  Requires-Python: >=3.10
16
16
  Description-Content-Type: text/markdown
17
17
  License-File: LICENSE
18
- Requires-Dist: fastcore>=1.7.5
18
+ Requires-Dist: fastcore>=1.7.8
19
19
  Requires-Dist: python-dateutil
20
20
  Requires-Dist: starlette>0.33
21
21
  Requires-Dist: oauthlib
@@ -0,0 +1,2 @@
1
+ __version__ = "0.6.0"
2
+ from .core import *
@@ -89,16 +89,18 @@ d = { 'settings': { 'branch': 'main',
89
89
  'fasthtml.core._xt_cts': ('api/core.html#_xt_cts', 'fasthtml/core.py'),
90
90
  'fasthtml.core._xt_resp': ('api/core.html#_xt_resp', 'fasthtml/core.py'),
91
91
  'fasthtml.core.cookie': ('api/core.html#cookie', 'fasthtml/core.py'),
92
- 'fasthtml.core.date': ('api/core.html#date', 'fasthtml/core.py'),
93
92
  'fasthtml.core.decode_uri': ('api/core.html#decode_uri', 'fasthtml/core.py'),
94
93
  'fasthtml.core.flat_tuple': ('api/core.html#flat_tuple', 'fasthtml/core.py'),
95
94
  'fasthtml.core.flat_xt': ('api/core.html#flat_xt', 'fasthtml/core.py'),
96
95
  'fasthtml.core.form2dict': ('api/core.html#form2dict', 'fasthtml/core.py'),
97
96
  'fasthtml.core.get_key': ('api/core.html#get_key', 'fasthtml/core.py'),
97
+ 'fasthtml.core.parse_form': ('api/core.html#parse_form', 'fasthtml/core.py'),
98
+ 'fasthtml.core.parsed_date': ('api/core.html#parsed_date', 'fasthtml/core.py'),
98
99
  'fasthtml.core.reg_re_param': ('api/core.html#reg_re_param', 'fasthtml/core.py'),
99
100
  'fasthtml.core.serve': ('api/core.html#serve', 'fasthtml/core.py'),
100
101
  'fasthtml.core.signal_shutdown': ('api/core.html#signal_shutdown', 'fasthtml/core.py'),
101
102
  'fasthtml.core.snake2hyphens': ('api/core.html#snake2hyphens', 'fasthtml/core.py'),
103
+ 'fasthtml.core.str2date': ('api/core.html#str2date', 'fasthtml/core.py'),
102
104
  'fasthtml.core.str2int': ('api/core.html#str2int', 'fasthtml/core.py'),
103
105
  'fasthtml.core.uri': ('api/core.html#uri', 'fasthtml/core.py')},
104
106
  'fasthtml.fastapp': { 'fasthtml.fastapp.ContainerX': ('api/fastapp.html#containerx', 'fasthtml/fastapp.py'),
@@ -97,9 +97,12 @@ def _fill_item(item, obj):
97
97
  val = None if name is None else obj.get(name, None)
98
98
  if val is not None and not 'skip' in attr:
99
99
  if tag=='input':
100
- if attr.get('type', '') in ('checkbox','radio'):
100
+ if attr.get('type', '') == 'checkbox':
101
101
  if val: attr['checked'] = '1'
102
102
  else: attr.pop('checked', '')
103
+ elif attr.get('type', '') == 'radio':
104
+ if val and val == attr['value']: attr['checked'] = '1'
105
+ else: attr.pop('checked', '')
103
106
  else: attr['value'] = val
104
107
  if tag=='textarea': cs=(val,)
105
108
  if tag == 'select':
@@ -26,7 +26,7 @@ def attrmap_x(o):
26
26
  fh_cfg['attrmap'] = attrmap_x
27
27
  fh_cfg['valmap'] = valmap
28
28
 
29
- def ft_html(tag: str, *c, id=None, cls=None, title=None, style=None, attrmap=None, valmap=None, **kwargs):
29
+ def ft_html(tag: str, *c, id=None, cls=None, title=None, style=None, attrmap=None, valmap=None, ft_cls=FT, **kwargs):
30
30
  ...
31
31
 
32
32
  @use_kwargs(hx_attrs, keep=True)
@@ -4,10 +4,10 @@
4
4
 
5
5
  # %% auto 0
6
6
  __all__ = ['empty', 'htmx_hdrs', 'fh_cfg', 'htmx_resps', 'htmxsrc', 'htmxwssrc', 'fhjsscr', 'htmxctsrc', 'surrsrc', 'scopesrc',
7
- 'viewport', 'charset', 'all_meths', 'date', 'snake2hyphens', 'HtmxHeaders', 'str2int', 'HttpHeader',
8
- 'HtmxResponseHeaders', 'form2dict', 'flat_xt', 'Beforeware', 'EventStream', 'signal_shutdown', 'WS_RouteX',
9
- 'uri', 'decode_uri', 'flat_tuple', 'Redirect', 'RouteX', 'RouterX', 'get_key', 'FastHTML', 'serve', 'Client',
10
- 'cookie', 'reg_re_param', 'MiddlewareBase', 'FtResponse']
7
+ 'viewport', 'charset', 'all_meths', 'parsed_date', 'snake2hyphens', 'HtmxHeaders', 'str2int', 'str2date',
8
+ 'HttpHeader', 'HtmxResponseHeaders', 'form2dict', 'parse_form', 'flat_xt', 'Beforeware', 'EventStream',
9
+ 'signal_shutdown', 'WS_RouteX', 'uri', 'decode_uri', 'flat_tuple', 'Redirect', 'RouteX', 'RouterX',
10
+ 'get_key', 'FastHTML', 'serve', 'Client', 'cookie', 'reg_re_param', 'MiddlewareBase', 'FtResponse']
11
11
 
12
12
  # %% ../nbs/api/00_core.ipynb
13
13
  import json,uuid,inspect,types,uvicorn,signal,asyncio,threading
@@ -18,7 +18,7 @@ from fastcore.meta import use_kwargs_dict
18
18
 
19
19
  from types import UnionType, SimpleNamespace as ns, GenericAlias
20
20
  from typing import Optional, get_type_hints, get_args, get_origin, Union, Mapping, TypedDict, List, Any
21
- from datetime import datetime
21
+ from datetime import datetime,date
22
22
  from dataclasses import dataclass,fields
23
23
  from collections import namedtuple
24
24
  from inspect import isfunction,ismethod,Parameter,get_annotations
@@ -39,7 +39,7 @@ empty = Parameter.empty
39
39
  def _sig(f): return signature_ex(f, True)
40
40
 
41
41
  # %% ../nbs/api/00_core.ipynb
42
- def date(s:str):
42
+ def parsed_date(s:str):
43
43
  "Convert `s` to a datetime"
44
44
  return dtparse.parse(s)
45
45
 
@@ -84,13 +84,18 @@ def _mk_list(t, v): return [t(o) for o in v]
84
84
  # %% ../nbs/api/00_core.ipynb
85
85
  fh_cfg = AttrDict(indent=True)
86
86
 
87
+ # %% ../nbs/api/00_core.ipynb
88
+ def str2date(s:str)->date:
89
+ "`date.fromisoformat` with empty string handling"
90
+ return date.fromisoformat(s) if s else None
91
+
87
92
  # %% ../nbs/api/00_core.ipynb
88
93
  def _fix_anno(t):
89
94
  "Create appropriate callable type for casting a `str` to type `t` (or first type in `t` if union)"
90
95
  origin = get_origin(t)
91
96
  if origin is Union or origin is UnionType or origin in (list,List):
92
97
  t = first(o for o in get_args(t) if o!=type(None))
93
- d = {bool: str2bool, int: str2int}
98
+ d = {bool: str2bool, int: str2int, date: str2date}
94
99
  res = d.get(t, t)
95
100
  if origin in (list,List): return partial(_mk_list, res)
96
101
  return lambda o: res(o[-1]) if isinstance(o,(list,tuple)) else res(o)
@@ -143,13 +148,25 @@ def form2dict(form: FormData) -> dict:
143
148
  "Convert starlette form data to a dict"
144
149
  return {k: _formitem(form, k) for k in form}
145
150
 
151
+ # %% ../nbs/api/00_core.ipynb
152
+ async def parse_form(req: Request) -> FormData:
153
+ "Starlette errors on empty multipart forms, so this checks for that situation"
154
+ ctype = req.headers.get("Content-Type", "")
155
+ if not ctype.startswith("multipart/form-data"): return await req.form()
156
+ try: boundary = ctype.split("boundary=")[1].strip()
157
+ except IndexError: raise HTTPException(400, "Invalid form-data: no boundary")
158
+ min_len = len(boundary) + 6
159
+ clen = int(req.headers.get("Content-Length", "0"))
160
+ if clen <= min_len: return FormData()
161
+ return await req.form()
162
+
146
163
  # %% ../nbs/api/00_core.ipynb
147
164
  async def _from_body(req, p):
148
165
  anno = p.annotation
149
166
  # Get the fields and types of type `anno`, if available
150
167
  d = _annotations(anno)
151
168
  if req.headers.get('content-type', None)=='application/json': data = await req.json()
152
- else: data = form2dict(await req.form())
169
+ else: data = form2dict(await parse_form(req))
153
170
  cargs = {k: _form_arg(k, v, d) for k, v in data.items() if not d or k in d}
154
171
  return anno(**cargs)
155
172
 
@@ -179,10 +196,9 @@ async def _find_p(req, arg:str, p:Parameter):
179
196
  res = req.path_params.get(arg, None)
180
197
  if res in (empty,None): res = req.cookies.get(arg, None)
181
198
  if res in (empty,None): res = req.headers.get(snake2hyphens(arg), None)
182
- if res in (empty,None): res = req.query_params.get(arg, None)
183
- if res in (empty,None):
184
- frm = await req.form()
185
- res = _formitem(frm, arg)
199
+ if res in (empty,None): res = req.query_params.getlist(arg)
200
+ if res==[]: res = None
201
+ if res in (empty,None): res = _formitem(await parse_form(req), arg)
186
202
  # Raise 400 error if the param does not include a default
187
203
  if (res in (empty,None)) and p.default is empty: raise HTTPException(400, f"Missing required field: {arg}")
188
204
  # If we have a default, return that if we have no value
@@ -417,7 +433,7 @@ class RouteX(Route):
417
433
  resp = None
418
434
  req.injects = []
419
435
  req.hdrs,req.ftrs,req.htmlkw,req.bodykw = map(deepcopy, (self._app.hdrs,self._app.ftrs,self._app.htmlkw,self._app.bodykw))
420
- req.hdrs,req.ftrs = list(req.hdrs),list(req.ftrs)
436
+ req.hdrs,req.ftrs = listify(req.hdrs),listify(req.ftrs)
421
437
  for b in self._app.before:
422
438
  if not resp:
423
439
  if isinstance(b, Beforeware): bf,skip = b.f,b.skip
@@ -1,12 +1,12 @@
1
1
  """The `FastHTML` subclass of `Starlette`, along with the `RouterX` and `RouteX` classes it automatically uses."""
2
- __all__ = ['empty', 'htmx_hdrs', 'fh_cfg', 'htmx_resps', 'htmxsrc', 'htmxwssrc', 'fhjsscr', 'htmxctsrc', 'surrsrc', 'scopesrc', 'viewport', 'charset', 'all_meths', 'date', 'snake2hyphens', 'HtmxHeaders', 'str2int', 'HttpHeader', 'HtmxResponseHeaders', 'form2dict', 'flat_xt', 'Beforeware', 'EventStream', 'signal_shutdown', 'WS_RouteX', 'uri', 'decode_uri', 'flat_tuple', 'Redirect', 'RouteX', 'RouterX', 'get_key', 'FastHTML', 'serve', 'cookie', 'reg_re_param', 'MiddlewareBase']
3
- import json, uuid, inspect, types, uvicorn, signal, asyncio
2
+ __all__ = ['empty', 'htmx_hdrs', 'fh_cfg', 'htmx_resps', 'htmxsrc', 'htmxwssrc', 'fhjsscr', 'htmxctsrc', 'surrsrc', 'scopesrc', 'viewport', 'charset', 'all_meths', 'parsed_date', 'snake2hyphens', 'HtmxHeaders', 'str2int', 'str2date', 'HttpHeader', 'HtmxResponseHeaders', 'form2dict', 'parse_form', 'flat_xt', 'Beforeware', 'EventStream', 'signal_shutdown', 'WS_RouteX', 'uri', 'decode_uri', 'flat_tuple', 'Redirect', 'RouteX', 'RouterX', 'get_key', 'FastHTML', 'serve', 'Client', 'cookie', 'reg_re_param', 'MiddlewareBase', 'FtResponse']
3
+ import json, uuid, inspect, types, uvicorn, signal, asyncio, threading
4
4
  from fastcore.utils import *
5
5
  from fastcore.xml import *
6
6
  from fastcore.meta import use_kwargs_dict
7
7
  from types import UnionType, SimpleNamespace as ns, GenericAlias
8
8
  from typing import Optional, get_type_hints, get_args, get_origin, Union, Mapping, TypedDict, List, Any
9
- from datetime import datetime
9
+ from datetime import datetime, date
10
10
  from dataclasses import dataclass, fields
11
11
  from collections import namedtuple
12
12
  from inspect import isfunction, ismethod, Parameter, get_annotations
@@ -16,13 +16,15 @@ from urllib.parse import urlencode, parse_qs, quote, unquote
16
16
  from copy import copy, deepcopy
17
17
  from warnings import warn
18
18
  from dateutil import parser as dtparse
19
+ from httpx import ASGITransport, AsyncClient
20
+ from anyio import from_thread
19
21
  from .starlette import *
20
22
  empty = Parameter.empty
21
23
 
22
24
  def _sig(f):
23
25
  ...
24
26
 
25
- def date(s: str):
27
+ def parsed_date(s: str):
26
28
  """Convert `s` to a datetime"""
27
29
  ...
28
30
 
@@ -56,6 +58,10 @@ def _mk_list(t, v):
56
58
  ...
57
59
  fh_cfg = AttrDict(indent=True)
58
60
 
61
+ def str2date(s: str) -> date:
62
+ """`date.fromisoformat` with empty string handling"""
63
+ ...
64
+
59
65
  def _fix_anno(t):
60
66
  """Create appropriate callable type for casting a `str` to type `t` (or first type in `t` if union)"""
61
67
  ...
@@ -93,6 +99,10 @@ def form2dict(form: FormData) -> dict:
93
99
  """Convert starlette form data to a dict"""
94
100
  ...
95
101
 
102
+ async def parse_form(req: Request) -> FormData:
103
+ """Starlette errors on empty multipart forms, so this checks for that situation"""
104
+ ...
105
+
96
106
  async def _from_body(req, p):
97
107
  ...
98
108
 
@@ -173,9 +183,15 @@ def flat_tuple(o):
173
183
  """Flatten lists"""
174
184
  ...
175
185
 
186
+ def _xt_cts(req, resp):
187
+ ...
188
+
176
189
  def _xt_resp(req, resp):
177
190
  ...
178
191
 
192
+ def _is_ft_resp(resp):
193
+ ...
194
+
179
195
  def _resp(req, resp, cls=empty):
180
196
  ...
181
197
 
@@ -258,6 +274,17 @@ def serve(appname=None, app='app', host='0.0.0.0', port=None, reload=True, reloa
258
274
  """Run the app in an async server, with live reload set as the default."""
259
275
  ...
260
276
 
277
+ class Client:
278
+ """A simple httpx ASGI client that doesn't require `async`"""
279
+
280
+ def __init__(self, app, url='http://testserver'):
281
+ ...
282
+
283
+ def _sync(self, method, url, **kwargs):
284
+ ...
285
+ for o in ('get', 'post', 'delete', 'put', 'patch', 'options'):
286
+ setattr(Client, o, partialmethod(Client._sync, o))
287
+
261
288
  def cookie(key: str, value='', max_age=None, expires=None, path='/', domain=None, secure=False, httponly=False, samesite='lax'):
262
289
  """Create a 'set-cookie' `HttpHeader`"""
263
290
  ...
@@ -270,4 +297,13 @@ reg_re_param('static', 'ico|gif|jpg|jpeg|webm|css|js|woff|png|svg|mp4|webp|ttf|o
270
297
  class MiddlewareBase:
271
298
 
272
299
  async def __call__(self, scope, receive, send) -> None:
300
+ ...
301
+
302
+ class FtResponse:
303
+ """Wrap an FT response with any Starlette `Response`"""
304
+
305
+ def __init__(self, content, status_code: int=200, headers=None, cls=HTMLResponse, media_type: str | None=None, background=None):
306
+ ...
307
+
308
+ def __response__(self, req):
273
309
  ...
@@ -1,5 +1,5 @@
1
1
  """Simple extensions to standard HTML components, such as adding sensible defaults"""
2
- __all__ = ['A', 'Form', 'AX', 'Hidden', 'CheckboxX', 'Script', 'Style', 'double_braces', 'undouble_braces', 'loose_format', 'ScriptX', 'replace_css_vars', 'StyleX', 'On', 'Prev', 'Now', 'AnyNow', 'run_js', 'HtmxOn', 'Titled', 'Socials', 'Favicon', 'jsd', 'clear']
2
+ __all__ = ['sid_scr', 'A', 'Form', 'AX', 'Hidden', 'CheckboxX', 'Script', 'Style', 'double_braces', 'undouble_braces', 'loose_format', 'ScriptX', 'replace_css_vars', 'StyleX', 'On', 'Prev', 'Now', 'AnyNow', 'run_js', 'HtmxOn', 'Titled', 'Socials', 'Favicon', 'jsd', 'clear']
3
3
  from dataclasses import dataclass, asdict
4
4
  from typing import Any
5
5
  from fastcore.utils import *
@@ -32,11 +32,11 @@ def CheckboxX(checked: bool=False, label=None, value='1', id=None, name=None, *,
32
32
  """A Checkbox optionally inside a Label, preceded by a `Hidden` with matching name"""
33
33
  ...
34
34
 
35
- def Script(code: str='', *, id=None, cls=None, title=None, style=None, attrmap=None, valmap=None, **kwargs) -> FT:
35
+ def Script(code: str='', *, id=None, cls=None, title=None, style=None, attrmap=None, valmap=None, ft_cls=fastcore.xml.FT, **kwargs) -> FT:
36
36
  """A Script tag that doesn't escape its code"""
37
37
  ...
38
38
 
39
- def Style(*c, id=None, cls=None, title=None, style=None, attrmap=None, valmap=None, **kwargs) -> FT:
39
+ def Style(*c, id=None, cls=None, title=None, style=None, attrmap=None, valmap=None, ft_cls=fastcore.xml.FT, **kwargs) -> FT:
40
40
  """A Style tag that doesn't escape its code"""
41
41
  ...
42
42
 
@@ -65,11 +65,11 @@ def StyleX(fname, **kw):
65
65
  ...
66
66
 
67
67
  def On(code: str, event: str='click', sel: str='', me=True):
68
- """An async surreal.js script block event handler for `event` on selector `sel`"""
68
+ """An async surreal.js script block event handler for `event` on selector `sel`, making available parent `p`, event `ev`, and target `e`"""
69
69
  ...
70
70
 
71
71
  def Prev(code: str, event: str='click'):
72
- """An async surreal.js script block event handler for `event` on previous sibling"""
72
+ """An async surreal.js script block event handler for `event` on previous sibling, with same vars as `On`"""
73
73
  ...
74
74
 
75
75
  def Now(code: str, sel: str=''):
@@ -104,4 +104,5 @@ def jsd(org, repo, root, path, prov='gh', typ='script', ver=None, esm=False, **k
104
104
  ...
105
105
 
106
106
  def clear(id):
107
- ...
107
+ ...
108
+ sid_scr = Script('\nfunction uuid() {\n return [...crypto.getRandomValues(new Uint8Array(10))].map(b=>b.toString(36)).join(\'\');\n}\n\nsessionStorage.setItem("sid", sessionStorage.getItem("sid") || uuid());\n\nhtmx.on("htmx:configRequest", (e) => {\n const sid = sessionStorage.getItem("sid");\n if (sid) {\n const url = new URL(e.detail.path, window.location.origin);\n url.searchParams.set(\'sid\', sid);\n e.detail.path = url.pathname + url.search;\n }\n});\n')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-fasthtml
3
- Version: 0.5.3
3
+ Version: 0.6.0
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
@@ -15,7 +15,7 @@ Classifier: License :: OSI Approved :: Apache Software License
15
15
  Requires-Python: >=3.10
16
16
  Description-Content-Type: text/markdown
17
17
  License-File: LICENSE
18
- Requires-Dist: fastcore>=1.7.5
18
+ Requires-Dist: fastcore>=1.7.8
19
19
  Requires-Dist: python-dateutil
20
20
  Requires-Dist: starlette>0.33
21
21
  Requires-Dist: oauthlib
@@ -1,4 +1,4 @@
1
- fastcore>=1.7.5
1
+ fastcore>=1.7.8
2
2
  python-dateutil
3
3
  starlette>0.33
4
4
  oauthlib
@@ -1,10 +1,10 @@
1
1
  [DEFAULT]
2
2
  repo = fasthtml
3
3
  lib_name = fasthtml
4
- version = 0.5.3
4
+ version = 0.6.0
5
5
  min_python = 3.10
6
6
  license = apache2
7
- requirements = fastcore>=1.7.5 python-dateutil starlette>0.33 oauthlib itsdangerous uvicorn[standard]>=0.30 httpx fastlite>=0.0.9 python-multipart beautifulsoup4
7
+ requirements = fastcore>=1.7.8 python-dateutil starlette>0.33 oauthlib itsdangerous uvicorn[standard]>=0.30 httpx fastlite>=0.0.9 python-multipart beautifulsoup4
8
8
  dev_requirements = ipython lxml pysymbol_llm
9
9
  black_formatting = False
10
10
  conda_user = fastai
@@ -1,2 +0,0 @@
1
- __version__ = "0.5.3"
2
- from .core import *
File without changes