python-fasthtml 0.12.28__tar.gz → 0.12.30__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.12.28/python_fasthtml.egg-info → python_fasthtml-0.12.30}/PKG-INFO +1 -1
- python_fasthtml-0.12.30/fasthtml/__init__.py +2 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/fasthtml/_modidx.py +12 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/fasthtml/core.py +9 -1
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/fasthtml/oauth.py +3 -1
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/fasthtml/xtend.py +92 -10
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30/python_fasthtml.egg-info}/PKG-INFO +1 -1
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/settings.ini +1 -1
- python_fasthtml-0.12.28/fasthtml/__init__.py +0 -2
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/CONTRIBUTING.md +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/LICENSE +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/MANIFEST.in +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/README.md +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/fasthtml/authmw.py +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/fasthtml/basics.py +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/fasthtml/cli.py +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/fasthtml/common.py +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/fasthtml/components.py +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/fasthtml/components.pyi +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/fasthtml/core.pyi +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/fasthtml/fastapp.py +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/fasthtml/ft.py +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/fasthtml/js.py +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/fasthtml/jupyter.py +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/fasthtml/katex.js +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/fasthtml/live_reload.py +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/fasthtml/pico.py +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/fasthtml/starlette.py +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/fasthtml/stripe_otp.py +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/fasthtml/svg.py +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/fasthtml/toaster.py +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/fasthtml/xtend.pyi +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/pyproject.toml +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/python_fasthtml.egg-info/SOURCES.txt +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/python_fasthtml.egg-info/dependency_links.txt +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/python_fasthtml.egg-info/entry_points.txt +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/python_fasthtml.egg-info/not-zip-safe +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/python_fasthtml.egg-info/requires.txt +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/python_fasthtml.egg-info/top_level.txt +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/setup.cfg +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/setup.py +0 -0
- {python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/tests/test_toaster.py +0 -0
|
@@ -73,6 +73,9 @@ d = { 'settings': { 'branch': 'main',
|
|
|
73
73
|
'fasthtml.core.RouteFuncs.__getattr__': ('api/core.html#routefuncs.__getattr__', 'fasthtml/core.py'),
|
|
74
74
|
'fasthtml.core.RouteFuncs.__init__': ('api/core.html#routefuncs.__init__', 'fasthtml/core.py'),
|
|
75
75
|
'fasthtml.core.RouteFuncs.__setattr__': ('api/core.html#routefuncs.__setattr__', 'fasthtml/core.py'),
|
|
76
|
+
'fasthtml.core.StaticNoCache': ('api/core.html#staticnocache', 'fasthtml/core.py'),
|
|
77
|
+
'fasthtml.core.StaticNoCache.file_response': ( 'api/core.html#staticnocache.file_response',
|
|
78
|
+
'fasthtml/core.py'),
|
|
76
79
|
'fasthtml.core.StringConvertor.to_string': ('api/core.html#stringconvertor.to_string', 'fasthtml/core.py'),
|
|
77
80
|
'fasthtml.core._add_ids': ('api/core.html#_add_ids', 'fasthtml/core.py'),
|
|
78
81
|
'fasthtml.core._annotations': ('api/core.html#_annotations', 'fasthtml/core.py'),
|
|
@@ -260,6 +263,12 @@ d = { 'settings': { 'branch': 'main',
|
|
|
260
263
|
'fasthtml.xtend.Fragment.__init__': ('api/xtend.html#fragment.__init__', 'fasthtml/xtend.py'),
|
|
261
264
|
'fasthtml.xtend.Hidden': ('api/xtend.html#hidden', 'fasthtml/xtend.py'),
|
|
262
265
|
'fasthtml.xtend.HtmxOn': ('api/xtend.html#htmxon', 'fasthtml/xtend.py'),
|
|
266
|
+
'fasthtml.xtend.LdContactPoint': ('api/xtend.html#ldcontactpoint', 'fasthtml/xtend.py'),
|
|
267
|
+
'fasthtml.xtend.LdCourse': ('api/xtend.html#ldcourse', 'fasthtml/xtend.py'),
|
|
268
|
+
'fasthtml.xtend.LdCourseInstance': ('api/xtend.html#ldcourseinstance', 'fasthtml/xtend.py'),
|
|
269
|
+
'fasthtml.xtend.LdJson': ('api/xtend.html#ldjson', 'fasthtml/xtend.py'),
|
|
270
|
+
'fasthtml.xtend.LdOrg': ('api/xtend.html#ldorg', 'fasthtml/xtend.py'),
|
|
271
|
+
'fasthtml.xtend.LdWebsite': ('api/xtend.html#ldwebsite', 'fasthtml/xtend.py'),
|
|
263
272
|
'fasthtml.xtend.Nbsp': ('api/xtend.html#nbsp', 'fasthtml/xtend.py'),
|
|
264
273
|
'fasthtml.xtend.Now': ('api/xtend.html#now', 'fasthtml/xtend.py'),
|
|
265
274
|
'fasthtml.xtend.On': ('api/xtend.html#on', 'fasthtml/xtend.py'),
|
|
@@ -277,6 +286,9 @@ d = { 'settings': { 'branch': 'main',
|
|
|
277
286
|
'fasthtml.xtend.jsd': ('api/xtend.html#jsd', 'fasthtml/xtend.py'),
|
|
278
287
|
'fasthtml.xtend.loose_format': ('api/xtend.html#loose_format', 'fasthtml/xtend.py'),
|
|
279
288
|
'fasthtml.xtend.replace_css_vars': ('api/xtend.html#replace_css_vars', 'fasthtml/xtend.py'),
|
|
289
|
+
'fasthtml.xtend.robots_txt': ('api/xtend.html#robots_txt', 'fasthtml/xtend.py'),
|
|
280
290
|
'fasthtml.xtend.run_js': ('api/xtend.html#run_js', 'fasthtml/xtend.py'),
|
|
291
|
+
'fasthtml.xtend.sitemap_url': ('api/xtend.html#sitemap_url', 'fasthtml/xtend.py'),
|
|
292
|
+
'fasthtml.xtend.sitemap_xml': ('api/xtend.html#sitemap_xml', 'fasthtml/xtend.py'),
|
|
281
293
|
'fasthtml.xtend.undouble_braces': ('api/xtend.html#undouble_braces', 'fasthtml/xtend.py'),
|
|
282
294
|
'fasthtml.xtend.with_sid': ('api/xtend.html#with_sid', 'fasthtml/xtend.py')}}}
|
|
@@ -8,7 +8,8 @@ __all__ = ['empty', 'htmx_hdrs', 'fh_cfg', 'htmx_resps', 'htmx_exts', 'htmxsrc',
|
|
|
8
8
|
'HtmxHeaders', 'HttpHeader', 'HtmxResponseHeaders', 'form2dict', 'parse_form', 'JSONResponse', 'flat_xt',
|
|
9
9
|
'Beforeware', 'EventStream', 'signal_shutdown', 'uri', 'decode_uri', 'flat_tuple', 'noop_body', 'respond',
|
|
10
10
|
'is_full_page', 'Redirect', 'get_key', 'qp', 'def_hdrs', 'FastHTML', 'nested_name', 'serve', 'Client',
|
|
11
|
-
'RouteFuncs', 'APIRouter', 'cookie', 'reg_re_param', '
|
|
11
|
+
'RouteFuncs', 'APIRouter', 'cookie', 'reg_re_param', 'StaticNoCache', 'MiddlewareBase', 'FtResponse',
|
|
12
|
+
'unqid']
|
|
12
13
|
|
|
13
14
|
# %% ../nbs/api/00_core.ipynb
|
|
14
15
|
import json,uuid,inspect,types,signal,asyncio,threading,inspect,random,contextlib
|
|
@@ -820,6 +821,13 @@ def static_route(self:FastHTML, ext='', prefix='/', static_path='.'):
|
|
|
820
821
|
@self.route(f"{prefix}{{fname:path}}{ext}")
|
|
821
822
|
async def get(fname:str): return FileResponse(f'{static_path}/{fname}{ext}')
|
|
822
823
|
|
|
824
|
+
# %% ../nbs/api/00_core.ipynb
|
|
825
|
+
class StaticNoCache(StaticFiles):
|
|
826
|
+
def file_response(self, *args, **kwargs):
|
|
827
|
+
resp = super().file_response(*args, **kwargs)
|
|
828
|
+
resp.headers.setdefault("Cache-Control", "no-cache")
|
|
829
|
+
return resp
|
|
830
|
+
|
|
823
831
|
# %% ../nbs/api/00_core.ipynb
|
|
824
832
|
class MiddlewareBase:
|
|
825
833
|
async def __call__(self, scope, receive, send) -> None:
|
|
@@ -184,7 +184,9 @@ class OAuth:
|
|
|
184
184
|
|
|
185
185
|
@app.get(redir_path)
|
|
186
186
|
def redirect(req, session, code:str=None, error:str=None, state:str=None):
|
|
187
|
-
if not code:
|
|
187
|
+
if not code:
|
|
188
|
+
session['oauth_error']=error
|
|
189
|
+
return RedirectResponse(self.error_path, status_code=303)
|
|
188
190
|
scheme = 'http' if url_match(req,self.http_patterns) or not self.https else 'https'
|
|
189
191
|
base_url = f"{scheme}://{get_host(req)}"
|
|
190
192
|
info = AttrDictDefault(cli.retr_info(code, base_url+redir_path))
|
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
# %% auto 0
|
|
6
6
|
__all__ = ['sid_scr', 'A', 'AX', 'Form', 'Hidden', 'CheckboxX', 'Script', 'Style', 'double_braces', 'undouble_braces',
|
|
7
7
|
'loose_format', 'ScriptX', 'replace_css_vars', 'StyleX', 'Nbsp', 'Surreal', 'On', 'Prev', 'Now', 'AnyNow',
|
|
8
|
-
'run_js', 'HtmxOn', 'jsd', 'Fragment', 'Titled', 'Socials', 'YouTubeEmbed', 'Favicon', 'clear', 'with_sid'
|
|
8
|
+
'run_js', 'HtmxOn', 'jsd', 'Fragment', 'Titled', 'Socials', 'YouTubeEmbed', 'Favicon', 'clear', 'with_sid',
|
|
9
|
+
'LdJson', 'LdContactPoint', 'LdOrg', 'LdWebsite', 'LdCourseInstance', 'LdCourse', 'robots_txt',
|
|
10
|
+
'sitemap_url', 'sitemap_xml']
|
|
9
11
|
|
|
10
12
|
# %% ../nbs/api/02_xtend.ipynb
|
|
11
13
|
from dataclasses import dataclass, asdict
|
|
@@ -224,18 +226,13 @@ def YouTubeEmbed(video_id:str, *, width:int=560, height:int=315, start_time:int=
|
|
|
224
226
|
print(f"https://www.youtube.com/embed/{video_id}{query_string}")
|
|
225
227
|
return Div(
|
|
226
228
|
Iframe(
|
|
227
|
-
width=width,
|
|
228
|
-
height=height,
|
|
229
|
+
width=width, height=height,
|
|
229
230
|
src=f"https://www.youtube.com/embed/{video_id}{query_string}",
|
|
230
|
-
title=title,
|
|
231
|
-
frameborder="0",
|
|
231
|
+
title=title, frameborder="0",
|
|
232
232
|
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share",
|
|
233
|
-
referrerpolicy="strict-origin-when-cross-origin",
|
|
234
|
-
allowfullscreen='',
|
|
233
|
+
referrerpolicy="strict-origin-when-cross-origin", allowfullscreen='',
|
|
235
234
|
**kwargs
|
|
236
|
-
),
|
|
237
|
-
cls=cls
|
|
238
|
-
)
|
|
235
|
+
), cls=cls)
|
|
239
236
|
|
|
240
237
|
# %% ../nbs/api/02_xtend.ipynb
|
|
241
238
|
def Favicon(light_icon, dark_icon):
|
|
@@ -268,3 +265,88 @@ htmx.on("htmx:configRequest", (e) => {
|
|
|
268
265
|
def with_sid(app, dest, path='/'):
|
|
269
266
|
@app.route(path)
|
|
270
267
|
def get(): return Div(hx_get=dest, hx_trigger=f'load delay:0.001s', hx_swap='outerHTML')
|
|
268
|
+
|
|
269
|
+
# %% ../nbs/api/02_xtend.ipynb
|
|
270
|
+
def LdJson(typ, data:dict, script=False, extra=None, **kwargs)->FT:
|
|
271
|
+
"A script tag containing JSON-LD structured data"
|
|
272
|
+
cts = {'@type':typ, "@context": "https://schema.org"} | data | (extra or {})
|
|
273
|
+
if not script: return cts
|
|
274
|
+
return Script(dumps(cts, indent=1), type="application/ld+json", **kwargs)
|
|
275
|
+
|
|
276
|
+
# %% ../nbs/api/02_xtend.ipynb
|
|
277
|
+
def LdContactPoint(contact_type:str, email:str=None, phone:str=None, script=False, **extra)->dict:
|
|
278
|
+
"Create a ContactPoint for JSON-LD"
|
|
279
|
+
data = {"contactType": contact_type}
|
|
280
|
+
if email: data["email"] = email
|
|
281
|
+
if phone: data["telephone"] = phone
|
|
282
|
+
return LdJson("ContactPoint", data, extra=extra, script=script)
|
|
283
|
+
|
|
284
|
+
# %% ../nbs/api/02_xtend.ipynb
|
|
285
|
+
def LdOrg(name:str, url:str=None, logo:str=None, alt_name:str=None,
|
|
286
|
+
same_as:list=None, contact_points:list=None, script=False, **extra)->dict:
|
|
287
|
+
"JSON-LD Organization structured data"
|
|
288
|
+
data = {"name": name}
|
|
289
|
+
if alt_name: data["alternateName"] = alt_name
|
|
290
|
+
if url: data["url"] = url
|
|
291
|
+
if logo: data["logo"] = logo
|
|
292
|
+
if same_as: data["sameAs"] = same_as
|
|
293
|
+
if contact_points: data["contactPoint"] = contact_points
|
|
294
|
+
return LdJson("Organization", data, extra=extra, script=script)
|
|
295
|
+
|
|
296
|
+
# %% ../nbs/api/02_xtend.ipynb
|
|
297
|
+
def LdWebsite(name:str, url:str, script=False, **extra)->dict:
|
|
298
|
+
"Create JSON-LD WebSite structured data"
|
|
299
|
+
data = {"name": name, "url": url}
|
|
300
|
+
return LdJson("WebSite", data, extra=extra, script=script)
|
|
301
|
+
|
|
302
|
+
# %% ../nbs/api/02_xtend.ipynb
|
|
303
|
+
def LdCourseInstance(course_mode:str="Online", start_date:str=None, end_date:str=None,
|
|
304
|
+
location:dict=None, instructor:dict=None, script=False, **extra)->dict:
|
|
305
|
+
"Create a CourseInstance for JSON-LD"
|
|
306
|
+
data = {"courseMode": course_mode}
|
|
307
|
+
if start_date: data["startDate"] = start_date
|
|
308
|
+
if end_date: data["endDate"] = end_date
|
|
309
|
+
if location: data["location"] = location
|
|
310
|
+
if instructor: data["instructor"] = instructor
|
|
311
|
+
return LdJson("CourseInstance", data, extra=extra, script=script)
|
|
312
|
+
|
|
313
|
+
# %% ../nbs/api/02_xtend.ipynb
|
|
314
|
+
def LdCourse(name:str, description:str, provider:dict, course_instance:dict=None, script=False, **extra)->dict:
|
|
315
|
+
"Create JSON-LD Course structured data"
|
|
316
|
+
data = { "name": name, "description": description, "provider": provider }
|
|
317
|
+
if course_instance: data["hasCourseInstance"] = course_instance
|
|
318
|
+
return LdJson("Course", data, extra=extra, script=script)
|
|
319
|
+
|
|
320
|
+
# %% ../nbs/api/02_xtend.ipynb
|
|
321
|
+
def robots_txt(app, allow_all=True, disallow_paths=None, sitemap_url=None, crawl_delay=None):
|
|
322
|
+
"Add a /robots.txt route to the app"
|
|
323
|
+
@app.route("/robots.txt")
|
|
324
|
+
def get():
|
|
325
|
+
lines = ["User-agent: *"]
|
|
326
|
+
if allow_all and not disallow_paths: lines.append("Allow: /")
|
|
327
|
+
elif disallow_paths: lines.extend(f"Disallow: {path}" for path in disallow_paths)
|
|
328
|
+
else: lines.append("Disallow: /")
|
|
329
|
+
if crawl_delay: lines.append(f"Crawl-delay: {crawl_delay}")
|
|
330
|
+
if sitemap_url: lines.append(f"Sitemap: {sitemap_url}")
|
|
331
|
+
return "\n".join(lines)
|
|
332
|
+
|
|
333
|
+
# %% ../nbs/api/02_xtend.ipynb
|
|
334
|
+
from fastcore.xml import Url,Loc,Lastmod,Changefreq,Priority,Urlset
|
|
335
|
+
|
|
336
|
+
# %% ../nbs/api/02_xtend.ipynb
|
|
337
|
+
def sitemap_url(url_info, loc_base=""):
|
|
338
|
+
"Create a sitemap URL element from url_info (string or dict)"
|
|
339
|
+
if isinstance(url_info, str): return Url(Loc(loc_base + url_info))
|
|
340
|
+
loc = loc_base + url_info['loc']
|
|
341
|
+
url_elem = [Loc(loc)]
|
|
342
|
+
if 'lastmod' in url_info: url_elem.append(Lastmod(url_info['lastmod']))
|
|
343
|
+
if 'changefreq' in url_info: url_elem.append(Changefreq(url_info['changefreq']))
|
|
344
|
+
if 'priority' in url_info: url_elem.append(Priority(str(url_info['priority'])))
|
|
345
|
+
return Url(*url_elem)
|
|
346
|
+
|
|
347
|
+
def sitemap_xml(app, urls, loc_base=""):
|
|
348
|
+
"Add a /sitemap.xml route to the app with list of URLs"
|
|
349
|
+
@app.route("/sitemap.xml")
|
|
350
|
+
def get():
|
|
351
|
+
urlset = [sitemap_url(url_info, loc_base) for url_info in urls]
|
|
352
|
+
return Urlset(*urlset, xmlns="http://www.sitemaps.org/schemas/sitemap/0.9")
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[DEFAULT]
|
|
2
2
|
repo = fasthtml
|
|
3
3
|
lib_name = python-fasthtml
|
|
4
|
-
version = 0.12.
|
|
4
|
+
version = 0.12.30
|
|
5
5
|
min_python = 3.10
|
|
6
6
|
license = apache2
|
|
7
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
|
|
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.12.28 → python_fasthtml-0.12.30}/python_fasthtml.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{python_fasthtml-0.12.28 → python_fasthtml-0.12.30}/python_fasthtml.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|