python-fasthtml 0.2.2__tar.gz → 0.2.4__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 (33) hide show
  1. {python-fasthtml-0.2.2/python_fasthtml.egg-info → python-fasthtml-0.2.4}/PKG-INFO +1 -1
  2. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/fasthtml/__init__.py +1 -1
  3. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/fasthtml/_modidx.py +1 -0
  4. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/fasthtml/components.py +8 -4
  5. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/fasthtml/core.py +8 -5
  6. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/fasthtml/fastapp.py +2 -2
  7. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4/python_fasthtml.egg-info}/PKG-INFO +1 -1
  8. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/settings.ini +1 -1
  9. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/CONTRIBUTING.md +0 -0
  10. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/LICENSE +0 -0
  11. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/MANIFEST.in +0 -0
  12. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/README.md +0 -0
  13. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/fasthtml/authmw.py +0 -0
  14. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/fasthtml/cli.py +0 -0
  15. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/fasthtml/common.py +0 -0
  16. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/fasthtml/components.pyi +0 -0
  17. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/fasthtml/ft.py +0 -0
  18. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/fasthtml/js.py +0 -0
  19. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/fasthtml/live_reload.py +0 -0
  20. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/fasthtml/oauth.py +0 -0
  21. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/fasthtml/starlette.py +0 -0
  22. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/fasthtml/svg.py +0 -0
  23. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/fasthtml/toaster.py +0 -0
  24. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/fasthtml/xtend.py +0 -0
  25. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/fasthtml/xtend.pyi +0 -0
  26. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/python_fasthtml.egg-info/SOURCES.txt +0 -0
  27. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/python_fasthtml.egg-info/dependency_links.txt +0 -0
  28. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/python_fasthtml.egg-info/entry_points.txt +0 -0
  29. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/python_fasthtml.egg-info/not-zip-safe +0 -0
  30. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/python_fasthtml.egg-info/requires.txt +0 -0
  31. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/python_fasthtml.egg-info/top_level.txt +0 -0
  32. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/setup.cfg +0 -0
  33. {python-fasthtml-0.2.2 → python-fasthtml-0.2.4}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-fasthtml
3
- Version: 0.2.2
3
+ Version: 0.2.4
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
@@ -1,4 +1,4 @@
1
- __version__ = "0.2.2"
1
+ __version__ = "0.2.4"
2
2
  from .core import *
3
3
  from .authmw import *
4
4
  from .components import *
@@ -53,6 +53,7 @@ d = { 'settings': { 'branch': 'main',
53
53
  'fasthtml.core._mk_list': ('api/core.html#_mk_list', 'fasthtml/core.py'),
54
54
  'fasthtml.core._resp': ('api/core.html#_resp', 'fasthtml/core.py'),
55
55
  'fasthtml.core._send_ws': ('api/core.html#_send_ws', 'fasthtml/core.py'),
56
+ 'fasthtml.core._sig': ('api/core.html#_sig', 'fasthtml/core.py'),
56
57
  'fasthtml.core._wrap_call': ('api/core.html#_wrap_call', 'fasthtml/core.py'),
57
58
  'fasthtml.core._wrap_ex': ('api/core.html#_wrap_ex', 'fasthtml/core.py'),
58
59
  'fasthtml.core._wrap_req': ('api/core.html#_wrap_req', 'fasthtml/core.py'),
@@ -82,7 +82,7 @@ def _fill_item(item, obj):
82
82
  else: attr.pop('checked', '')
83
83
  else: attr['value'] = val
84
84
  if tag=='textarea': cs=(val,)
85
- return FT(tag,cs,attr)
85
+ return FT(tag,cs,attr,void_=item.void_)
86
86
 
87
87
  # %% ../nbs/api/01_components.ipynb
88
88
  def fill_form(form:FT, obj)->FT:
@@ -120,7 +120,7 @@ def __getattr__(tag):
120
120
 
121
121
  # %% ../nbs/api/01_components.ipynb
122
122
  _re_h2x_attr_key = re.compile(r'^[A-Za-z_-][\w-]*$')
123
- def html2ft(html):
123
+ def html2ft(html, attr1st=False):
124
124
  """Convert HTML to an `ft` expression"""
125
125
  rev_map = {'class': 'cls', 'for': 'fr'}
126
126
 
@@ -136,13 +136,17 @@ def html2ft(html):
136
136
  for key, value in sorted(elm.attrs.items(), key=lambda x: x[0]=='class'):
137
137
  if isinstance(value,(tuple,list)): value = " ".join(value)
138
138
  key = rev_map.get(key, key)
139
- attrs.append(f'{key.replace("-", "_")}={value!r}' if _re_h2x_attr_key.match(key) else f'**{{{key!r}:{value!r}}}')
139
+ attrs.append(f'{key.replace("-", "_")}={value!r}'
140
+ if _re_h2x_attr_key.match(key) else f'**{{{key!r}:{value!r}}}')
140
141
  spc = " "*lvl*indent
141
142
  onlychild = not cts or (len(cts)==1 and isinstance(cts[0],str))
142
143
  j = ', ' if onlychild else f',\n{spc}'
143
144
  inner = j.join(filter(None, cs+attrs))
144
145
  if onlychild: return f'{tag_name}({inner})'
145
- return f'{tag_name}(\n{spc}{inner}\n{" "*(lvl-1)*indent})'
146
+ if not attr1st or not attrs: return f'{tag_name}(\n{spc}{inner}\n{" "*(lvl-1)*indent})'
147
+ inner_cs = j.join(filter(None, cs))
148
+ inner_attrs = ', '.join(filter(None, attrs))
149
+ return f'{tag_name}({inner_attrs})(\n{spc}{inner_cs}\n{" "*(lvl-1)*indent})'
146
150
 
147
151
  soup = BeautifulSoup(html.strip(), 'html.parser')
148
152
  for c in soup.find_all(string=risinstance(Comment)): c.extract()
@@ -18,7 +18,7 @@ from typing import Optional, get_type_hints, get_args, get_origin, Union, Mappin
18
18
  from datetime import datetime
19
19
  from dataclasses import dataclass,fields,is_dataclass,MISSING,asdict
20
20
  from collections import namedtuple
21
- from inspect import isfunction,ismethod,signature,Parameter,get_annotations
21
+ from inspect import isfunction,ismethod,Parameter,get_annotations
22
22
  from functools import wraps, partialmethod
23
23
  from http import cookies
24
24
  from copy import copy,deepcopy
@@ -27,6 +27,9 @@ from .starlette import *
27
27
 
28
28
  empty = Parameter.empty
29
29
 
30
+ # %% ../nbs/api/00_core.ipynb
31
+ def _sig(f): return signature_ex(f, True)
32
+
30
33
  # %% ../nbs/api/00_core.ipynb
31
34
  def is_typeddict(cls:type)->bool:
32
35
  "Check if `cls` is a `TypedDict`"
@@ -226,7 +229,7 @@ def _ws_endp(recv, conn=None, disconn=None, hdrs=None, before=None):
226
229
  cls = type('WS_Endp', (WebSocketEndpoint,), {"encoding":"text"})
227
230
 
228
231
  async def _generic_handler(handler, ws, data=None):
229
- wd = _wrap_ws(ws, loads(data) if data else {}, signature(handler).parameters)
232
+ wd = _wrap_ws(ws, loads(data) if data else {}, _sig(handler).parameters)
230
233
  resp = handler(*wd)
231
234
  if resp:
232
235
  if is_async_callable(handler): resp = await resp
@@ -287,7 +290,7 @@ async def _wrap_call(f, req, params):
287
290
  class RouteX(Route):
288
291
  def __init__(self, path:str, endpoint, *, methods=None, name=None, include_in_schema=True, middleware=None,
289
292
  hdrs=None, ftrs=None, before=None, after=None, htmlkw=None, **bodykw):
290
- self.sig = signature(endpoint)
293
+ self.sig = _sig(endpoint)
291
294
  self.f,self.hdrs,self.ftrs,self.before,self.after,self.htmlkw,self.bodykw = endpoint,hdrs,ftrs,before,after,htmlkw,bodykw
292
295
  super().__init__(path, self._endp, methods=methods, name=name, include_in_schema=include_in_schema, middleware=middleware)
293
296
 
@@ -301,10 +304,10 @@ class RouteX(Route):
301
304
  if isinstance(b, Beforeware): bf,skip = b.f,b.skip
302
305
  else: bf,skip = b,[]
303
306
  if not any(re.match(r, req.url.path) for r in skip):
304
- resp = await _wrap_call(bf, req, signature(bf).parameters)
307
+ resp = await _wrap_call(bf, req, _sig(bf).parameters)
305
308
  if not resp: resp = await _wrap_call(self.f, req, self.sig.parameters)
306
309
  for a in self.after:
307
- _,*wreq = await _wrap_req(req, signature(a).parameters)
310
+ _,*wreq = await _wrap_req(req, _sig(a).parameters)
308
311
  nr = a(resp, *wreq)
309
312
  if nr: resp = nr
310
313
  return _resp(req, resp, self.sig.return_annotation)
@@ -60,12 +60,12 @@ def fast_app(
60
60
  **kwargs)->Any:
61
61
  h = (picolink,) if pico or (pico is None and default_hdrs) else ()
62
62
  if hdrs: h += tuple(hdrs)
63
-
63
+
64
64
  app = app_factory(hdrs=h, ftrs=ftrs, before=before, middleware=middleware, live=live, debug=debug, routes=routes, exception_handlers=exception_handlers,
65
65
  on_startup=on_startup, on_shutdown=on_shutdown, lifespan=lifespan, default_hdrs=default_hdrs, secret_key=secret_key,
66
66
  session_cookie=session_cookie, max_age=max_age, sess_path=sess_path, same_site=same_site, sess_https_only=sess_https_only,
67
67
  sess_domain=sess_domain, key_fname=key_fname, ws_hdr=ws_hdr, htmlkw=htmlkw, reload_attempts=reload_attempts, reload_interval=reload_interval, **(bodykw or {}))
68
-
68
+
69
69
  @app.route("/{fname:path}.{ext:static}")
70
70
  async def get(fname:str, ext:str): return FileResponse(f'{fname}.{ext}')
71
71
  if not db_file: return app,app.route
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-fasthtml
3
- Version: 0.2.2
3
+ Version: 0.2.4
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
@@ -1,7 +1,7 @@
1
1
  [DEFAULT]
2
2
  repo = fasthtml
3
3
  lib_name = fasthtml
4
- version = 0.2.2
4
+ version = 0.2.4
5
5
  min_python = 3.10
6
6
  license = apache2
7
7
  requirements = fastcore>=1.6.3 python-dateutil starlette>0.33 oauthlib itsdangerous uvicorn[standard]>=0.30 httpx fastlite>=0.0.6 python-multipart beautifulsoup4
File without changes