Skip to content

Commit fde17fc

Browse files
committed
fixes #575
1 parent 855a7be commit fde17fc

File tree

3 files changed

+54
-39
lines changed

3 files changed

+54
-39
lines changed

fastcore/_modidx.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,7 @@
564564
'fastcore.xml.XT.attrs': ('xml.html#xt.attrs', 'fastcore/xml.py'),
565565
'fastcore.xml.XT.children': ('xml.html#xt.children', 'fastcore/xml.py'),
566566
'fastcore.xml.XT.tag': ('xml.html#xt.tag', 'fastcore/xml.py'),
567+
'fastcore.xml.__getattr__': ('xml.html#__getattr__', 'fastcore/xml.py'),
567568
'fastcore.xml._attrmap': ('xml.html#_attrmap', 'fastcore/xml.py'),
568569
'fastcore.xml._escape': ('xml.html#_escape', 'fastcore/xml.py'),
569570
'fastcore.xml._to_attr': ('xml.html#_to_attr', 'fastcore/xml.py'),

fastcore/xml.py

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/11_xml.ipynb.
22

33
# %% auto 0
4-
__all__ = ['voids', 'XT', 'xt', 'to_xml', 'highlight', 'showtags', 'Html', 'Head', 'Title', 'Meta', 'Link', 'Style', 'Body',
5-
'Pre', 'Code', 'Div', 'Span', 'P', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'Strong', 'Em', 'B', 'I', 'U', 'S',
6-
'Strike', 'Sub', 'Sup', 'Hr', 'Br', 'Img', 'A', 'Nav', 'Ul', 'Ol', 'Li', 'Dl', 'Dt', 'Dd', 'Table', 'Thead',
7-
'Tbody', 'Tfoot', 'Tr', 'Th', 'Td', 'Caption', 'Col', 'Colgroup', 'Form', 'Input', 'Textarea', 'Button',
8-
'Select', 'Option', 'Label', 'Fieldset', 'Legend', 'Details', 'Summary', 'Main', 'Header', 'Footer',
9-
'Section', 'Article', 'Aside', 'Figure', 'Figcaption', 'Mark', 'Small', 'Iframe', 'Object', 'Embed', 'Param',
10-
'Video', 'Audio', 'Source', 'Canvas', 'Svg', 'Math', 'Script', 'Noscript', 'Template', 'Slot']
4+
__all__ = ['XT', 'xt', 'to_xml', 'highlight', 'showtags', 'Html', 'Head', 'Title', 'Meta', 'Link', 'Style', 'Body', 'Pre', 'Code',
5+
'Div', 'Span', 'P', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'Strong', 'Em', 'B', 'I', 'U', 'S', 'Strike', 'Sub',
6+
'Sup', 'Hr', 'Br', 'Img', 'A', 'Nav', 'Ul', 'Ol', 'Li', 'Dl', 'Dt', 'Dd', 'Table', 'Thead', 'Tbody', 'Tfoot',
7+
'Tr', 'Th', 'Td', 'Caption', 'Col', 'Colgroup', 'Form', 'Input', 'Textarea', 'Button', 'Select', 'Option',
8+
'Label', 'Fieldset', 'Legend', 'Details', 'Summary', 'Main', 'Header', 'Footer', 'Section', 'Article',
9+
'Aside', 'Figure', 'Figcaption', 'Mark', 'Small', 'Iframe', 'Object', 'Embed', 'Param', 'Video', 'Audio',
10+
'Source', 'Canvas', 'Svg', 'Math', 'Script', 'Noscript', 'Template', 'Slot']
1111

1212
# %% ../nbs/11_xml.ipynb 2
1313
from .utils import *
@@ -27,7 +27,10 @@ def _attrmap(o):
2727

2828
# %% ../nbs/11_xml.ipynb 5
2929
class XT(list):
30-
def __init__(self, tag, cs, attrs=None, **kwargs): super().__init__([tag, cs, {**(attrs or {}), **kwargs}])
30+
def __init__(self, tag, cs, attrs=None, void_=False, **kwargs):
31+
super().__init__([tag, cs, {**(attrs or {}), **kwargs}])
32+
self.void_ = void_
33+
3134
@property
3235
def tag(self): return self[0]
3336
@property
@@ -36,19 +39,19 @@ def children(self): return self[1]
3639
def attrs(self): return self[2]
3740

3841
def __setattr__(self, k, v):
39-
if k.startswith('__') or k in ('tag','cs','attrs'): return super().__setattr__(k,v)
42+
if k.startswith('__') or k in ('tag','cs','attrs','void_'): return super().__setattr__(k,v)
4043
self.attrs[k.lstrip('_').replace('_', '-')] = v
4144

4245
def __getattr__(self, k):
4346
if k.startswith('__') or k not in self.attrs: raise AttributeError(k)
4447
return self.attrs[k.lstrip('_').replace('_', '-')]
4548

4649
# %% ../nbs/11_xml.ipynb 6
47-
def xt(tag:str, *c, **kw):
50+
def xt(tag:str, *c, void_=False, **kw):
4851
"Create an XML tag structure `[tag,children,attrs]` for `toxml()`"
4952
if len(c)==1 and isinstance(c[0], types.GeneratorType): c = tuple(c[0])
5053
kw = {_attrmap(k):v for k,v in kw.items() if v is not None}
51-
return XT(tag.lower(),c,kw)
54+
return XT(tag.lower(),c,kw, void_=void_)
5255

5356
# %% ../nbs/11_xml.ipynb 7
5457
_g = globals()
@@ -65,12 +68,9 @@ def xt(tag:str, *c, **kw):
6568
for o in _all_: _g[o] = partial(xt, o.lower())
6669

6770
# %% ../nbs/11_xml.ipynb 14
68-
voids = set('area base br col command embed hr img input keygen link meta param source track wbr !doctype'.split())
69-
70-
# %% ../nbs/11_xml.ipynb 15
7171
def _escape(s): return '' if s is None else escape(s) if isinstance(s, str) else s
7272

73-
# %% ../nbs/11_xml.ipynb 16
73+
# %% ../nbs/11_xml.ipynb 15
7474
def _to_attr(k,v):
7575
if isinstance(v,bool):
7676
if v==True : return str(k)
@@ -82,7 +82,7 @@ def _to_attr(k,v):
8282
if qt in v: qt = "'"
8383
return f'{k}={qt}{v}{qt}'
8484

85-
# %% ../nbs/11_xml.ipynb 17
85+
# %% ../nbs/11_xml.ipynb 16
8686
def to_xml(elm, lvl=0):
8787
"Convert `xt` element tree into an XML string"
8888
if elm is None: return ''
@@ -97,24 +97,31 @@ def to_xml(elm, lvl=0):
9797
sattrs = (_to_attr(k,v) for k,v in attrs.items())
9898
stag += ' ' + ' '.join(sattrs)
9999

100-
cltag = '' if tag in voids else f'</{tag}>'
100+
isvoid = getattr(elm, 'void_', False)
101+
cltag = '' if isvoid else f'</{tag}>'
101102
if not cs: return f'{sp}<{stag}>{cltag}\n'
102103
if len(cs)==1 and not isinstance(cs[0],(list,tuple)) and not hasattr(cs[0],'__xt__'):
103104
return f'{sp}<{stag}>{_escape(cs[0])}{cltag}\n'
104105
res = f'{sp}<{stag}>\n'
105106
res += ''.join(to_xml(c, lvl=lvl+2) for c in cs)
106-
if tag not in voids: res += f'{sp}{cltag}\n'
107+
if not isvoid: res += f'{sp}{cltag}\n'
107108
return res
108109

109-
# %% ../nbs/11_xml.ipynb 19
110+
# %% ../nbs/11_xml.ipynb 18
110111
def highlight(s, lang='xml'):
111112
"Markdown to syntax-highlight `s` in language `lang`"
112113
return f'```{lang}\n{to_xml(s)}\n```'
113114

114-
# %% ../nbs/11_xml.ipynb 20
115+
# %% ../nbs/11_xml.ipynb 19
115116
def showtags(s):
116117
return f"""<code><pre>
117118
{escape(to_xml(s))}
118119
</code></pre>"""
119120

120121
XT._repr_markdown_ = highlight
122+
123+
# %% ../nbs/11_xml.ipynb 20
124+
def __getattr__(tag):
125+
if tag.startswith('_') or tag[0].islower(): raise AttributeError
126+
def _f(*c, target_id=None, **kwargs): return xt(tag, *c, target_id=target_id, **kwargs)
127+
return _f

nbs/11_xml.ipynb

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,10 @@
7272
"source": [
7373
"#|export\n",
7474
"class XT(list):\n",
75-
" def __init__(self, tag, cs, attrs=None, **kwargs): super().__init__([tag, cs, {**(attrs or {}), **kwargs}])\n",
75+
" def __init__(self, tag, cs, attrs=None, void_=False, **kwargs):\n",
76+
" super().__init__([tag, cs, {**(attrs or {}), **kwargs}])\n",
77+
" self.void_ = void_\n",
78+
"\n",
7679
" @property\n",
7780
" def tag(self): return self[0]\n",
7881
" @property\n",
@@ -81,7 +84,7 @@
8184
" def attrs(self): return self[2]\n",
8285
"\n",
8386
" def __setattr__(self, k, v):\n",
84-
" if k.startswith('__') or k in ('tag','cs','attrs'): return super().__setattr__(k,v)\n",
87+
" if k.startswith('__') or k in ('tag','cs','attrs','void_'): return super().__setattr__(k,v)\n",
8588
" self.attrs[k.lstrip('_').replace('_', '-')] = v\n",
8689
"\n",
8790
" def __getattr__(self, k):\n",
@@ -97,11 +100,11 @@
97100
"outputs": [],
98101
"source": [
99102
"#| export\n",
100-
"def xt(tag:str, *c, **kw):\n",
103+
"def xt(tag:str, *c, void_=False, **kw):\n",
101104
" \"Create an XML tag structure `[tag,children,attrs]` for `toxml()`\"\n",
102105
" if len(c)==1 and isinstance(c[0], types.GeneratorType): c = tuple(c[0])\n",
103106
" kw = {_attrmap(k):v for k,v in kw.items() if v is not None}\n",
104-
" return XT(tag.lower(),c,kw)"
107+
" return XT(tag.lower(),c,kw, void_=void_)"
105108
]
106109
},
107110
{
@@ -236,17 +239,6 @@
236239
"elem"
237240
]
238241
},
239-
{
240-
"cell_type": "code",
241-
"execution_count": null,
242-
"id": "c7de63a4",
243-
"metadata": {},
244-
"outputs": [],
245-
"source": [
246-
"#| export\n",
247-
"voids = set('area base br col command embed hr img input keygen link meta param source track wbr !doctype'.split())"
248-
]
249-
},
250242
{
251243
"cell_type": "code",
252244
"execution_count": null,
@@ -300,13 +292,14 @@
300292
" sattrs = (_to_attr(k,v) for k,v in attrs.items())\n",
301293
" stag += ' ' + ' '.join(sattrs)\n",
302294
"\n",
303-
" cltag = '' if tag in voids else f'</{tag}>'\n",
295+
" isvoid = getattr(elm, 'void_', False)\n",
296+
" cltag = '' if isvoid else f'</{tag}>'\n",
304297
" if not cs: return f'{sp}<{stag}>{cltag}\\n'\n",
305298
" if len(cs)==1 and not isinstance(cs[0],(list,tuple)) and not hasattr(cs[0],'__xt__'):\n",
306299
" return f'{sp}<{stag}>{_escape(cs[0])}{cltag}\\n'\n",
307300
" res = f'{sp}<{stag}>\\n'\n",
308301
" res += ''.join(to_xml(c, lvl=lvl+2) for c in cs)\n",
309-
" if tag not in voids: res += f'{sp}{cltag}\\n'\n",
302+
" if not isvoid: res += f'{sp}{cltag}\\n'\n",
310303
" return res"
311304
]
312305
},
@@ -327,8 +320,8 @@
327320
" <body>\n",
328321
" <div class=\"myclass\">\n",
329322
"Some text\n",
330-
" <input name=\"me\">\n",
331-
" <img src=\"filename\" data=\"1\">\n",
323+
" <input name=\"me\"></input>\n",
324+
" <img src=\"filename\" data=\"1\"></img>\n",
332325
" </div>\n",
333326
" </body>\n",
334327
"</html>\n",
@@ -370,6 +363,20 @@
370363
"XT._repr_markdown_ = highlight"
371364
]
372365
},
366+
{
367+
"cell_type": "code",
368+
"execution_count": null,
369+
"id": "530666f8",
370+
"metadata": {},
371+
"outputs": [],
372+
"source": [
373+
"#| export\n",
374+
"def __getattr__(tag):\n",
375+
" if tag.startswith('_') or tag[0].islower(): raise AttributeError\n",
376+
" def _f(*c, target_id=None, **kwargs): return xt(tag, *c, target_id=target_id, **kwargs)\n",
377+
" return _f"
378+
]
379+
},
373380
{
374381
"cell_type": "markdown",
375382
"id": "df973d4e",

0 commit comments

Comments
 (0)