python-fasthtml 0.6.8__tar.gz → 0.6.10__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 (41) hide show
  1. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/CONTRIBUTING.md +4 -1
  2. {python-fasthtml-0.6.8/python_fasthtml.egg-info → python-fasthtml-0.6.10}/PKG-INFO +2 -2
  3. python-fasthtml-0.6.10/fasthtml/__init__.py +2 -0
  4. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/_modidx.py +2 -1
  5. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/oauth.py +24 -19
  6. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10/python_fasthtml.egg-info}/PKG-INFO +2 -2
  7. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/python_fasthtml.egg-info/requires.txt +1 -1
  8. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/settings.ini +2 -2
  9. python-fasthtml-0.6.8/fasthtml/__init__.py +0 -2
  10. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/LICENSE +0 -0
  11. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/MANIFEST.in +0 -0
  12. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/README.md +0 -0
  13. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/authmw.py +0 -0
  14. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/basics.py +0 -0
  15. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/cli.py +0 -0
  16. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/common.py +0 -0
  17. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/components.py +0 -0
  18. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/components.pyi +0 -0
  19. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/core.py +0 -0
  20. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/core.pyi +0 -0
  21. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/fastapp.py +0 -0
  22. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/ft.py +0 -0
  23. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/js.py +0 -0
  24. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/jupyter.py +0 -0
  25. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/katex.js +0 -0
  26. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/live_reload.py +0 -0
  27. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/pico.py +0 -0
  28. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/starlette.py +0 -0
  29. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/svg.py +0 -0
  30. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/toaster.py +0 -0
  31. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/xtend.py +0 -0
  32. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/xtend.pyi +0 -0
  33. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/pyproject.toml +0 -0
  34. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/python_fasthtml.egg-info/SOURCES.txt +0 -0
  35. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/python_fasthtml.egg-info/dependency_links.txt +0 -0
  36. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/python_fasthtml.egg-info/entry_points.txt +0 -0
  37. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/python_fasthtml.egg-info/not-zip-safe +0 -0
  38. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/python_fasthtml.egg-info/top_level.txt +0 -0
  39. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/setup.cfg +0 -0
  40. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/setup.py +0 -0
  41. {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/tests/test_toaster.py +0 -0
@@ -1,6 +1,9 @@
1
1
  # How to contribute
2
2
 
3
- This project uses [nbdev](https://nbdev.fast.ai/getting_started.html) for development. Before beginning, make sure that nbdev and a jupyter-compatible client such as jupyterlab or nbclassic are installed. To make changes, update the notebooks in the `nbs` folder, not the .py files directly. Then, run `nbdev_export`. For more details, have a look at the [nbdev tutorial](https://nbdev.fast.ai/tutorials/tutorial.html).
3
+ Make sure you have read the [doc on code style](
4
+ https://docs.fast.ai/dev/style.html) first. (Note that we don't follow PEP8, but instead follow a coding style designed specifically for numerical and interactive programming.)
5
+
6
+ This project uses [nbdev](https://nbdev.fast.ai/getting_started.html) for development. Before beginning, make sure that nbdev and a jupyter-compatible client such as jupyterlab or nbclassic are installed. To make changes, update the notebooks in the `nbs` folder, not the .py files directly. Then, run `nbdev_export`. For more details, have a look at the [nbdev tutorial](https://nbdev.fast.ai/tutorials/tutorial.html). Depending on the code changes, you might also need to run `tools/update.sh` to update python interface modules and [LLM reference material](https://github.com/AnswerDotAI/llms-txt).
4
7
 
5
8
  You may want to set up a `prep` alias in `~/.zshrc` or other shell startup file:
6
9
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-fasthtml
3
- Version: 0.6.8
3
+ Version: 0.6.10
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.8
18
+ Requires-Dist: fastcore>=1.7.10
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.10"
2
+ from .core import *
@@ -160,7 +160,8 @@ d = { 'settings': { 'branch': 'main',
160
160
  'fasthtml/oauth.py'),
161
161
  'fasthtml.oauth._AppClient.retr_id': ('api/oauth.html#_appclient.retr_id', 'fasthtml/oauth.py'),
162
162
  'fasthtml.oauth._AppClient.retr_info': ('api/oauth.html#_appclient.retr_info', 'fasthtml/oauth.py'),
163
- 'fasthtml.oauth.decode': ('api/oauth.html#decode', 'fasthtml/oauth.py')},
163
+ 'fasthtml.oauth.redir_url': ('api/oauth.html#redir_url', 'fasthtml/oauth.py'),
164
+ 'fasthtml.oauth.url_match': ('api/oauth.html#url_match', 'fasthtml/oauth.py')},
164
165
  'fasthtml.pico': { 'fasthtml.pico.Card': ('api/pico.html#card', 'fasthtml/pico.py'),
165
166
  'fasthtml.pico.Container': ('api/pico.html#container', 'fasthtml/pico.py'),
166
167
  'fasthtml.pico.DialogX': ('api/pico.html#dialogx', 'fasthtml/pico.py'),
@@ -3,14 +3,14 @@
3
3
  # AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/08_oauth.ipynb.
4
4
 
5
5
  # %% auto 0
6
- __all__ = ['GoogleAppClient', 'GitHubAppClient', 'HuggingFaceClient', 'DiscordAppClient', 'decode', 'OAuth']
6
+ __all__ = ['http_patterns', 'GoogleAppClient', 'GitHubAppClient', 'HuggingFaceClient', 'DiscordAppClient', 'redir_url',
7
+ 'url_match', 'OAuth']
7
8
 
8
9
  # %% ../nbs/api/08_oauth.ipynb
9
10
  from .common import *
10
11
  from oauthlib.oauth2 import WebApplicationClient
11
12
  from urllib.parse import urlparse, urlencode, parse_qs, quote, unquote
12
- from httpx import get, post
13
- import secrets
13
+ import secrets, httpx
14
14
 
15
15
  # %% ../nbs/api/08_oauth.ipynb
16
16
  class _AppClient(WebApplicationClient):
@@ -45,7 +45,6 @@ class GitHubAppClient(_AppClient):
45
45
  id_key = 'id'
46
46
 
47
47
  def __init__(self, client_id, client_secret, code=None, scope=None, **kwargs):
48
- if not scope: scope="user"
49
48
  super().__init__(client_id, client_secret, code=code, scope=scope, **kwargs)
50
49
 
51
50
  # %% ../nbs/api/08_oauth.ipynb
@@ -84,7 +83,7 @@ class DiscordAppClient(_AppClient):
84
83
  def parse_response(self, code):
85
84
  headers = {'Content-Type': 'application/x-www-form-urlencoded'}
86
85
  data = dict(grant_type='authorization_code', code=code)#, redirect_uri=self.redirect_uri)
87
- r = post(self.token_url, data=data, headers=headers, auth=(self.client_id, self.client_secret))
86
+ r = httpx.post(self.token_url, data=data, headers=headers, auth=(self.client_id, self.client_secret))
88
87
  r.raise_for_status()
89
88
  self.parse_request_body_response(r.text)
90
89
 
@@ -96,29 +95,28 @@ def login_link(self:WebApplicationClient, redirect_uri, scope=None, state=None):
96
95
  if not state: state=getattr(self, 'state', None)
97
96
  return self.prepare_request_uri(self.base_url, redirect_uri, scope, state=state)
98
97
 
98
+ # %% ../nbs/api/08_oauth.ipynb
99
+ def redir_url(request, redir_path, scheme='https'):
100
+ "Get the redir url for the host in `request`"
101
+ return f"{scheme}://{request.url.netloc}{redir_path}"
102
+
99
103
  # %% ../nbs/api/08_oauth.ipynb
100
104
  @patch
101
105
  def parse_response(self:_AppClient, code, redirect_uri):
102
106
  "Get the token from the oauth2 server response"
103
107
  payload = dict(code=code, redirect_uri=redirect_uri, client_id=self.client_id,
104
108
  client_secret=self.client_secret, grant_type='authorization_code')
105
- r = post(self.token_url, json=payload)
109
+ r = httpx.post(self.token_url, json=payload)
106
110
  r.raise_for_status()
107
111
  self.parse_request_body_response(r.text)
108
112
 
109
- # %% ../nbs/api/08_oauth.ipynb
110
- def decode(code_url):
111
- parsed_url = urlparse(code_url)
112
- query_params = parse_qs(parsed_url.query)
113
- return query_params.get('code', [''])[0], query_params.get('state', [''])[0], code_url.split('?')[0]
114
-
115
113
  # %% ../nbs/api/08_oauth.ipynb
116
114
  @patch
117
115
  def get_info(self:_AppClient, token=None):
118
116
  "Get the info for authenticated user"
119
117
  if not token: token = self.token["access_token"]
120
118
  headers = {'Authorization': f'Bearer {token}'}
121
- return get(self.info_url, headers=headers).json()
119
+ return httpx.get(self.info_url, headers=headers).json()
122
120
 
123
121
  # %% ../nbs/api/08_oauth.ipynb
124
122
  @patch
@@ -133,24 +131,29 @@ def retr_id(self:_AppClient, code, redirect_uri):
133
131
  "Call `retr_info` and then return id/subscriber value"
134
132
  return self.retr_info(code, redirect_uri)[self.id_key]
135
133
 
134
+ # %% ../nbs/api/08_oauth.ipynb
135
+ http_patterns = (r'^(localhost|127\.0\.0\.1)(:\d+)?$',)
136
+ def url_match(url, patterns=http_patterns):
137
+ return any(re.match(pattern, url.netloc.split(':')[0]) for pattern in patterns)
138
+
136
139
  # %% ../nbs/api/08_oauth.ipynb
137
140
  class OAuth:
138
- def __init__(self, app, cli, skip=None, redir_path='/redirect', logout_path='/logout', login_path='/login'):
141
+ def __init__(self, app, cli, skip=None, redir_path='/redirect', logout_path='/logout', login_path='/login', https=True, http_patterns=http_patterns):
139
142
  if not skip: skip = [redir_path,login_path]
140
- self.app,self.cli,self.skip,self.redir_path,self.logout_path,self.login_path = app,cli,skip,redir_path,logout_path,login_path
141
-
143
+ store_attr()
142
144
  def before(req, session):
143
145
  auth = req.scope['auth'] = session.get('auth')
144
146
  if not auth: return RedirectResponse(self.login_path, status_code=303)
145
147
  info = AttrDictDefault(cli.get_info(auth))
146
148
  if not self._chk_auth(info, session): return RedirectResponse(self.login_path, status_code=303)
149
+
147
150
  app.before.append(Beforeware(before, skip=skip))
148
151
 
149
152
  @app.get(redir_path)
150
153
  def redirect(code:str, req, session, state:str=None):
151
154
  if not code: return "No code provided!"
152
- base_url = f"{req.url.scheme}://{req.url.netloc}"
153
- print(base_url)
155
+ scheme = 'http' if url_match(req.url,self.http_patterns) or not self.https else 'https'
156
+ base_url = f"{scheme}://{req.url.netloc}"
154
157
  info = AttrDictDefault(cli.retr_info(code, base_url+redir_path))
155
158
  if not self._chk_auth(info, session): return RedirectResponse(self.login_path, status_code=303)
156
159
  session['auth'] = cli.token['access_token']
@@ -161,7 +164,9 @@ class OAuth:
161
164
  session.pop('auth', None)
162
165
  return self.logout(session)
163
166
 
164
- def redir_url(self, req): return f"{req.url.scheme}://{req.url.netloc}{self.redir_path}"
167
+ def redir_url(self, req):
168
+ scheme = 'http' if url_match(req.url,self.http_patterns) or not self.https else 'https'
169
+ return redir_url(req, self.redir_path, scheme)
165
170
  def login_link(self, req, scope=None, state=None): return self.cli.login_link(self.redir_url(req), scope=scope, state=state)
166
171
 
167
172
  def login(self, info, state): raise NotImplementedError()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-fasthtml
3
- Version: 0.6.8
3
+ Version: 0.6.10
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.8
18
+ Requires-Dist: fastcore>=1.7.10
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.8
1
+ fastcore>=1.7.10
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.6.8
4
+ version = 0.6.10
5
5
  min_python = 3.10
6
6
  license = apache2
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
7
+ requirements = fastcore>=1.7.10 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.6.8"
2
- from .core import *