Skip to content

Commit 85b96ca

Browse files
committed
fixes #640
1 parent 72a2adb commit 85b96ca

File tree

5 files changed

+48
-78
lines changed

5 files changed

+48
-78
lines changed

fastcore/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "1.7.16"
1+
__version__ = "1.7.17"

fastcore/_modidx.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,6 @@
595595
'fastcore.xdg.xdg_runtime_dir': ('xdg.html#xdg_runtime_dir', 'fastcore/xdg.py'),
596596
'fastcore.xdg.xdg_state_home': ('xdg.html#xdg_state_home', 'fastcore/xdg.py')},
597597
'fastcore.xml': { 'fastcore.xml.FT': ('xml.html#ft', 'fastcore/xml.py'),
598-
'fastcore.xml.FT.__add__': ('xml.html#ft.__add__', 'fastcore/xml.py'),
599598
'fastcore.xml.FT.__call__': ('xml.html#ft.__call__', 'fastcore/xml.py'),
600599
'fastcore.xml.FT.__getattr__': ('xml.html#ft.__getattr__', 'fastcore/xml.py'),
601600
'fastcore.xml.FT.__getitem__': ('xml.html#ft.__getitem__', 'fastcore/xml.py'),
@@ -604,8 +603,10 @@
604603
'fastcore.xml.FT.__repr__': ('xml.html#ft.__repr__', 'fastcore/xml.py'),
605604
'fastcore.xml.FT.__setattr__': ('xml.html#ft.__setattr__', 'fastcore/xml.py'),
606605
'fastcore.xml.FT.__setitem__': ('xml.html#ft.__setitem__', 'fastcore/xml.py'),
606+
'fastcore.xml.FT.changed': ('xml.html#ft.changed', 'fastcore/xml.py'),
607607
'fastcore.xml.FT.get': ('xml.html#ft.get', 'fastcore/xml.py'),
608608
'fastcore.xml.FT.list': ('xml.html#ft.list', 'fastcore/xml.py'),
609+
'fastcore.xml.FT.on': ('xml.html#ft.on', 'fastcore/xml.py'),
609610
'fastcore.xml.FT.set': ('xml.html#ft.set', 'fastcore/xml.py'),
610611
'fastcore.xml.Html': ('xml.html#html', 'fastcore/xml.py'),
611612
'fastcore.xml.Safe': ('xml.html#safe', 'fastcore/xml.py'),

fastcore/xml.py

+22-16
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,17 @@ class FT:
5858
def __init__(self, tag:str, cs:tuple, attrs:dict=None, void_=False, **kwargs):
5959
assert isinstance(cs, tuple)
6060
self.tag,self.children,self.attrs,self.void_ = tag,cs,attrs,void_
61+
self.listeners_ = []
62+
63+
def on(self, f): self.listeners_.append(f)
64+
def changed(self):
65+
[f(self) for f in self.listeners_]
66+
return self
6167

6268
def __setattr__(self, k, v):
63-
if k.startswith('__') or k in ('tag','children','attrs','void_'): return super().__setattr__(k,v)
69+
if k.startswith('__') or k[-1]=='_' or k in ('tag','children','attrs','void_'): return super().__setattr__(k,v)
6470
self.attrs[k.lstrip('_').replace('_', '-')] = v
71+
self.changed()
6572

6673
def __getattr__(self, k):
6774
if k.startswith('__'): raise AttributeError(k)
@@ -71,28 +78,27 @@ def __getattr__(self, k):
7178
def list(self): return [self.tag,self.children,self.attrs]
7279
def get(self, k, default=None): return self.attrs.get(k.lstrip('_').replace('_', '-'), default)
7380
def __repr__(self): return f'{self.tag}({self.children},{self.attrs})'
74-
75-
def __add__(self, b):
76-
self.children = self.children + tuplify(b)
77-
return self
81+
def __iter__(self): return iter(self.children)
82+
def __getitem__(self, idx): return self.children[idx]
7883

7984
def __setitem__(self, i, o):
8085
self.children = self.children[:i] + (o,) + self.children[i+1:]
81-
82-
def __getitem__(self, idx): return self.children[idx]
83-
def __iter__(self): return iter(self.children)
86+
self.changed()
8487

8588
def __call__(self, *c, **kw):
8689
c,kw = _preproc(c,kw)
87-
if c: self = self+c
90+
if c: self.children = self.children+c
8891
if kw: self.attrs = {**self.attrs, **kw}
89-
return self
92+
return self.changed()
9093

91-
def set(self, *o, **k):
92-
"Set children and/or attributes—chainable"
93-
if o: self.children = o
94-
for k,v in k.items(): setattr(self,k,v)
95-
return self
94+
def set(self, *c, **kw):
95+
"Set children and/or attributes (chainable)"
96+
c,kw = _preproc(c,kw)
97+
if c: self.children = c
98+
if kw:
99+
self.attrs = {k:v for k,v in self.attrs.items() if k in ('id','name')}
100+
self.attrs = {**self.attrs, **kw}
101+
return self.changed()
96102

97103
# %% ../nbs/11_xml.ipynb
98104
def ft(tag:str, *c, void_:bool=False, attrmap:callable=attrmap, valmap:callable=valmap, ft_cls=FT, **kw):
@@ -175,7 +181,7 @@ def _to_xml(elm, lvl=0, indent=True, do_escape=True):
175181

176182
stag = tag
177183
if attrs:
178-
sattrs = ' '.join(_to_attr(k, v) for k, v in attrs.items() if v not in (False, None, ''))
184+
sattrs = ' '.join(_to_attr(k, v) for k, v in attrs.items() if v not in (False, None, '') and k[-1]!='_')
179185
if sattrs: stag += f' {sattrs}'
180186

181187
cltag = '' if is_void else f'</{tag}>'

nbs/11_xml.ipynb

+22-59
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,17 @@
134134
" def __init__(self, tag:str, cs:tuple, attrs:dict=None, void_=False, **kwargs):\n",
135135
" assert isinstance(cs, tuple)\n",
136136
" self.tag,self.children,self.attrs,self.void_ = tag,cs,attrs,void_\n",
137+
" self.listeners_ = []\n",
138+
" \n",
139+
" def on(self, f): self.listeners_.append(f)\n",
140+
" def changed(self):\n",
141+
" [f(self) for f in self.listeners_]\n",
142+
" return self\n",
137143
"\n",
138144
" def __setattr__(self, k, v):\n",
139-
" if k.startswith('__') or k in ('tag','children','attrs','void_'): return super().__setattr__(k,v)\n",
145+
" if k.startswith('__') or k[-1]=='_' or k in ('tag','children','attrs','void_'): return super().__setattr__(k,v)\n",
140146
" self.attrs[k.lstrip('_').replace('_', '-')] = v\n",
147+
" self.changed()\n",
141148
"\n",
142149
" def __getattr__(self, k):\n",
143150
" if k.startswith('__'): raise AttributeError(k)\n",
@@ -147,28 +154,27 @@
147154
" def list(self): return [self.tag,self.children,self.attrs]\n",
148155
" def get(self, k, default=None): return self.attrs.get(k.lstrip('_').replace('_', '-'), default)\n",
149156
" def __repr__(self): return f'{self.tag}({self.children},{self.attrs})'\n",
150-
"\n",
151-
" def __add__(self, b):\n",
152-
" self.children = self.children + tuplify(b)\n",
153-
" return self\n",
157+
" def __iter__(self): return iter(self.children)\n",
158+
" def __getitem__(self, idx): return self.children[idx]\n",
154159
" \n",
155160
" def __setitem__(self, i, o):\n",
156161
" self.children = self.children[:i] + (o,) + self.children[i+1:]\n",
157-
"\n",
158-
" def __getitem__(self, idx): return self.children[idx]\n",
159-
" def __iter__(self): return iter(self.children)\n",
162+
" self.changed()\n",
160163
"\n",
161164
" def __call__(self, *c, **kw):\n",
162165
" c,kw = _preproc(c,kw)\n",
163-
" if c: self = self+c\n",
166+
" if c: self.children = self.children+c\n",
164167
" if kw: self.attrs = {**self.attrs, **kw}\n",
165-
" return self\n",
168+
" return self.changed()\n",
166169
"\n",
167-
" def set(self, *o, **k):\n",
168-
" \"Set children and/or attributes—chainable\"\n",
169-
" if o: self.children = o\n",
170-
" for k,v in k.items(): setattr(self,k,v)\n",
171-
" return self"
170+
" def set(self, *c, **kw):\n",
171+
" \"Set children and/or attributes (chainable)\"\n",
172+
" c,kw = _preproc(c,kw)\n",
173+
" if c: self.children = c\n",
174+
" if kw:\n",
175+
" self.attrs = {k:v for k,v in self.attrs.items() if k in ('id','name')}\n",
176+
" self.attrs = {**self.attrs, **kw}\n",
177+
" return self.changed()"
172178
]
173179
},
174180
{
@@ -207,49 +213,6 @@
207213
"for o in _all_: _g[o] = partial(ft, o.lower(), void_=o.lower() in voids)"
208214
]
209215
},
210-
{
211-
"cell_type": "code",
212-
"execution_count": null,
213-
"id": "306844ba",
214-
"metadata": {},
215-
"outputs": [
216-
{
217-
"data": {
218-
"text/plain": [
219-
"body((div(('hi',),{'a': 1, 'b': True, 'class': None}), p(('hi',),{'class': 'a 1', 'style': 'a:1; b:2'})),{})"
220-
]
221-
},
222-
"execution_count": null,
223-
"metadata": {},
224-
"output_type": "execute_result"
225-
}
226-
],
227-
"source": [
228-
"a = Body(Div('hi', a=1, b=True, cls=()), P('hi', cls=['a',1], style=dict(a=1,b=2)))\n",
229-
"a"
230-
]
231-
},
232-
{
233-
"cell_type": "code",
234-
"execution_count": null,
235-
"id": "500f358a",
236-
"metadata": {},
237-
"outputs": [
238-
{
239-
"data": {
240-
"text/plain": [
241-
"body((div(('hi',),{'a': 1, 'b': True, 'class': None}), p(('hi',),{'class': 'a 1', 'style': 'a:1; b:2'}), p(('a',),{}), p(('b',),{})),{})"
242-
]
243-
},
244-
"execution_count": null,
245-
"metadata": {},
246-
"output_type": "execute_result"
247-
}
248-
],
249-
"source": [
250-
"a + (P('a'),P('b'))"
251-
]
252-
},
253216
{
254217
"cell_type": "markdown",
255218
"id": "732e44ab",
@@ -462,7 +425,7 @@
462425
"\n",
463426
" stag = tag\n",
464427
" if attrs:\n",
465-
" sattrs = ' '.join(_to_attr(k, v) for k, v in attrs.items() if v not in (False, None, ''))\n",
428+
" sattrs = ' '.join(_to_attr(k, v) for k, v in attrs.items() if v not in (False, None, '') and k[-1]!='_')\n",
466429
" if sattrs: stag += f' {sattrs}'\n",
467430
"\n",
468431
" cltag = '' if is_void else f'</{tag}>'\n",

settings.ini

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ author = Jeremy Howard and Sylvain Gugger
88
author_email = infos@fast.ai
99
copyright = fast.ai
1010
branch = master
11-
version = 1.7.16
11+
version = 1.7.17
1212
min_python = 3.8
1313
audience = Developers
1414
language = English

0 commit comments

Comments
 (0)