Skip to content

Commit b57476b

Browse files
committed
fixes #124
1 parent 05641ae commit b57476b

File tree

6 files changed

+65
-24
lines changed

6 files changed

+65
-24
lines changed

fastcore/_nbdev.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@
137137
"parallel": "02_utils.ipynb",
138138
"run_procs": "02_utils.ipynb",
139139
"parallel_gen": "02_utils.ipynb",
140+
"threaded": "02_utils.ipynb",
140141
"type_hints": "03_dispatch.ipynb",
141142
"anno_ret": "03_dispatch.ipynb",
142143
"sorted_topologically": "03_dispatch.ipynb",

fastcore/foundation.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ class Config:
448448
def __init__(self, cfg_name='settings.ini'):
449449
cfg_path = Path.cwd()
450450
while cfg_path != cfg_path.parent and not (cfg_path/cfg_name).exists(): cfg_path = cfg_path.parent
451-
self.config_file = cfg_path/cfg_name
451+
self.config_path,self.config_file = cfg_path,cfg_path/cfg_name
452452
assert self.config_file.exists(), f"Could not find {cfg_name}"
453453
self.d = read_config_file(self.config_file)['DEFAULT']
454454
_add_new_defaults(self.d, self.config_file,
@@ -462,4 +462,4 @@ def __getattr__(self,k): return stop(AttributeError(k)) if k=='d' or k not in
462462
def get(self,k,default=None):
463463
v = self.d.get(k, default)
464464
if v is None: return v
465-
return self.config_file.parent/v if k.endswith('_path') else v
465+
return self.config_path/v if k.endswith('_path') else v

fastcore/utils.py

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
'Self', 'Self', 'save_pickle', 'load_pickle', 'bunzip', 'join_path_file', 'urlread', 'urljson', 'run',
1111
'do_request', 'sort_by_run', 'PrettyString', 'round_multiple', 'even_mults', 'num_cpus', 'add_props',
1212
'ContextManagers', 'set_num_threads', 'ProcessPoolExecutor', 'ThreadPoolExecutor', 'parallel', 'run_procs',
13-
'parallel_gen']
13+
'parallel_gen', 'threaded']
1414

1515
# Cell
1616
from .imports import *
@@ -23,6 +23,7 @@
2323
from urllib.request import Request,urlopen
2424
from urllib.error import HTTPError
2525
from urllib.parse import urlencode
26+
from threading import Thread
2627

2728
# Cell
2829
def ifnone(a, b):
@@ -570,18 +571,22 @@ def join_path_file(file, path, ext=''):
570571
return path/f'{file}{ext}'
571572

572573
# Cell
573-
def urlread(url):
574-
"Retrieve `url`"
575-
with urlopen(url) as res: return res.read()
574+
def urlread(url, data=None, **kwargs):
575+
"Retrieve `url`, using `data` dict or `kwargs` to `POST` if present"
576+
if kwargs and not data: data=kwargs
577+
if data is not None:
578+
if not isinstance(data, (str,bytes)): data = urlencode(data)
579+
if not isinstance(data, bytes): data = data.encode('ascii')
580+
with urlopen(url, data=data) as res: return res.read()
576581

577582
# Cell
578-
def urljson(url):
583+
def urljson(url, data=None):
579584
"Retrieve `url` and decode json"
580-
return json.loads(urlread(url))
585+
return json.loads(urlread(url, data=data))
581586

582587
# Cell
583588
def run(cmd, *rest, ignore_ex=False, as_bytes=False):
584-
"Pass `cmd` (splitting with `shlex` if string) to `subprocess.run`, returning `stdout`, or raise `IOError` on failure"
589+
"Pass `cmd` (splitting with `shlex` if string) to `subprocess.run`; return `stdout`; raise `IOError` if fails"
585590
if rest: cmd = (cmd,)+rest
586591
elif isinstance(cmd,str): cmd = shlex.split(cmd)
587592
res = subprocess.run(cmd, capture_output=True)
@@ -777,4 +782,14 @@ def parallel_gen(cls, items, n_workers=defaults.cpus, **kwargs):
777782
if progress_bar: items = progress_bar(items, leave=False)
778783
f=partial(_f_pg, cls(**kwargs), queue)
779784
done=partial(_done_pg, queue, items)
780-
yield from run_procs(f, done, L(batches,idx).zip())
785+
yield from run_procs(f, done, L(batches,idx).zip())
786+
787+
# Cell
788+
def threaded(f):
789+
"Run `f` in a thread, and returns the thread"
790+
@wraps(f)
791+
def _f(*args, **kwargs):
792+
res = Thread(target=f, args=args, kwargs=kwargs)
793+
res.start()
794+
return res
795+
return _f

nbs/01_foundation.ipynb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3104,7 +3104,7 @@
31043104
" def __init__(self, cfg_name='settings.ini'):\n",
31053105
" cfg_path = Path.cwd()\n",
31063106
" while cfg_path != cfg_path.parent and not (cfg_path/cfg_name).exists(): cfg_path = cfg_path.parent\n",
3107-
" self.config_file = cfg_path/cfg_name\n",
3107+
" self.config_path,self.config_file = cfg_path,cfg_path/cfg_name\n",
31083108
" assert self.config_file.exists(), f\"Could not find {cfg_name}\"\n",
31093109
" self.d = read_config_file(self.config_file)['DEFAULT']\n",
31103110
" _add_new_defaults(self.d, self.config_file,\n",
@@ -3118,7 +3118,7 @@
31183118
" def get(self,k,default=None):\n",
31193119
" v = self.d.get(k, default)\n",
31203120
" if v is None: return v\n",
3121-
" return self.config_file.parent/v if k.endswith('_path') else v"
3121+
" return self.config_path/v if k.endswith('_path') else v"
31223122
]
31233123
},
31243124
{

nbs/02_utils.ipynb

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
"from pdb import set_trace\n",
2626
"from urllib.request import Request,urlopen\n",
2727
"from urllib.error import HTTPError\n",
28-
"from urllib.parse import urlencode"
28+
"from urllib.parse import urlencode\n",
29+
"from threading import Thread"
2930
]
3031
},
3132
{
@@ -295,7 +296,7 @@
295296
{
296297
"data": {
297298
"text/plain": [
298-
"<__main__._t at 0x7fbd249d4100>"
299+
"<__main__._t at 0x7ff9a9c3deb0>"
299300
]
300301
},
301302
"execution_count": null,
@@ -2170,7 +2171,7 @@
21702171
{
21712172
"data": {
21722173
"text/plain": [
2173-
"['c', 'h', 'g', 'd', 'f', 'e', 'a', 'b']"
2174+
"['g', 'd', 'h', 'a', 'f', 'c', 'b', 'e']"
21742175
]
21752176
},
21762177
"execution_count": null,
@@ -2929,7 +2930,7 @@
29292930
{
29302931
"data": {
29312932
"text/plain": [
2932-
"Path('.ipynb_checkpoints')"
2933+
"Path('.gitattributes')"
29332934
]
29342935
},
29352936
"execution_count": null,
@@ -2963,7 +2964,7 @@
29632964
{
29642965
"data": {
29652966
"text/plain": [
2966-
"(Path('../fastcore/logargs.py'), Path('04_transform.ipynb'))"
2967+
"(Path('../fastcore/all.py'), Path('00_test.ipynb'))"
29672968
]
29682969
},
29692970
"execution_count": null,
@@ -3147,9 +3148,13 @@
31473148
"outputs": [],
31483149
"source": [
31493150
"#export\n",
3150-
"def urlread(url):\n",
3151-
" \"Retrieve `url`\"\n",
3152-
" with urlopen(url) as res: return res.read()"
3151+
"def urlread(url, data=None, **kwargs):\n",
3152+
" \"Retrieve `url`, using `data` dict or `kwargs` to `POST` if present\"\n",
3153+
" if kwargs and not data: data=kwargs\n",
3154+
" if data is not None:\n",
3155+
" if not isinstance(data, (str,bytes)): data = urlencode(data)\n",
3156+
" if not isinstance(data, bytes): data = data.encode('ascii')\n",
3157+
" with urlopen(url, data=data) as res: return res.read()"
31533158
]
31543159
},
31553160
{
@@ -3159,9 +3164,9 @@
31593164
"outputs": [],
31603165
"source": [
31613166
"#export\n",
3162-
"def urljson(url):\n",
3167+
"def urljson(url, data=None):\n",
31633168
" \"Retrieve `url` and decode json\"\n",
3164-
" return json.loads(urlread(url))"
3169+
" return json.loads(urlread(url, data=data))"
31653170
]
31663171
},
31673172
{
@@ -3172,7 +3177,7 @@
31723177
"source": [
31733178
"#export\n",
31743179
"def run(cmd, *rest, ignore_ex=False, as_bytes=False):\n",
3175-
" \"Pass `cmd` (splitting with `shlex` if string) to `subprocess.run`, returning `stdout`, or raise `IOError` on failure\"\n",
3180+
" \"Pass `cmd` (splitting with `shlex` if string) to `subprocess.run`; return `stdout`; raise `IOError` if fails\"\n",
31763181
" if rest: cmd = (cmd,)+rest\n",
31773182
" elif isinstance(cmd,str): cmd = shlex.split(cmd)\n",
31783183
" res = subprocess.run(cmd, capture_output=True)\n",
@@ -4013,6 +4018,23 @@
40134018
"test_eq(res.sorted().itemgot(1), x+1)"
40144019
]
40154020
},
4021+
{
4022+
"cell_type": "code",
4023+
"execution_count": null,
4024+
"metadata": {},
4025+
"outputs": [],
4026+
"source": [
4027+
"#export\n",
4028+
"def threaded(f):\n",
4029+
" \"Run `f` in a thread, and returns the thread\"\n",
4030+
" @wraps(f)\n",
4031+
" def _f(*args, **kwargs):\n",
4032+
" res = Thread(target=f, args=args, kwargs=kwargs)\n",
4033+
" res.start()\n",
4034+
" return res\n",
4035+
" return _f"
4036+
]
4037+
},
40164038
{
40174039
"cell_type": "markdown",
40184040
"metadata": {},

setup.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@
5555
long_description = long_description,
5656
long_description_content_type = 'text/markdown',
5757
zip_safe = False,
58-
entry_points = { 'console_scripts': cfg.get('console_scripts','').split() },
58+
entry_points = {
59+
'console_scripts': cfg.get('console_scripts','').split(),
60+
'nbdev': [f'index={cfg["lib_name"]}._nbdev']
61+
},
5962
**setup_cfg)
6063

0 commit comments

Comments
 (0)