python-fasthtml 0.12.35__tar.gz → 0.12.37__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.35/python_fasthtml.egg-info → python_fasthtml-0.12.37}/PKG-INFO +3 -2
  2. python_fasthtml-0.12.37/fasthtml/__init__.py +2 -0
  3. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/fasthtml/_modidx.py +6 -1
  4. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/fasthtml/fastapp.py +1 -1
  5. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/fasthtml/jupyter.py +2 -2
  6. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/fasthtml/oauth.py +32 -4
  7. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/fasthtml/svg.py +2 -2
  8. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/fasthtml/toaster.py +1 -1
  9. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37/python_fasthtml.egg-info}/PKG-INFO +3 -2
  10. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/python_fasthtml.egg-info/requires.txt +2 -1
  11. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/settings.ini +3 -3
  12. python_fasthtml-0.12.35/fasthtml/__init__.py +0 -2
  13. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/CONTRIBUTING.md +0 -0
  14. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/LICENSE +0 -0
  15. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/MANIFEST.in +0 -0
  16. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/README.md +0 -0
  17. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/fasthtml/authmw.py +0 -0
  18. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/fasthtml/basics.py +0 -0
  19. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/fasthtml/cli.py +0 -0
  20. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/fasthtml/common.py +0 -0
  21. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/fasthtml/components.py +0 -0
  22. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/fasthtml/components.pyi +0 -0
  23. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/fasthtml/core.py +0 -0
  24. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/fasthtml/core.pyi +0 -0
  25. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/fasthtml/ft.py +0 -0
  26. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/fasthtml/js.py +0 -0
  27. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/fasthtml/katex.js +0 -0
  28. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/fasthtml/live_reload.py +0 -0
  29. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/fasthtml/pico.py +0 -0
  30. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/fasthtml/starlette.py +0 -0
  31. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/fasthtml/stripe_otp.py +0 -0
  32. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/fasthtml/xtend.py +0 -0
  33. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/fasthtml/xtend.pyi +0 -0
  34. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/pyproject.toml +0 -0
  35. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/python_fasthtml.egg-info/SOURCES.txt +0 -0
  36. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/python_fasthtml.egg-info/dependency_links.txt +0 -0
  37. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/python_fasthtml.egg-info/entry_points.txt +0 -0
  38. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/python_fasthtml.egg-info/not-zip-safe +0 -0
  39. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/python_fasthtml.egg-info/top_level.txt +0 -0
  40. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/setup.cfg +0 -0
  41. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/setup.py +0 -0
  42. {python_fasthtml-0.12.35 → python_fasthtml-0.12.37}/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.35
3
+ Version: 0.12.37
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
@@ -18,7 +18,7 @@ Classifier: License :: OSI Approved :: Apache Software License
18
18
  Requires-Python: >=3.10
19
19
  Description-Content-Type: text/markdown
20
20
  License-File: LICENSE
21
- Requires-Dist: fastcore>=1.8.1
21
+ Requires-Dist: fastcore>=1.10.0
22
22
  Requires-Dist: python-dateutil
23
23
  Requires-Dist: starlette>0.33
24
24
  Requires-Dist: oauthlib
@@ -33,6 +33,7 @@ Requires-Dist: ipython; extra == "dev"
33
33
  Requires-Dist: lxml; extra == "dev"
34
34
  Requires-Dist: pysymbol_llm; extra == "dev"
35
35
  Requires-Dist: monsterui; extra == "dev"
36
+ Requires-Dist: PyJWT; extra == "dev"
36
37
  Dynamic: author
37
38
  Dynamic: author-email
38
39
  Dynamic: classifier
@@ -0,0 +1,2 @@
1
+ __version__ = "0.12.37"
2
+ from .core import *
@@ -158,7 +158,12 @@ d = { 'settings': { 'branch': 'main',
158
158
  'fasthtml.jupyter.wait_port_free': ('api/jupyter.html#wait_port_free', 'fasthtml/jupyter.py'),
159
159
  'fasthtml.jupyter.ws_client': ('api/jupyter.html#ws_client', 'fasthtml/jupyter.py')},
160
160
  'fasthtml.live_reload': {},
161
- 'fasthtml.oauth': { 'fasthtml.oauth.Auth0AppClient': ('api/oauth.html#auth0appclient', 'fasthtml/oauth.py'),
161
+ 'fasthtml.oauth': { 'fasthtml.oauth.AppleAppClient': ('api/oauth.html#appleappclient', 'fasthtml/oauth.py'),
162
+ 'fasthtml.oauth.AppleAppClient.__init__': ('api/oauth.html#appleappclient.__init__', 'fasthtml/oauth.py'),
163
+ 'fasthtml.oauth.AppleAppClient.client_secret': ( 'api/oauth.html#appleappclient.client_secret',
164
+ 'fasthtml/oauth.py'),
165
+ 'fasthtml.oauth.AppleAppClient.get_info': ('api/oauth.html#appleappclient.get_info', 'fasthtml/oauth.py'),
166
+ 'fasthtml.oauth.Auth0AppClient': ('api/oauth.html#auth0appclient', 'fasthtml/oauth.py'),
162
167
  'fasthtml.oauth.Auth0AppClient.__init__': ('api/oauth.html#auth0appclient.__init__', 'fasthtml/oauth.py'),
163
168
  'fasthtml.oauth.Auth0AppClient._fetch_openid_config': ( 'api/oauth.html#auth0appclient._fetch_openid_config',
164
169
  'fasthtml/oauth.py'),
@@ -63,7 +63,7 @@ def fast_app(
63
63
  static_path:str=".", # Where the static file route points to, defaults to root dir
64
64
  body_wrap:callable=noop_body, # FT wrapper for body contents
65
65
  nb_hdrs:bool=False, # If in notebook include headers inject headers in notebook DOM?
66
- **kwargs)->Any:
66
+ **kwargs):
67
67
  "Create a FastHTML or FastHTMLWithLiveReload app."
68
68
  h = (picolink,) if pico or (pico is None and default_hdrs) else ()
69
69
  if hdrs: h += tuple(hdrs)
@@ -63,9 +63,9 @@ def show(*s, **kwargs):
63
63
 
64
64
  # %% ../nbs/api/06_jupyter.ipynb
65
65
  def render_ft(**kw):
66
- "Call once in a notebook or solveit dialog to auto-render components"
66
+ "Call once in a notebook or solveit dialog to auto-render components with HTMX support"
67
67
  @patch
68
- def _repr_markdown_(self:FT):
68
+ def _repr_html_(self:FT):
69
69
  scr_proc = Script('if (window.htmx) htmx.process(document.body)')
70
70
  return to_xml(Div(self, scr_proc, **kw))
71
71
 
@@ -4,13 +4,13 @@
4
4
 
5
5
  # %% auto 0
6
6
  __all__ = ['http_patterns', 'GoogleAppClient', 'GitHubAppClient', 'HuggingFaceClient', 'DiscordAppClient', 'Auth0AppClient',
7
- 'get_host', 'redir_url', 'url_match', 'OAuth', 'load_creds']
7
+ 'AppleAppClient', 'get_host', 'redir_url', 'url_match', 'OAuth', 'load_creds']
8
8
 
9
9
  # %% ../nbs/api/08_oauth.ipynb
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
13
+ import secrets, httpx, time
14
14
 
15
15
  # %% ../nbs/api/08_oauth.ipynb
16
16
  class _AppClient(WebApplicationClient):
@@ -112,6 +112,33 @@ class Auth0AppClient(_AppClient):
112
112
  d = dict(response_type="code", client_id=self.client_id, scope=self.scope, redirect_uri=redir_url(req, self.redirect_uri))
113
113
  return f"{self.base_url}?{urlencode(d)}"
114
114
 
115
+ # %% ../nbs/api/08_oauth.ipynb
116
+ class AppleAppClient(_AppClient):
117
+ "A `WebApplicationClient` for Apple Sign In"
118
+ base_url = "https://appleid.apple.com/auth/authorize"
119
+ token_url = "https://appleid.apple.com/auth/token"
120
+
121
+ def __init__(self, client_id, key_id, team_id, private_key, code=None, scope=None, **kwargs):
122
+ if not scope: scope = ["name", "email"]
123
+ super().__init__(client_id, client_secret=None, code=code, scope=scope, **kwargs)
124
+ self.key_id, self.team_id, self.private_key = key_id, team_id, private_key
125
+
126
+ @property
127
+ def client_secret(self):
128
+ import jwt
129
+ now = int(time.time())
130
+ payload = dict(iss=self.team_id, iat=now, exp=now + 86400 * 180, aud='https://appleid.apple.com', sub=self.client_id)
131
+ return jwt.encode(payload, self.private_key, algorithm='ES256', headers={'kid': self.key_id})
132
+
133
+ @client_secret.setter
134
+ def client_secret(self, value): pass
135
+
136
+ def get_info(self, token=None):
137
+ "Decode user info from the ID token"
138
+ import jwt
139
+ if token: self.token = token
140
+ return jwt.decode(self.token.get('id_token'), options={"verify_signature": False})
141
+
115
142
  # %% ../nbs/api/08_oauth.ipynb
116
143
  @patch
117
144
  def login_link(self:WebApplicationClient, redirect_uri, scope=None, state=None, **kwargs):
@@ -171,8 +198,9 @@ def url_match(request, patterns=http_patterns):
171
198
 
172
199
  # %% ../nbs/api/08_oauth.ipynb
173
200
  class OAuth:
174
- def __init__(self, app, cli, skip=None, redir_path='/redirect', error_path='/error', logout_path='/logout', login_path='/login', https=True, http_patterns=http_patterns):
201
+ def __init__(self, app, cli, skip=None, redir_path='/redirect', error_path='/error', logout_path='/logout', login_path='/login', https=True, http_patterns=http_patterns, redir_method='get'):
175
202
  if not skip: skip = [redir_path,error_path,login_path]
203
+ redir_handler = app.post if redir_method == 'post' else app.get
176
204
  store_attr()
177
205
  def before(req, session):
178
206
  if 'auth' not in req.scope: req.scope['auth'] = session.get('auth')
@@ -182,7 +210,7 @@ class OAuth:
182
210
  if res: return res
183
211
  app.before.append(Beforeware(before, skip=skip))
184
212
 
185
- @app.get(redir_path)
213
+ @redir_handler(redir_path)
186
214
  def redirect(req, session, code:str=None, error:str=None, state:str=None):
187
215
  if not code:
188
216
  session['oauth_error']=error
@@ -79,9 +79,9 @@ def transformd(translate=None, scale=None, rotate=None, skewX=None, skewY=None,
79
79
 
80
80
  # %% ../nbs/api/05_svg.ipynb
81
81
  @delegates(ft_svg)
82
- def Line(x1, y1, x2=0, y2=0, stroke='black', w=None, stroke_width=1, **kwargs):
82
+ def Line(x1, y1, x2=0, y2=0, stroke=None, w=None, stroke_width=None, **kwargs):
83
83
  "A standard SVG `line` element"
84
- if w: stroke_width=w
84
+ if w: stroke_width = w
85
85
  return ft_svg('line', x1=x1, y1=y1, x2=x2, y2=y2, stroke=stroke, stroke_width=stroke_width, **kwargs)
86
86
 
87
87
  # %% ../nbs/api/05_svg.ipynb
@@ -7,7 +7,7 @@ tcid='fh-toast-container'
7
7
  sk = "toasts"
8
8
  toast_css = """
9
9
  #fh-toast-container {
10
- position: fixed; inset: 20px 0; z-index: 1000; max-width: 80vw;
10
+ position: fixed; inset: 20px 0; z-index: 1090; max-width: 80vw;
11
11
  display: flex; flex-direction: column; align-items: center;
12
12
  gap: 10px; pointer-events: none; margin: 0 auto;
13
13
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-fasthtml
3
- Version: 0.12.35
3
+ Version: 0.12.37
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
@@ -18,7 +18,7 @@ Classifier: License :: OSI Approved :: Apache Software License
18
18
  Requires-Python: >=3.10
19
19
  Description-Content-Type: text/markdown
20
20
  License-File: LICENSE
21
- Requires-Dist: fastcore>=1.8.1
21
+ Requires-Dist: fastcore>=1.10.0
22
22
  Requires-Dist: python-dateutil
23
23
  Requires-Dist: starlette>0.33
24
24
  Requires-Dist: oauthlib
@@ -33,6 +33,7 @@ Requires-Dist: ipython; extra == "dev"
33
33
  Requires-Dist: lxml; extra == "dev"
34
34
  Requires-Dist: pysymbol_llm; extra == "dev"
35
35
  Requires-Dist: monsterui; extra == "dev"
36
+ Requires-Dist: PyJWT; extra == "dev"
36
37
  Dynamic: author
37
38
  Dynamic: author-email
38
39
  Dynamic: classifier
@@ -1,4 +1,4 @@
1
- fastcore>=1.8.1
1
+ fastcore>=1.10.0
2
2
  python-dateutil
3
3
  starlette>0.33
4
4
  oauthlib
@@ -14,3 +14,4 @@ ipython
14
14
  lxml
15
15
  pysymbol_llm
16
16
  monsterui
17
+ PyJWT
@@ -1,11 +1,11 @@
1
1
  [DEFAULT]
2
2
  repo = fasthtml
3
3
  lib_name = python-fasthtml
4
- version = 0.12.35
4
+ version = 0.12.37
5
5
  min_python = 3.10
6
6
  license = apache2
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
8
- dev_requirements = ipython lxml pysymbol_llm monsterui
7
+ requirements = fastcore>=1.10.0 python-dateutil starlette>0.33 oauthlib itsdangerous uvicorn[standard]>=0.30 httpx fastlite>=0.1.1 python-multipart beautifulsoup4
8
+ dev_requirements = ipython lxml pysymbol_llm monsterui PyJWT
9
9
  black_formatting = False
10
10
  conda_user = fastai
11
11
  doc_path = _docs
@@ -1,2 +0,0 @@
1
- __version__ = "0.12.35"
2
- from .core import *