|
a |
|
b/ipynb/notebook2script.py |
|
|
1 |
#!/usr/bin/env python |
|
|
2 |
|
|
|
3 |
import json,fire,re |
|
|
4 |
from pathlib import Path |
|
|
5 |
|
|
|
6 |
def is_export(cell): |
|
|
7 |
if cell['cell_type'] != 'code': return False |
|
|
8 |
src = cell['source'] |
|
|
9 |
if len(src) == 0 or len(src[0]) < 7: return False |
|
|
10 |
#import pdb; pdb.set_trace() |
|
|
11 |
return re.match(r'^\s*#\s*export\s*$', src[0], re.IGNORECASE) is not None |
|
|
12 |
|
|
|
13 |
def getSortedFiles(allFiles, upTo=None): |
|
|
14 |
'''Returns all the notebok files sorted by name. |
|
|
15 |
allFiles = True : returns all files |
|
|
16 |
= '*_*.ipynb' : returns this pattern |
|
|
17 |
upTo = None : no upper limit |
|
|
18 |
= filter : returns all files up to 'filter' included |
|
|
19 |
The sorting optioj is important to ensure that the notebok are executed in correct order. |
|
|
20 |
''' |
|
|
21 |
import glob |
|
|
22 |
ret = [] |
|
|
23 |
if (allFiles==True): ret = glob.glob('*.ipynb') # Checks both that is bool type and that is True |
|
|
24 |
if (isinstance(allFiles,str)): ret = glob.glob(allFiles) |
|
|
25 |
if 0==len(ret): |
|
|
26 |
print('WARNING: No files found') |
|
|
27 |
return ret |
|
|
28 |
if upTo is not None: ret = [f for f in ret if str(f)<=str(upTo)] |
|
|
29 |
return sorted(ret) |
|
|
30 |
|
|
|
31 |
def notebook2script(fname=None, allFiles=None, upTo=None): |
|
|
32 |
'''Finds cells starting with `#export` and puts them into a new module |
|
|
33 |
+ allFiles: convert all files in the folder |
|
|
34 |
+ upTo: convert files up to specified one included |
|
|
35 |
|
|
|
36 |
ES: |
|
|
37 |
notebook2script --allFiles=True # Parse all files |
|
|
38 |
notebook2script --allFiles=nb* # Parse all files starting with nb* |
|
|
39 |
notebook2script --upTo=10 # Parse all files with (name<='10') |
|
|
40 |
notebook2script --allFiles=*_*.ipynb --upTo=10 # Parse all files with an '_' and (name<='10') |
|
|
41 |
''' |
|
|
42 |
# initial checks |
|
|
43 |
if (allFiles is None) and (upTo is not None): allFiles=True # Enable allFiles if upTo is present |
|
|
44 |
if (fname is None) and (not allFiles): print('Should provide a file name') |
|
|
45 |
if not allFiles: notebook2scriptSingle(fname) |
|
|
46 |
else: |
|
|
47 |
print('Begin...') |
|
|
48 |
[notebook2scriptSingle(f) for f in getSortedFiles(allFiles,upTo)] |
|
|
49 |
print('...End') |
|
|
50 |
|
|
|
51 |
|
|
|
52 |
def notebook2scriptSingle(fname): |
|
|
53 |
"Finds cells starting with `#export` and puts them into a new module" |
|
|
54 |
fname = Path(fname) |
|
|
55 |
fname_out = f'nb_{fname.stem.split("_")[0]}.py' |
|
|
56 |
main_dic = json.load(open(fname,'r')) |
|
|
57 |
code_cells = [c for c in main_dic['cells'] if is_export(c)] |
|
|
58 |
module = f''' |
|
|
59 |
################################################# |
|
|
60 |
### THIS FILE WAS AUTOGENERATED! DO NOT EDIT! ### |
|
|
61 |
################################################# |
|
|
62 |
# file to edit: dev_nb/{fname.name} |
|
|
63 |
|
|
|
64 |
''' |
|
|
65 |
for cell in code_cells: module += ''.join(cell['source'][1:]) + '\n\n' |
|
|
66 |
# remove trailing spaces |
|
|
67 |
module = re.sub(r' +$', '', module, flags=re.MULTILINE) |
|
|
68 |
output_path = fname.parent/'../exp'/fname_out |
|
|
69 |
print (output_path) |
|
|
70 |
open(output_path,'w').write(module[:-2]) |
|
|
71 |
print(f"Converted {fname} to {output_path}") |
|
|
72 |
|
|
|
73 |
if __name__ == '__main__': fire.Fire(notebook2script) |
|
|
74 |
|