Skip to content

Commit

Permalink
fixes #513
Browse files Browse the repository at this point in the history
  • Loading branch information
jph00 committed Oct 19, 2024
1 parent 5eac7ba commit 94a405b
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 31 deletions.
19 changes: 9 additions & 10 deletions fasthtml/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,21 +73,22 @@ def _get_htmx(h):
return HtmxHeaders(**res)

# %% ../nbs/api/00_core.ipynb
def _mk_list(t, v): return [t(o) for o in v]
def _mk_list(t, v): return [t(o) for o in listify(v)]

# %% ../nbs/api/00_core.ipynb
fh_cfg = AttrDict(indent=True)

# %% ../nbs/api/00_core.ipynb
def _fix_anno(t):
def _fix_anno(t, o):
"Create appropriate callable type for casting a `str` to type `t` (or first type in `t` if union)"
origin = get_origin(t)
if origin is Union or origin is UnionType or origin in (list,List):
t = first(o for o in get_args(t) if o!=type(None))
d = {bool: str2bool, int: str2int, date: str2date, UploadFile: noop}
res = d.get(t, t)
if origin in (list,List): return partial(_mk_list, res)
return lambda o: res(o[-1]) if isinstance(o,(list,tuple)) else res(o)
if origin in (list,List): return _mk_list(res, o)
if not isinstance(o, (str,list,tuple)): return o
return res(o[-1]) if isinstance(o,(list,tuple)) else res(o)

# %% ../nbs/api/00_core.ipynb
def _form_arg(k, v, d):
Expand All @@ -97,7 +98,7 @@ def _form_arg(k, v, d):
# This is the type we want to cast `v` to
anno = d.get(k, None)
if not anno: return v
return _fix_anno(anno)(v)
return _fix_anno(anno, v)

# %% ../nbs/api/00_core.ipynb
@dataclass
Expand Down Expand Up @@ -195,9 +196,8 @@ async def _find_p(req, arg:str, p:Parameter):
# If we have a default, return that if we have no value
if res in (empty,None): res = p.default
# We can cast str and list[str] to types; otherwise just return what we have
if not isinstance(res, (list,str)) or anno is empty: return res
anno = _fix_anno(anno)
try: return anno(res)
if anno is empty: return res
try: return _fix_anno(anno, res)
except ValueError: raise HTTPException(404, req.url.path) from None

async def _wrap_req(req, params):
Expand Down Expand Up @@ -241,8 +241,7 @@ def _find_wsp(ws, data, hdrs, arg:str, p:Parameter):
if res is empty or res is None: res = p.default
# We can cast str and list[str] to types; otherwise just return what we have
if not isinstance(res, (list,str)) or anno is empty: return res
anno = _fix_anno(anno)
return [anno(o) for o in res] if isinstance(res,list) else anno(res)
return [_fix_anno(anno, o) for o in res] if isinstance(res,list) else _fix_anno(anno, res)

def _wrap_ws(ws, data, params):
hdrs = {k.lower().replace('-','_'):v for k,v in data.pop('HEADERS', {}).items()}
Expand Down
60 changes: 40 additions & 20 deletions nbs/api/00_core.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@
{
"data": {
"text/plain": [
"datetime.datetime(2024, 10, 16, 14, 0)"
"datetime.datetime(2024, 10, 19, 14, 0)"
]
},
"execution_count": null,
Expand Down Expand Up @@ -280,7 +280,7 @@
"outputs": [],
"source": [
"#| export\n",
"def _mk_list(t, v): return [t(o) for o in v]"
"def _mk_list(t, v): return [t(o) for o in listify(v)]"
]
},
{
Expand Down Expand Up @@ -310,15 +310,16 @@
"outputs": [],
"source": [
"#| export\n",
"def _fix_anno(t):\n",
"def _fix_anno(t, o):\n",
" \"Create appropriate callable type for casting a `str` to type `t` (or first type in `t` if union)\"\n",
" origin = get_origin(t)\n",
" if origin is Union or origin is UnionType or origin in (list,List):\n",
" t = first(o for o in get_args(t) if o!=type(None))\n",
" d = {bool: str2bool, int: str2int, date: str2date, UploadFile: noop}\n",
" res = d.get(t, t)\n",
" if origin in (list,List): return partial(_mk_list, res)\n",
" return lambda o: res(o[-1]) if isinstance(o,(list,tuple)) else res(o)"
" if origin in (list,List): return _mk_list(res, o)\n",
" if not isinstance(o, (str,list,tuple)): return o\n",
" return res(o[-1]) if isinstance(o,(list,tuple)) else res(o)"
]
},
{
Expand All @@ -328,12 +329,12 @@
"metadata": {},
"outputs": [],
"source": [
"test_eq(_fix_anno(Union[str,None])('a'), 'a')\n",
"test_eq(_fix_anno(float)(0.9), 0.9)\n",
"test_eq(_fix_anno(int)('1'), 1)\n",
"test_eq(_fix_anno(int)(['1','2']), 2)\n",
"test_eq(_fix_anno(list[int])(['1','2']), [1,2])\n",
"test_eq(_fix_anno(list[int])('1'), [1])"
"test_eq(_fix_anno(Union[str,None], 'a'), 'a')\n",
"test_eq(_fix_anno(float, 0.9), 0.9)\n",
"test_eq(_fix_anno(int, '1'), 1)\n",
"test_eq(_fix_anno(int, ['1','2']), 2)\n",
"test_eq(_fix_anno(list[int], ['1','2']), [1,2])\n",
"test_eq(_fix_anno(list[int], '1'), [1])"
]
},
{
Expand All @@ -351,7 +352,7 @@
" # This is the type we want to cast `v` to\n",
" anno = d.get(k, None)\n",
" if not anno: return v\n",
" return _fix_anno(anno)(v)"
" return _fix_anno(anno, v)"
]
},
{
Expand Down Expand Up @@ -651,9 +652,8 @@
" # If we have a default, return that if we have no value\n",
" if res in (empty,None): res = p.default\n",
" # We can cast str and list[str] to types; otherwise just return what we have\n",
" if not isinstance(res, (list,str)) or anno is empty: return res\n",
" anno = _fix_anno(anno)\n",
" try: return anno(res)\n",
" if anno is empty: return res\n",
" try: return _fix_anno(anno, res)\n",
" except ValueError: raise HTTPException(404, req.url.path) from None\n",
"\n",
"async def _wrap_req(req, params):\n",
Expand Down Expand Up @@ -805,8 +805,7 @@
" if res is empty or res is None: res = p.default\n",
" # We can cast str and list[str] to types; otherwise just return what we have\n",
" if not isinstance(res, (list,str)) or anno is empty: return res\n",
" anno = _fix_anno(anno)\n",
" return [anno(o) for o in res] if isinstance(res,list) else anno(res)\n",
" return [_fix_anno(anno, o) for o in res] if isinstance(res,list) else _fix_anno(anno, res)\n",
"\n",
"def _wrap_ws(ws, data, params):\n",
" hdrs = {k.lower().replace('-','_'):v for k,v in data.pop('HEADERS', {}).items()}\n",
Expand Down Expand Up @@ -2233,6 +2232,27 @@
"print(res.text)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "28a99667",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"200\n",
"content1\n"
]
}
],
"source": [
"res = cli.post('/uploads', files=[files[0]])\n",
"print(res.status_code)\n",
"print(res.text)"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand All @@ -2243,13 +2263,13 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Set to 2024-10-16 15:38:25.588198\n"
"Set to 2024-10-19 15:14:43.250650\n"
]
},
{
"data": {
"text/plain": [
"'Session time: 2024-10-16 15:38:25.588198'"
"'Session time: 2024-10-19 15:14:43.250650'"
]
},
"execution_count": null,
Expand Down Expand Up @@ -2480,7 +2500,7 @@
{
"data": {
"text/plain": [
"'Cookie was set at time 15:38:25.962118'"
"'Cookie was set at time 15:14:43.683602'"
]
},
"execution_count": null,
Expand Down
1 change: 0 additions & 1 deletion nbs/api/04_pico.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@
"data": {
"text/html": [
"<link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/@picocss/pico@latest/css/pico.conditional.min.css\">\n",
"\n",
"<style>:root { --pico-font-size: 100%; }</style>\n"
],
"text/plain": [
Expand Down

0 comments on commit 94a405b

Please sign in to comment.