Skip to content

Commit 89ffc8b

Browse files
committed
xml tuple
1 parent bed9cba commit 89ffc8b

File tree

5 files changed

+71
-23
lines changed

5 files changed

+71
-23
lines changed

fastcore/_modidx.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,7 @@
411411
'fastcore.parallel.parallel_gen': ('parallel.html#parallel_gen', 'fastcore/parallel.py'),
412412
'fastcore.parallel.parallelable': ('parallel.html#parallelable', 'fastcore/parallel.py'),
413413
'fastcore.parallel.run_procs': ('parallel.html#run_procs', 'fastcore/parallel.py'),
414+
'fastcore.parallel.startproc': ('parallel.html#startproc', 'fastcore/parallel.py'),
414415
'fastcore.parallel.startthread': ('parallel.html#startthread', 'fastcore/parallel.py'),
415416
'fastcore.parallel.threaded': ('parallel.html#threaded', 'fastcore/parallel.py')},
416417
'fastcore.script': { 'fastcore.script.Param': ('script.html#param', 'fastcore/script.py'),

fastcore/parallel.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/03a_parallel.ipynb.
22

33
# %% auto 0
4-
__all__ = ['threaded', 'startthread', 'parallelable', 'ThreadPoolExecutor', 'ProcessPoolExecutor', 'parallel', 'add_one',
5-
'run_procs', 'parallel_gen']
4+
__all__ = ['threaded', 'startthread', 'startproc', 'parallelable', 'ThreadPoolExecutor', 'ProcessPoolExecutor', 'parallel',
5+
'add_one', 'run_procs', 'parallel_gen']
66

77
# %% ../nbs/03a_parallel.ipynb 1
88
from .imports import *
@@ -38,9 +38,14 @@ def _f(*args, **kwargs):
3838
# %% ../nbs/03a_parallel.ipynb 6
3939
def startthread(f):
4040
"Like `threaded`, but start thread immediately"
41-
threaded(f)()
41+
return threaded(f)()
4242

4343
# %% ../nbs/03a_parallel.ipynb 8
44+
def startproc(f):
45+
"Like `threaded(True)`, but start Process immediately"
46+
return threaded(True)(f)()
47+
48+
# %% ../nbs/03a_parallel.ipynb 10
4449
def _call(lock, pause, n, g, item):
4550
l = False
4651
if pause:
@@ -51,7 +56,7 @@ def _call(lock, pause, n, g, item):
5156
if l: lock.release()
5257
return g(item)
5358

54-
# %% ../nbs/03a_parallel.ipynb 9
59+
# %% ../nbs/03a_parallel.ipynb 11
5560
def parallelable(param_name, num_workers, f=None):
5661
f_in_main = f == None or sys.modules[f.__module__].__name__ == "__main__"
5762
if sys.platform == "win32" and IN_NOTEBOOK and num_workers > 0 and f_in_main:
@@ -60,7 +65,7 @@ def parallelable(param_name, num_workers, f=None):
6065
return False
6166
return True
6267

63-
# %% ../nbs/03a_parallel.ipynb 10
68+
# %% ../nbs/03a_parallel.ipynb 12
6469
class ThreadPoolExecutor(concurrent.futures.ThreadPoolExecutor):
6570
"Same as Python's ThreadPoolExecutor, except can pass `max_workers==0` for serial execution"
6671
def __init__(self, max_workers=defaults.cpus, on_exc=print, pause=0, **kwargs):
@@ -78,7 +83,7 @@ def map(self, f, items, *args, timeout=None, chunksize=1, **kwargs):
7883
try: return super().map(_g, items, timeout=timeout, chunksize=chunksize)
7984
except Exception as e: self.on_exc(e)
8085

81-
# %% ../nbs/03a_parallel.ipynb 12
86+
# %% ../nbs/03a_parallel.ipynb 14
8287
@delegates()
8388
class ProcessPoolExecutor(concurrent.futures.ProcessPoolExecutor):
8489
"Same as Python's ProcessPoolExecutor, except can pass `max_workers==0` for serial execution"
@@ -101,11 +106,11 @@ def map(self, f, items, *args, timeout=None, chunksize=1, **kwargs):
101106
try: return super().map(_g, items, timeout=timeout, chunksize=chunksize)
102107
except Exception as e: self.on_exc(e)
103108

104-
# %% ../nbs/03a_parallel.ipynb 14
109+
# %% ../nbs/03a_parallel.ipynb 16
105110
try: from fastprogress import progress_bar
106111
except: progress_bar = None
107112

108-
# %% ../nbs/03a_parallel.ipynb 15
113+
# %% ../nbs/03a_parallel.ipynb 17
109114
def parallel(f, items, *args, n_workers=defaults.cpus, total=None, progress=None, pause=0,
110115
method=None, threadpool=False, timeout=None, chunksize=1, **kwargs):
111116
"Applies `func` in parallel to `items`, using `n_workers`"
@@ -122,28 +127,28 @@ def parallel(f, items, *args, n_workers=defaults.cpus, total=None, progress=None
122127
r = progress_bar(r, total=total, leave=False)
123128
return L(r)
124129

125-
# %% ../nbs/03a_parallel.ipynb 16
130+
# %% ../nbs/03a_parallel.ipynb 18
126131
def add_one(x, a=1):
127132
# this import is necessary for multiprocessing in notebook on windows
128133
import random
129134
time.sleep(random.random()/80)
130135
return x+a
131136

132-
# %% ../nbs/03a_parallel.ipynb 22
137+
# %% ../nbs/03a_parallel.ipynb 24
133138
def run_procs(f, f_done, args):
134139
"Call `f` for each item in `args` in parallel, yielding `f_done`"
135140
processes = L(args).map(Process, args=arg0, target=f)
136141
for o in processes: o.start()
137142
yield from f_done()
138143
processes.map(Self.join())
139144

140-
# %% ../nbs/03a_parallel.ipynb 23
145+
# %% ../nbs/03a_parallel.ipynb 25
141146
def _f_pg(obj, queue, batch, start_idx):
142147
for i,b in enumerate(obj(batch)): queue.put((start_idx+i,b))
143148

144149
def _done_pg(queue, items): return (queue.get() for _ in items)
145150

146-
# %% ../nbs/03a_parallel.ipynb 24
151+
# %% ../nbs/03a_parallel.ipynb 26
147152
def parallel_gen(cls, items, n_workers=defaults.cpus, **kwargs):
148153
"Instantiate `cls` in `n_workers` procs & call each on a subset of `items` in parallel."
149154
if not parallelable('n_workers', n_workers): n_workers = 0

fastcore/xml.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,19 @@
1313
from .utils import *
1414

1515
import types
16-
from dataclasses import dataclass
1716
from functools import partial
1817
from html import escape
1918

2019
# %% ../nbs/11_xml.ipynb 4
2120
def _attrmap(o):
22-
return dict(cls='class', klass='class', fr='for').get(o, o)
21+
o = dict(htmlClass='class', cls='class', klass='class', fr='for', htmlFor='for').get(o, o)
22+
return o.lstrip('_').replace('_', '-')
2323

2424
# %% ../nbs/11_xml.ipynb 5
2525
def xt(tag:str, *c, **kw):
2626
"Create an XML tag structure `[tag,children,attrs]` for `toxml()`"
2727
if len(c)==1 and isinstance(c[0], types.GeneratorType): c = tuple(c[0])
28-
kw = {_attrmap(k.lstrip('_')):str(v) for k,v in kw.items()}
28+
kw = {_attrmap(k):str(v) for k,v in kw.items()}
2929
return [tag.lower(),c,kw]
3030

3131
# %% ../nbs/11_xml.ipynb 6
@@ -45,6 +45,7 @@ def xt(tag:str, *c, **kw):
4545
# %% ../nbs/11_xml.ipynb 9
4646
def to_xml(elm, lvl=0):
4747
"Convert `xt` element tree into an XML string"
48+
if isinstance(elm, tuple): return '\n'.join(to_xml(o) for o in elm)
4849
if hasattr(elm, '__xt__'): elm = elm.__xt__()
4950
sp = ' ' * lvl
5051
if not isinstance(elm, list):
@@ -54,11 +55,11 @@ def to_xml(elm, lvl=0):
5455
tag,cs,attrs = elm
5556
stag = tag
5657
if attrs:
57-
sattrs = (f'{k}="{escape(str(v))}"' for k,v in attrs.items())
58+
sattrs = (f'{k}="{escape(str(v), quote=False)}"' for k,v in attrs.items())
5859
stag += ' ' + ' '.join(sattrs)
5960

6061
if not cs: return f'{sp}<{stag}></{tag}>\n'
6162
res = f'{sp}<{stag}>\n'
62-
res += ''.join(to_xml(c, lvl+2) for c in cs)
63+
res += ''.join(to_xml(c, lvl=lvl+2) for c in cs)
6364
res += f'{sp}</{tag}>\n'
6465
return res

nbs/03a_parallel.ipynb

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@
113113
"#|export\n",
114114
"def startthread(f):\n",
115115
" \"Like `threaded`, but start thread immediately\"\n",
116-
" threaded(f)()"
116+
" return threaded(f)()"
117117
]
118118
},
119119
{
@@ -144,6 +144,46 @@
144144
"time.sleep(0.1)"
145145
]
146146
},
147+
{
148+
"cell_type": "code",
149+
"execution_count": null,
150+
"metadata": {},
151+
"outputs": [],
152+
"source": [
153+
"#|export\n",
154+
"def startproc(f):\n",
155+
" \"Like `threaded(True)`, but start Process immediately\"\n",
156+
" return threaded(True)(f)()"
157+
]
158+
},
159+
{
160+
"cell_type": "code",
161+
"execution_count": null,
162+
"metadata": {},
163+
"outputs": [
164+
{
165+
"name": "stdout",
166+
"output_type": "stream",
167+
"text": [
168+
"first\n",
169+
"second\n"
170+
]
171+
}
172+
],
173+
"source": [
174+
"@startproc\n",
175+
"def _():\n",
176+
" time.sleep(0.05)\n",
177+
" print(\"second\")\n",
178+
"\n",
179+
"@startproc\n",
180+
"def _():\n",
181+
" time.sleep(0.01)\n",
182+
" print(\"first\")\n",
183+
"\n",
184+
"time.sleep(0.1)"
185+
]
186+
},
147187
{
148188
"cell_type": "code",
149189
"execution_count": null,

nbs/11_xml.ipynb

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
"from fastcore.utils import *\n",
3232
"\n",
3333
"import types\n",
34-
"from dataclasses import dataclass\n",
3534
"from functools import partial\n",
3635
"from html import escape"
3736
]
@@ -55,7 +54,8 @@
5554
"source": [
5655
"#| export\n",
5756
"def _attrmap(o):\n",
58-
" return dict(cls='class', klass='class', fr='for').get(o, o)"
57+
" o = dict(htmlClass='class', cls='class', klass='class', fr='for', htmlFor='for').get(o, o)\n",
58+
" return o.lstrip('_').replace('_', '-')"
5959
]
6060
},
6161
{
@@ -69,7 +69,7 @@
6969
"def xt(tag:str, *c, **kw):\n",
7070
" \"Create an XML tag structure `[tag,children,attrs]` for `toxml()`\"\n",
7171
" if len(c)==1 and isinstance(c[0], types.GeneratorType): c = tuple(c[0])\n",
72-
" kw = {_attrmap(k.lstrip('_')):str(v) for k,v in kw.items()}\n",
72+
" kw = {_attrmap(k):str(v) for k,v in kw.items()}\n",
7373
" return [tag.lower(),c,kw]"
7474
]
7575
},
@@ -147,6 +147,7 @@
147147
"#| export\n",
148148
"def to_xml(elm, lvl=0):\n",
149149
" \"Convert `xt` element tree into an XML string\"\n",
150+
" if isinstance(elm, tuple): return '\\n'.join(to_xml(o) for o in elm)\n",
150151
" if hasattr(elm, '__xt__'): elm = elm.__xt__()\n",
151152
" sp = ' ' * lvl\n",
152153
" if not isinstance(elm, list):\n",
@@ -156,12 +157,12 @@
156157
" tag,cs,attrs = elm\n",
157158
" stag = tag\n",
158159
" if attrs:\n",
159-
" sattrs = (f'{k}=\"{escape(str(v))}\"' for k,v in attrs.items())\n",
160+
" sattrs = (f'{k}=\"{escape(str(v), quote=False)}\"' for k,v in attrs.items())\n",
160161
" stag += ' ' + ' '.join(sattrs)\n",
161162
" \n",
162163
" if not cs: return f'{sp}<{stag}></{tag}>\\n'\n",
163164
" res = f'{sp}<{stag}>\\n'\n",
164-
" res += ''.join(to_xml(c, lvl+2) for c in cs)\n",
165+
" res += ''.join(to_xml(c, lvl=lvl+2) for c in cs)\n",
165166
" res += f'{sp}</{tag}>\\n'\n",
166167
" return res"
167168
]

0 commit comments

Comments
 (0)