Skip to content

Commit

Permalink
fixes #512
Browse files Browse the repository at this point in the history
  • Loading branch information
jph00 committed Oct 10, 2024
1 parent 6a2c0f0 commit e91b9af
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 20 deletions.
17 changes: 10 additions & 7 deletions fasthtml/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,17 +368,20 @@ def _xt_cts(req, resp):
resp = resp + tuple(getattr(req, 'injects', ()))
http_hdrs,resp = partition(resp, risinstance(HttpHeader))
http_hdrs = {o.k:str(o.v) for o in http_hdrs}
tasks,resp = partition(resp, risinstance(BackgroundTask))
ts = BackgroundTasks()
for t in tasks: ts.tasks.append(t)
hdr_tags = 'title','meta','link','style','base'
titles,bdy = partition(resp, lambda o: getattr(o, 'tag', '') in hdr_tags)
if resp and 'hx-request' not in req.headers and not any(getattr(o, 'tag', '')=='html' for o in resp):
if not titles: titles = [Title('FastHTML page')]
resp = Html(Head(*titles, *flat_xt(req.hdrs)), Body(bdy, *flat_xt(req.ftrs), **req.bodykw), **req.htmlkw)
return _to_xml(req, resp, indent=fh_cfg.indent), http_hdrs
return _to_xml(req, resp, indent=fh_cfg.indent), http_hdrs, ts

# %% ../nbs/api/00_core.ipynb
def _xt_resp(req, resp):
cts,http_hdrs = _xt_cts(req, resp)
return HTMLResponse(cts, headers=http_hdrs)
cts,http_hdrs,tasks = _xt_cts(req, resp)
return HTMLResponse(cts, headers=http_hdrs, background=tasks)

# %% ../nbs/api/00_core.ipynb
def _is_ft_resp(resp): return isinstance(resp, (list,tuple,HttpHeader,FT)) or hasattr(resp, '__ft__')
Expand Down Expand Up @@ -652,11 +655,11 @@ async def __call__(self, scope, receive, send) -> None:
# %% ../nbs/api/00_core.ipynb
class FtResponse:
"Wrap an FT response with any Starlette `Response`"
def __init__(self, content, status_code:int=200, headers=None, cls=HTMLResponse, media_type:str|None=None, background=None):
def __init__(self, content, status_code:int=200, headers=None, cls=HTMLResponse, media_type:str|None=None):
self.content,self.status_code,self.headers = content,status_code,headers
self.cls,self.media_type,self.background = cls,media_type,background
self.cls,self.media_type = cls,media_type

def __response__(self, req):
cts,httphdrs = _xt_cts(req, self.content)
cts,httphdrs,tasks = _xt_cts(req, self.content)
headers = {**(self.headers or {}), **httphdrs}
return self.cls(cts, status_code=self.status_code, headers=headers, media_type=self.media_type, background=self.background)
return self.cls(cts, status_code=self.status_code, headers=headers, media_type=self.media_type, background=tasks)
2 changes: 2 additions & 0 deletions fasthtml/starlette.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@
from starlette.datastructures import CommaSeparatedStrings, Secret, UploadFile, URLPath
from starlette.types import ASGIApp, Receive, Scope, Send
from starlette.concurrency import run_in_threadpool
from starlette.background import BackgroundTask, BackgroundTasks

54 changes: 41 additions & 13 deletions nbs/api/00_core.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@
{
"data": {
"text/plain": [
"datetime.datetime(2024, 10, 10, 14, 0)"
"datetime.datetime(2024, 10, 11, 14, 0)"
]
},
"execution_count": null,
Expand Down Expand Up @@ -1054,12 +1054,15 @@
" resp = resp + tuple(getattr(req, 'injects', ()))\n",
" http_hdrs,resp = partition(resp, risinstance(HttpHeader))\n",
" http_hdrs = {o.k:str(o.v) for o in http_hdrs}\n",
" tasks,resp = partition(resp, risinstance(BackgroundTask))\n",
" ts = BackgroundTasks()\n",
" for t in tasks: ts.tasks.append(t)\n",
" hdr_tags = 'title','meta','link','style','base'\n",
" titles,bdy = partition(resp, lambda o: getattr(o, 'tag', '') in hdr_tags)\n",
" if resp and 'hx-request' not in req.headers and not any(getattr(o, 'tag', '')=='html' for o in resp):\n",
" if not titles: titles = [Title('FastHTML page')]\n",
" resp = Html(Head(*titles, *flat_xt(req.hdrs)), Body(bdy, *flat_xt(req.ftrs), **req.bodykw), **req.htmlkw)\n",
" return _to_xml(req, resp, indent=fh_cfg.indent), http_hdrs"
" return _to_xml(req, resp, indent=fh_cfg.indent), http_hdrs, ts"
]
},
{
Expand All @@ -1071,8 +1074,8 @@
"source": [
"#| export\n",
"def _xt_resp(req, resp):\n",
" cts,http_hdrs = _xt_cts(req, resp)\n",
" return HTMLResponse(cts, headers=http_hdrs)"
" cts,http_hdrs,tasks = _xt_cts(req, resp)\n",
" return HTMLResponse(cts, headers=http_hdrs, background=tasks)"
]
},
{
Expand Down Expand Up @@ -1245,7 +1248,7 @@
{
"data": {
"text/plain": [
"'8c0971cb-1c05-4aa4-99da-4553d00a0c3f'"
"'a604e4a2-08e8-462d-aff9-15468891fe09'"
]
},
"execution_count": null,
Expand Down Expand Up @@ -1509,7 +1512,7 @@
"metadata": {},
"outputs": [],
"source": [
"def get_cli(app): return app,Client(app),app.route"
"def get_cli(app): return app,TestClient(app),app.route"
]
},
{
Expand Down Expand Up @@ -1764,6 +1767,31 @@
"cli.get('/link').text"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "162b811e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Background task completed!\n"
]
}
],
"source": [
"@app.get(\"/background\")\n",
"async def background_task(request):\n",
" async def long_running_task():\n",
" await asyncio.sleep(0.1)\n",
" print(\"Background task completed!\")\n",
" return P(\"Task started\"), BackgroundTask(long_running_task)\n",
"\n",
"response = cli.get(\"/background\")"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand Down Expand Up @@ -2202,13 +2230,13 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Set to 2024-10-09 13:14:23.141104\n"
"Set to 2024-10-11 09:46:57.944986\n"
]
},
{
"data": {
"text/plain": [
"'Session time: 2024-10-09 13:14:23.141104'"
"'Session time: 2024-10-11 09:46:57.944986'"
]
},
"execution_count": null,
Expand Down Expand Up @@ -2439,7 +2467,7 @@
{
"data": {
"text/plain": [
"'Cookie was set at time 13:14:28.411872'"
"'Cookie was set at time 09:46:58.348630'"
]
},
"execution_count": null,
Expand Down Expand Up @@ -2569,14 +2597,14 @@
"#| export\n",
"class FtResponse:\n",
" \"Wrap an FT response with any Starlette `Response`\"\n",
" def __init__(self, content, status_code:int=200, headers=None, cls=HTMLResponse, media_type:str|None=None, background=None):\n",
" def __init__(self, content, status_code:int=200, headers=None, cls=HTMLResponse, media_type:str|None=None):\n",
" self.content,self.status_code,self.headers = content,status_code,headers\n",
" self.cls,self.media_type,self.background = cls,media_type,background\n",
" self.cls,self.media_type = cls,media_type\n",
" \n",
" def __response__(self, req):\n",
" cts,httphdrs = _xt_cts(req, self.content)\n",
" cts,httphdrs,tasks = _xt_cts(req, self.content)\n",
" headers = {**(self.headers or {}), **httphdrs}\n",
" return self.cls(cts, status_code=self.status_code, headers=headers, media_type=self.media_type, background=self.background)"
" return self.cls(cts, status_code=self.status_code, headers=headers, media_type=self.media_type, background=tasks)"
]
},
{
Expand Down

0 comments on commit e91b9af

Please sign in to comment.