Skip to content

Commit a787fa3

Browse files
authored
Merge branch 'main' into add-pdf-2-reg_re_param
2 parents ced0197 + 7b258d7 commit a787fa3

File tree

8 files changed

+394
-37
lines changed

8 files changed

+394
-37
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,19 @@
22

33
<!-- do not remove -->
44

5+
## 0.11.0
6+
7+
### Breaking changes
8+
9+
- FT components now stringify as their id if they have one
10+
11+
### New Features
12+
13+
- Create unique route names for nested functions ([#622](https://github.com/AnswerDotAI/fasthtml/issues/622))
14+
- Pass `id=True` when creating a component to get an auto unique id ([#622](https://github.com/AnswerDotAI/fasthtml/issues/622))
15+
- Add `+` to FT components ([#622](https://github.com/AnswerDotAI/fasthtml/issues/622))
16+
17+
518
## 0.10.3
619

720
### Bugs Squashed

fasthtml/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
__version__ = "0.10.4"
1+
__version__ = "0.11.1"
22
from .core import *

fasthtml/_modidx.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@
1111
'fasthtml.cli.railway_deploy': ('api/cli.html#railway_deploy', 'fasthtml/cli.py'),
1212
'fasthtml.cli.railway_link': ('api/cli.html#railway_link', 'fasthtml/cli.py')},
1313
'fasthtml.common': {},
14-
'fasthtml.components': { 'fasthtml.components.File': ('api/components.html#file', 'fasthtml/components.py'),
14+
'fasthtml.components': { 'fasthtml.components.FT.__add__': ('api/components.html#ft.__add__', 'fasthtml/components.py'),
15+
'fasthtml.components.FT.__radd__': ('api/components.html#ft.__radd__', 'fasthtml/components.py'),
16+
'fasthtml.components.FT.__str__': ('api/components.html#ft.__str__', 'fasthtml/components.py'),
17+
'fasthtml.components.File': ('api/components.html#file', 'fasthtml/components.py'),
1518
'fasthtml.components.__getattr__': ('api/components.html#__getattr__', 'fasthtml/components.py'),
1619
'fasthtml.components._fill_item': ('api/components.html#_fill_item', 'fasthtml/components.py'),
1720
'fasthtml.components.attrmap_x': ('api/components.html#attrmap_x', 'fasthtml/components.py'),
@@ -103,6 +106,7 @@
103106
'fasthtml.core.flat_xt': ('api/core.html#flat_xt', 'fasthtml/core.py'),
104107
'fasthtml.core.form2dict': ('api/core.html#form2dict', 'fasthtml/core.py'),
105108
'fasthtml.core.get_key': ('api/core.html#get_key', 'fasthtml/core.py'),
109+
'fasthtml.core.nested_name': ('api/core.html#nested_name', 'fasthtml/core.py'),
106110
'fasthtml.core.noop_body': ('api/core.html#noop_body', 'fasthtml/core.py'),
107111
'fasthtml.core.parse_form': ('api/core.html#parse_form', 'fasthtml/core.py'),
108112
'fasthtml.core.parsed_date': ('api/core.html#parsed_date', 'fasthtml/core.py'),

fasthtml/components.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,18 @@ def show(ft,*rest):
3737
if rest: ft = (ft,)+rest
3838
display.display(display.HTML(to_xml(ft)))
3939

40+
# %% ../nbs/api/01_components.ipynb
41+
@patch
42+
def __str__(self:FT): return self.id if self.id else object.__str__(self)
43+
44+
# %% ../nbs/api/01_components.ipynb
45+
@patch
46+
def __radd__(self:FT, b): return f'{b}{self}'
47+
48+
# %% ../nbs/api/01_components.ipynb
49+
@patch
50+
def __add__(self:FT, b): return f'{self}{b}'
51+
4052
# %% ../nbs/api/01_components.ipynb
4153
named = set('a button form frame iframe img input map meta object param select textarea'.split())
4254
html_attrs = 'id cls title style accesskey contenteditable dir draggable enterkeyhint hidden inert inputmode lang popover spellcheck tabindex translate'.split()
@@ -69,14 +81,14 @@ def attrmap_x(o):
6981
fh_cfg['auto_name']=True
7082

7183
# %% ../nbs/api/01_components.ipynb
72-
def ft_html(tag: str, *c, id=None, cls=None, title=None, style=None, attrmap=None, valmap=None, ft_cls=None, auto_id=None, **kwargs):
84+
def ft_html(tag: str, *c, id=None, cls=None, title=None, style=None, attrmap=None, valmap=None, ft_cls=None, **kwargs):
7385
ds,c = partition(c, risinstance(dict))
7486
for d in ds: kwargs = {**kwargs, **d}
7587
if ft_cls is None: ft_cls = fh_cfg.ft_cls
7688
if attrmap is None: attrmap=fh_cfg.attrmap
7789
if valmap is None: valmap =fh_cfg.valmap
78-
if auto_id is None: auto_id = fh_cfg.auto_id
79-
if auto_id and not id: id = unqid()
90+
if not id and fh_cfg.auto_id: id = True
91+
if id and isinstance(id,bool): id = unqid()
8092
kwargs['id'] = id.id if isinstance(id,FT) else id
8193
kwargs['cls'],kwargs['title'],kwargs['style'] = cls,title,style
8294
tag,c,kw = ft(tag, *c, attrmap=attrmap, valmap=valmap, **kwargs).list

fasthtml/core.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
'charset', 'cors_allow', 'iframe_scr', 'all_meths', 'parsed_date', 'snake2hyphens', 'HtmxHeaders',
88
'HttpHeader', 'HtmxResponseHeaders', 'form2dict', 'parse_form', 'flat_xt', 'Beforeware', 'EventStream',
99
'signal_shutdown', 'uri', 'decode_uri', 'flat_tuple', 'noop_body', 'respond', 'Redirect', 'get_key', 'qp',
10-
'def_hdrs', 'FastHTML', 'serve', 'Client', 'RouteFuncs', 'APIRouter', 'cookie', 'reg_re_param',
11-
'MiddlewareBase', 'FtResponse', 'unqid', 'setup_ws']
10+
'def_hdrs', 'FastHTML', 'nested_name', 'serve', 'Client', 'RouteFuncs', 'APIRouter', 'cookie',
11+
'reg_re_param', 'MiddlewareBase', 'FtResponse', 'unqid', 'setup_ws']
1212

1313
# %% ../nbs/api/00_core.ipynb
1414
import json,uuid,inspect,types,uvicorn,signal,asyncio,threading,inspect
@@ -597,10 +597,15 @@ def to(self, **kw): return qp(p, **kw)
597597
def __str__(self): return p
598598
return _lf()
599599

600+
# %% ../nbs/api/00_core.ipynb
601+
def nested_name(f):
602+
"Get name of function `f` using '_' to join nested function names"
603+
return f.__qualname__.replace('.<locals>.', '_')
604+
600605
# %% ../nbs/api/00_core.ipynb
601606
@patch
602607
def _add_route(self:FastHTML, func, path, methods, name, include_in_schema, body_wrap):
603-
n,fn,p = name,func.__name__,None if callable(path) else path
608+
n,fn,p = name,nested_name(func),None if callable(path) else path
604609
if methods: m = [methods] if isinstance(methods,str) else methods
605610
elif fn in all_meths and p is not None: m = [fn]
606611
else: m = ['get','post']

nbs/api/00_core.ipynb

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@
131131
{
132132
"data": {
133133
"text/plain": [
134-
"datetime.datetime(2024, 12, 27, 14, 0)"
134+
"datetime.datetime(2025, 1, 5, 14, 0)"
135135
]
136136
},
137137
"execution_count": null,
@@ -1230,7 +1230,7 @@
12301230
{
12311231
"data": {
12321232
"text/plain": [
1233-
"'a2597a39-e99d-4460-90b9-2ca21e87bc8f'"
1233+
"'cc87253c-bfc1-4544-bbc0-58dd8d3291bc'"
12341234
]
12351235
},
12361236
"execution_count": null,
@@ -1485,6 +1485,53 @@
14851485
" return _lf()"
14861486
]
14871487
},
1488+
{
1489+
"cell_type": "code",
1490+
"execution_count": null,
1491+
"id": "d2ecc738",
1492+
"metadata": {},
1493+
"outputs": [],
1494+
"source": [
1495+
"#| export\n",
1496+
"def nested_name(f):\n",
1497+
" \"Get name of function `f` using '_' to join nested function names\"\n",
1498+
" return f.__qualname__.replace('.<locals>.', '_')"
1499+
]
1500+
},
1501+
{
1502+
"cell_type": "code",
1503+
"execution_count": null,
1504+
"id": "c0f13ece",
1505+
"metadata": {},
1506+
"outputs": [],
1507+
"source": [
1508+
"def f():\n",
1509+
" def g(): ...\n",
1510+
" return g"
1511+
]
1512+
},
1513+
{
1514+
"cell_type": "code",
1515+
"execution_count": null,
1516+
"id": "b218f738",
1517+
"metadata": {},
1518+
"outputs": [
1519+
{
1520+
"data": {
1521+
"text/plain": [
1522+
"'f_g'"
1523+
]
1524+
},
1525+
"execution_count": null,
1526+
"metadata": {},
1527+
"output_type": "execute_result"
1528+
}
1529+
],
1530+
"source": [
1531+
"func = f()\n",
1532+
"nested_name(func)"
1533+
]
1534+
},
14881535
{
14891536
"cell_type": "code",
14901537
"execution_count": null,
@@ -1495,7 +1542,7 @@
14951542
"#| export\n",
14961543
"@patch\n",
14971544
"def _add_route(self:FastHTML, func, path, methods, name, include_in_schema, body_wrap):\n",
1498-
" n,fn,p = name,func.__name__,None if callable(path) else path\n",
1545+
" n,fn,p = name,nested_name(func),None if callable(path) else path\n",
14991546
" if methods: m = [methods] if isinstance(methods,str) else methods\n",
15001547
" elif fn in all_meths and p is not None: m = [fn]\n",
15011548
" else: m = ['get','post']\n",
@@ -2478,13 +2525,13 @@
24782525
"name": "stdout",
24792526
"output_type": "stream",
24802527
"text": [
2481-
"Set to 2024-12-27 08:45:58.732664\n"
2528+
"Set to 2025-01-05 15:35:39.508212\n"
24822529
]
24832530
},
24842531
{
24852532
"data": {
24862533
"text/plain": [
2487-
"'Session time: 2024-12-27 08:45:58.732664'"
2534+
"'Session time: 2025-01-05 15:35:39.508212'"
24882535
]
24892536
},
24902537
"execution_count": null,
@@ -3005,7 +3052,7 @@
30053052
{
30063053
"data": {
30073054
"text/plain": [
3008-
"'Cookie was set at time 08:45:58.893906'"
3055+
"'Cookie was set at time 15:35:40.128784'"
30093056
]
30103057
},
30113058
"execution_count": null,

0 commit comments

Comments
 (0)