Skip to content

Commit a552322

Browse files
committed
directives
1 parent 6a8e354 commit a552322

File tree

7 files changed

+471
-326
lines changed

7 files changed

+471
-326
lines changed

nbprocess/export.py

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

33
# %% auto 0
4-
__all__ = ['ExportModuleProc', 'rm_comments_proc', 'create_modules', 'nb_export', 'nbs_export']
4+
__all__ = ['ExportModuleProc', 'create_modules', 'nb_export', 'nbs_export']
55

66
# %% ../nbs/03_export.ipynb 3
77
from .read import *
@@ -14,9 +14,6 @@
1414
from fastcore.xtras import *
1515

1616
from collections import defaultdict
17-
from pprint import pformat
18-
from inspect import signature,Parameter
19-
import ast,contextlib,copy
2017

2118
# %% ../nbs/03_export.ipynb 5
2219
class ExportModuleProc:
@@ -29,28 +26,23 @@ def _export_(self, nbp, exp_to=None):
2926
self.in_all[ifnone(exp_to, '#')].append(nbp.cell)
3027

3128
# %% ../nbs/03_export.ipynb 8
32-
def rm_comments_proc(cell):
33-
"A proc that removes comments from each NB cell source"
34-
cell.source = ''.join(cell.source.splitlines(True)[len(cell._comments):])
35-
36-
# %% ../nbs/03_export.ipynb 9
3729
def create_modules(path, dest, procs=None, debug=False, mod_maker=ModuleMaker):
3830
"Create module(s) from notebook"
3931
exp = ExportModuleProc()
40-
nb = NBProcessor(path, [exp,rm_comments_proc]+L(procs), debug=debug)
32+
nb = NBProcessor(path, [exp]+L(procs), debug=debug)
4133
nb.process()
4234
for mod,cells in exp.modules.items():
4335
all_cells = exp.in_all[mod]
4436
name = exp.default_exp if mod=='#' else mod
4537
mm = mod_maker(dest=dest, name=name, nb_path=path, is_new=mod=='#')
4638
mm.make(cells, all_cells)
4739

48-
# %% ../nbs/03_export.ipynb 16
40+
# %% ../nbs/03_export.ipynb 15
4941
def nb_export(nbname, lib_path=None):
5042
if lib_path is None: lib_path = get_config().lib_path
5143
create_modules(nbname, lib_path)
5244

53-
# %% ../nbs/03_export.ipynb 17
45+
# %% ../nbs/03_export.ipynb 16
5446
@call_parse
5547
def nbs_export(
5648
path:str=None, # path or filename

nbprocess/process.py

Lines changed: 22 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/02_process.ipynb.
22

33
# %% auto 0
4-
__all__ = ['extract_comments', 'opt_set', 'NBProcessor', 'inject_meta', 'show_meta', 'insert_warning', 'update_tags']
4+
__all__ = ['extract_directives', 'opt_set', 'NBProcessor']
55

66
# %% ../nbs/02_process.ipynb 3
77
#|export
@@ -18,31 +18,32 @@
1818
from inspect import signature,Parameter
1919
import ast,contextlib,copy
2020

21+
# %% ../nbs/02_process.ipynb 7
22+
#|export
23+
def _directive(s):
24+
s = (s.strip()[2:]).strip().split()
25+
if not s: return None
26+
direc,*args = s
27+
return direc,args
28+
2129
# %% ../nbs/02_process.ipynb 8
2230
#|export
23-
def extract_comments(ss):
24-
"Take leading comments from lines of code in `ss`, remove `#|`, and split"
25-
ss = ss.splitlines()
31+
def extract_directives(cell):
32+
"Take leading comment directives from lines of code in `ss`, remove `#|`, and split"
33+
ss = cell.source.splitlines(True)
2634
first_code = first(i for i,o in enumerate(ss) if not o.strip() or not re.match(r'\s*#\|', o))
27-
return L((s.strip()[2:]).strip().split() for s in ss[:first_code]).filter()
35+
if not ss or first_code==0: return {}
36+
cell['source'] = ''.join(ss[first_code:])
37+
res = L(_directive(s) for s in ss[:first_code]).filter()
38+
return {k:v for k,v in res}
2839

2940
# %% ../nbs/02_process.ipynb 11
3041
#|export
31-
@functools.lru_cache(maxsize=None)
32-
def _param_count(f):
33-
"Number of parameters accepted by function `f`"
34-
params = list(signature(f).parameters.values())
35-
# If there's a `*args` then `f` can take as many params as needed
36-
if first(params, lambda o: o.kind==Parameter.VAR_POSITIONAL): return 99
37-
return len([o for o in params if o.kind in (Parameter.POSITIONAL_ONLY,Parameter.POSITIONAL_OR_KEYWORD)])
38-
39-
# %% ../nbs/02_process.ipynb 12
40-
#|export
4142
def opt_set(var, newval):
4243
"newval if newval else var"
4344
return newval if newval else var
4445

45-
# %% ../nbs/02_process.ipynb 13
46+
# %% ../nbs/02_process.ipynb 12
4647
#|export
4748
class NBProcessor:
4849
"Process cells and nbdev comments in a notebook"
@@ -53,15 +54,15 @@ def __init__(self, path=None, procs=None, preprocs=None, postprocs=None, nb=None
5354

5455
def _process_cell(self, cell):
5556
self.cell = cell
56-
if not hasattr(cell, '_comments'): cell._comments = extract_comments(cell.source)
57+
cell['_directives'] = extract_directives(cell)
5758
for proc in self.procs:
58-
if cell.cell_type=='code': cell._comments.map(self._process_comment,proc)
59+
if cell.cell_type=='code':
60+
for cmd,args in cell._directives.items(): self._process_comment(proc, cmd, args)
5961
if callable(proc): cell = opt_set(cell, proc(cell))
6062

61-
def _process_comment(self, proc, comment):
62-
cmd,*args = comment
63+
def _process_comment(self, proc, cmd, args):
6364
f = getattr(proc, f'_{cmd}_', None)
64-
if not f or _param_count(f)-1<len(args): return True
65+
if not f: return True
6566
if self.debug: print(cmd, args, f)
6667
return f(self, *args)
6768

@@ -71,41 +72,3 @@ def process(self):
7172
for i in range_of(self.nb.cells): self._process_cell(self.nb.cells[i])
7273
self.nb.cells = [c for c in self.nb.cells if c and getattr(c,'source',None) is not None]
7374
for proc in self.postprocs: self.nb = opt_set(self.nb, proc(self.nb))
74-
75-
# %% ../nbs/02_process.ipynb 18
76-
#|export
77-
_re_meta= r'^\s*#(?:cell_meta|meta):\S+\s*[\n\r]'
78-
79-
def inject_meta(cell):
80-
"Inject metadata into a cell for further preprocessing with a comment."
81-
_pattern = r'(^\s*#(?:cell_meta|meta):)(\S+)(\s*[\n\r])'
82-
if cell.cell_type == 'code' and re.search(_re_meta, cell.source, flags=re.MULTILINE):
83-
cell_meta = re.findall(_pattern, cell.source, re.MULTILINE)
84-
d = cell.metadata.get('nbprocess', {})
85-
for _, m, _ in cell_meta:
86-
if '=' in m:
87-
k,v = m.split('=')
88-
d[k] = v
89-
else: print(f"Warning cell_meta:{m} does not have '=' will be ignored.")
90-
cell.metadata['nbprocess'] = d
91-
92-
# %% ../nbs/02_process.ipynb 19
93-
#|export
94-
def show_meta(cell):
95-
"Show cell metadata"
96-
meta = cell.metadata.get('nbprocess')
97-
if meta: print(meta)
98-
99-
# %% ../nbs/02_process.ipynb 25
100-
#| export
101-
def insert_warning(nb):
102-
"Insert Autogenerated Warning Into Notebook after the first cell."
103-
content = "<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->"
104-
nb.cells.insert(1, AttrDict(cell_type='markdown', metadata={}, source=content))
105-
106-
# %% ../nbs/02_process.ipynb 30
107-
#|export
108-
def update_tags(cell):
109-
root = cell.metadata.get('nbprocess', {})
110-
tags = root.get('tags', root.get('tag')) # allow the singular also
111-
if tags: cell.metadata['tags'] = cell.metadata.get('tags', []) + tags.split(',')

nbprocess/processors.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/07_processors.ipynb.
2+
3+
# %% auto 0
4+
__all__ = ['inject_meta', 'show_meta', 'insert_warning', 'update_tags']
5+
6+
# %% ../nbs/07_processors.ipynb 3
7+
from .read import *
8+
from .imports import *
9+
from .process import *
10+
11+
from fastcore.imports import *
12+
from fastcore.xtras import *
13+
14+
# %% ../nbs/07_processors.ipynb 7
15+
_re_meta= r'^\s*#(?:cell_meta|meta):\S+\s*[\n\r]'
16+
17+
def inject_meta(cell):
18+
"Inject metadata into a cell for further preprocessing with a comment."
19+
_pattern = r'(^\s*#(?:cell_meta|meta):)(\S+)(\s*[\n\r])'
20+
if cell.cell_type == 'code' and re.search(_re_meta, cell.source, flags=re.MULTILINE):
21+
cell_meta = re.findall(_pattern, cell.source, re.MULTILINE)
22+
d = cell.metadata.get('nbprocess', {})
23+
for _, m, _ in cell_meta:
24+
if '=' in m:
25+
k,v = m.split('=')
26+
d[k] = v
27+
else: print(f"Warning cell_meta:{m} does not have '=' will be ignored.")
28+
cell.metadata['nbprocess'] = d
29+
30+
# %% ../nbs/07_processors.ipynb 8
31+
def show_meta(cell):
32+
"Show cell metadata"
33+
meta = cell.metadata.get('nbprocess')
34+
if meta: print(meta)
35+
36+
# %% ../nbs/07_processors.ipynb 14
37+
def insert_warning(nb):
38+
"Insert Autogenerated Warning Into Notebook after the first cell."
39+
content = "<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->"
40+
nb.cells.insert(1, AttrDict(cell_type='markdown', metadata={}, source=content))
41+
42+
# %% ../nbs/07_processors.ipynb 19
43+
def update_tags(cell):
44+
root = cell.metadata.get('nbprocess', {})
45+
tags = root.get('tags', root.get('tag')) # allow the singular also
46+
if tags: cell.metadata['tags'] = cell.metadata.get('tags', []) + tags.split(',')

0 commit comments

Comments
 (0)