python-fasthtml 0.12.41__tar.gz → 0.12.43__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.12.41/python_fasthtml.egg-info → python_fasthtml-0.12.43}/PKG-INFO +1 -1
  2. python_fasthtml-0.12.43/fasthtml/__init__.py +2 -0
  3. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/fasthtml/_modidx.py +4 -0
  4. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/fasthtml/core.py +22 -13
  5. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/fasthtml/oauth.py +10 -4
  6. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43/python_fasthtml.egg-info}/PKG-INFO +1 -1
  7. python_fasthtml-0.12.41/fasthtml/__init__.py +0 -2
  8. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/CONTRIBUTING.md +0 -0
  9. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/LICENSE +0 -0
  10. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/MANIFEST.in +0 -0
  11. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/README.md +0 -0
  12. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/fasthtml/authmw.py +0 -0
  13. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/fasthtml/basics.py +0 -0
  14. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/fasthtml/cli.py +0 -0
  15. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/fasthtml/common.py +0 -0
  16. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/fasthtml/components.py +0 -0
  17. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/fasthtml/components.pyi +0 -0
  18. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/fasthtml/core.pyi +0 -0
  19. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/fasthtml/fastapp.py +0 -0
  20. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/fasthtml/ft.py +0 -0
  21. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/fasthtml/js.py +0 -0
  22. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/fasthtml/jupyter.py +0 -0
  23. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/fasthtml/katex.js +0 -0
  24. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/fasthtml/live_reload.py +0 -0
  25. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/fasthtml/pico.py +0 -0
  26. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/fasthtml/starlette.py +0 -0
  27. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/fasthtml/stripe_otp.py +0 -0
  28. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/fasthtml/svg.py +0 -0
  29. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/fasthtml/toaster.py +0 -0
  30. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/fasthtml/xtend.py +0 -0
  31. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/fasthtml/xtend.pyi +0 -0
  32. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/pyproject.toml +0 -0
  33. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/python_fasthtml.egg-info/SOURCES.txt +0 -0
  34. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/python_fasthtml.egg-info/dependency_links.txt +0 -0
  35. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/python_fasthtml.egg-info/entry_points.txt +0 -0
  36. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/python_fasthtml.egg-info/requires.txt +0 -0
  37. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/python_fasthtml.egg-info/top_level.txt +0 -0
  38. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/setup.cfg +0 -0
  39. {python_fasthtml-0.12.41 → python_fasthtml-0.12.43}/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.41
3
+ Version: 0.12.43
4
4
  Summary: The fastest way to create an HTML app
5
5
  Author-email: Jeremy Howard and contributors <github@jhoward.fastmail.fm>
6
6
  License: Apache-2.0
@@ -0,0 +1,2 @@
1
+ __version__ = "0.12.43"
2
+ from .core import *
@@ -33,6 +33,10 @@ d = { 'settings': { 'branch': 'main',
33
33
  'fasthtml.core.APIRouter._wrap_func': ('api/core.html#apirouter._wrap_func', 'fasthtml/core.py'),
34
34
  'fasthtml.core.APIRouter.to_app': ('api/core.html#apirouter.to_app', 'fasthtml/core.py'),
35
35
  'fasthtml.core.APIRouter.ws': ('api/core.html#apirouter.ws', 'fasthtml/core.py'),
36
+ 'fasthtml.core.ApiReturn': ('api/core.html#apireturn', 'fasthtml/core.py'),
37
+ 'fasthtml.core.ApiReturn.__call__': ('api/core.html#apireturn.__call__', 'fasthtml/core.py'),
38
+ 'fasthtml.core.ApiReturn.__from_request__': ('api/core.html#apireturn.__from_request__', 'fasthtml/core.py'),
39
+ 'fasthtml.core.ApiReturn.__init__': ('api/core.html#apireturn.__init__', 'fasthtml/core.py'),
36
40
  'fasthtml.core.Beforeware': ('api/core.html#beforeware', 'fasthtml/core.py'),
37
41
  'fasthtml.core.Beforeware.__init__': ('api/core.html#beforeware.__init__', 'fasthtml/core.py'),
38
42
  'fasthtml.core.Client': ('api/core.html#client', 'fasthtml/core.py'),
@@ -5,18 +5,19 @@
5
5
  # %% auto #0
6
6
  __all__ = ['empty', 'htmx_hdrs', 'fh_cfg', 'htmx_resps', 'htmx_exts', 'htmxsrc', 'fhjsscr', 'surrsrc', 'scopesrc', 'viewport',
7
7
  'charset', 'cors_allow', 'iframe_scr', 'all_meths', 'devtools_loc', 'parsed_date', 'snake2hyphens',
8
- 'HtmxHeaders', 'HttpHeader', 'HtmxResponseHeaders', 'form2dict', 'parse_form', 'JSONResponse', 'flat_xt',
9
- 'Beforeware', 'EventStream', 'signal_shutdown', 'uri', 'decode_uri', 'flat_tuple', 'noop_body', 'respond',
10
- 'is_full_page', 'Redirect', 'get_key', 'qp', 'def_hdrs', 'FastHTML', 'nested_name', 'serve', 'Client',
11
- 'RouteFuncs', 'APIRouter', 'cookie', 'reg_re_param', 'StaticNoCache', 'MiddlewareBase', 'FtResponse',
12
- 'unqid']
8
+ 'HtmxHeaders', 'HttpHeader', 'HtmxResponseHeaders', 'form2dict', 'parse_form', 'ApiReturn', 'JSONResponse',
9
+ 'flat_xt', 'Beforeware', 'EventStream', 'signal_shutdown', 'uri', 'decode_uri', 'flat_tuple', 'noop_body',
10
+ 'respond', 'is_full_page', 'Redirect', 'get_key', 'qp', 'def_hdrs', 'FastHTML', 'nested_name', 'serve',
11
+ 'Client', 'RouteFuncs', 'APIRouter', 'cookie', 'reg_re_param', 'StaticNoCache', 'MiddlewareBase',
12
+ 'FtResponse', 'unqid']
13
13
 
14
14
  # %% ../nbs/api/00_core.ipynb #23503b9e
15
- import json,uuid,inspect,types,signal,asyncio,threading,inspect,random,contextlib,httpx,itsdangerous
15
+ import json,uuid,inspect,types,signal,asyncio,threading,inspect,random,contextlib,httpx,itsdangerous,uvicorn
16
16
 
17
17
  from fastcore.utils import *
18
18
  from fastcore.xml import *
19
- from fastcore.meta import use_kwargs_dict
19
+ from fastcore.meta import use_kwargs_dict,delegates
20
+ from fastcore.style import S
20
21
 
21
22
  from types import UnionType, SimpleNamespace as ns, GenericAlias
22
23
  from typing import Optional, get_type_hints, get_args, get_origin, Union, Mapping, TypedDict, List, Any
@@ -165,6 +166,13 @@ async def _from_body(req, p):
165
166
  cargs = {k: _form_arg(k, v, d) for k, v in data.items() if not d or k in d}
166
167
  return anno(**cargs)
167
168
 
169
+ # %% ../nbs/api/00_core.ipynb #88b6da3f
170
+ class ApiReturn:
171
+ @classmethod
172
+ async def __from_request__(cls, data, req): return cls(req.headers.get('accept')=='application/json')
173
+ def __init__(self, isapi=False): self.isapi = isapi
174
+ def __call__(self, norm, **kw): return kw if self.isapi else norm
175
+
168
176
  # %% ../nbs/api/00_core.ipynb #7cc39ba9
169
177
  class JSONResponse(JSONResponseOrig):
170
178
  "Same as starlette's version, but auto-stringifies non serializable types"
@@ -195,6 +203,7 @@ async def _find_p(req, arg:str, p:Parameter):
195
203
  if arg.lower()=='app': return req.scope['app']
196
204
  if arg.lower()=='body': return (await req.body()).decode()
197
205
  if arg.lower()=='state': return req.scope['app'].state
206
+ if arg.lower()=='api': return ApiReturn(req.headers.get('accept')=='application/json')
198
207
  if arg.lower() in ('hdrs','ftrs','bodykw','htmlkw'): return getattr(req, arg.lower())
199
208
  if arg!='resp': warn(f"`{arg} has no type annotation and is not a recognised special name, so is ignored.")
200
209
  return None
@@ -702,15 +711,15 @@ def set_lifespan(self:FastHTML, value):
702
711
  self.router.lifespan_context = value
703
712
 
704
713
  # %% ../nbs/api/00_core.ipynb #3a348474
714
+ @delegates(uvicorn.run)
705
715
  def serve(
706
716
  appname=None, # Name of the module
707
717
  app='app', # App instance to be served
708
718
  host='0.0.0.0', # If host is 0.0.0.0 will convert to localhost
709
719
  port=None, # If port is None it will default to 5001 or the PORT environment variable
710
720
  reload=True, # Default is to reload the app upon code changes
711
- reload_includes:list[str]|str|None=None, # Additional files to watch for changes
712
- reload_excludes:list[str]|str|None=None # Files to ignore for changes
713
- ):
721
+ **kwargs
722
+ ):
714
723
  "Run the app in an async server, with live reload set as the default."
715
724
  bk = inspect.currentframe().f_back
716
725
  glb = bk.f_globals
@@ -718,11 +727,11 @@ def serve(
718
727
  if not appname:
719
728
  if glb.get('__name__')=='__main__': appname = Path(glb.get('__file__', '')).stem
720
729
  elif code.co_name=='main' and bk.f_back.f_globals.get('__name__')=='__main__': appname = inspect.getmodule(bk).__name__
721
- import uvicorn
722
730
  if appname:
723
731
  if not port: port=int(os.getenv("PORT", default=5001))
724
- print(f'Link: http://{"localhost" if host=="0.0.0.0" else host}:{port}')
725
- uvicorn.run(f'{appname}:{app}', host=host, port=port, reload=reload, reload_includes=reload_includes, reload_excludes=reload_excludes)
732
+ link = f'http://{"localhost" if host=="0.0.0.0" else host}:{port}'
733
+ print('Link: '+ S.light_red.bold(link))
734
+ uvicorn.run(f'{appname}:{app}', host=host, port=port, reload=reload, **kwargs)
726
735
 
727
736
  # %% ../nbs/api/00_core.ipynb #8121968a
728
737
  class Client:
@@ -3,14 +3,17 @@
3
3
  # AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/08_oauth.ipynb.
4
4
 
5
5
  # %% auto #0
6
- __all__ = ['http_patterns', 'GoogleAppClient', 'GitHubAppClient', 'HuggingFaceClient', 'DiscordAppClient', 'Auth0AppClient',
7
- 'AppleAppClient', 'get_host', 'redir_url', 'url_match', 'OAuth', 'load_creds']
6
+ __all__ = ['log', 'http_patterns', 'GoogleAppClient', 'GitHubAppClient', 'HuggingFaceClient', 'DiscordAppClient',
7
+ 'Auth0AppClient', 'AppleAppClient', 'get_host', 'redir_url', 'url_match', 'OAuth', 'load_creds']
8
8
 
9
9
  # %% ../nbs/api/08_oauth.ipynb #793722f2
10
10
  from .common import *
11
11
  from oauthlib.oauth2 import WebApplicationClient
12
12
  from urllib.parse import urlparse, urlencode, parse_qs, quote, unquote
13
- import secrets, httpx, time, asyncio
13
+ import secrets, httpx, time, asyncio, logging
14
+
15
+ # %% ../nbs/api/08_oauth.ipynb #44aa4a88
16
+ log = logging.getLogger(__name__)
14
17
 
15
18
  # %% ../nbs/api/08_oauth.ipynb #0a078133
16
19
  class _AppClient(WebApplicationClient):
@@ -186,8 +189,11 @@ async def parse_response_async(self:_AppClient, code, redirect_uri):
186
189
  "Get the token from the oauth2 server response"
187
190
  payload = dict(code=code, redirect_uri=redirect_uri, client_id=self.client_id,
188
191
  client_secret=self.client_secret, grant_type='authorization_code')
192
+ log.debug(f"OAuth token request: redirect_uri={redirect_uri}, code={code[:20]}...")
189
193
  async with httpx.AsyncClient() as c:
190
- r = (await c.post(self.token_url, data=payload)).raise_for_status()
194
+ r = (await c.post(self.token_url, data=payload))
195
+ log.debug(f"OAuth response: {r.status_code} - {r.text}")
196
+ r.raise_for_status()
191
197
  self.parse_request_body_response(r.text)
192
198
 
193
199
  @patch
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-fasthtml
3
- Version: 0.12.41
3
+ Version: 0.12.43
4
4
  Summary: The fastest way to create an HTML app
5
5
  Author-email: Jeremy Howard and contributors <github@jhoward.fastmail.fm>
6
6
  License: Apache-2.0
@@ -1,2 +0,0 @@
1
- __version__ = "0.12.41"
2
- from .core import *