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.
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/CONTRIBUTING.md +4 -1
- {python-fasthtml-0.6.8/python_fasthtml.egg-info → python-fasthtml-0.6.10}/PKG-INFO +2 -2
- python-fasthtml-0.6.10/fasthtml/__init__.py +2 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/_modidx.py +2 -1
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/oauth.py +24 -19
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10/python_fasthtml.egg-info}/PKG-INFO +2 -2
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/python_fasthtml.egg-info/requires.txt +1 -1
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/settings.ini +2 -2
- python-fasthtml-0.6.8/fasthtml/__init__.py +0 -2
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/LICENSE +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/MANIFEST.in +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/README.md +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/authmw.py +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/basics.py +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/cli.py +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/common.py +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/components.py +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/components.pyi +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/core.py +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/core.pyi +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/fastapp.py +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/ft.py +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/js.py +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/jupyter.py +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/katex.js +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/live_reload.py +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/pico.py +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/starlette.py +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/svg.py +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/toaster.py +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/xtend.py +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/fasthtml/xtend.pyi +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/pyproject.toml +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/python_fasthtml.egg-info/SOURCES.txt +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/python_fasthtml.egg-info/dependency_links.txt +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/python_fasthtml.egg-info/entry_points.txt +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/python_fasthtml.egg-info/not-zip-safe +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/python_fasthtml.egg-info/top_level.txt +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/setup.cfg +0 -0
- {python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/setup.py +0 -0
- {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
|
-
|
|
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.
|
|
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.
|
|
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
|
|
@@ -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.
|
|
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', '
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
153
|
-
|
|
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):
|
|
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.
|
|
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.
|
|
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,10 +1,10 @@
|
|
|
1
1
|
[DEFAULT]
|
|
2
2
|
repo = fasthtml
|
|
3
3
|
lib_name = fasthtml
|
|
4
|
-
version = 0.6.
|
|
4
|
+
version = 0.6.10
|
|
5
5
|
min_python = 3.10
|
|
6
6
|
license = apache2
|
|
7
|
-
requirements = fastcore>=1.7.
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python-fasthtml-0.6.8 → python-fasthtml-0.6.10}/python_fasthtml.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|