Skip to content

Commit 2c65186

Browse files
committed
fix issues for fastai
1 parent 442ac3e commit 2c65186

22 files changed

+532
-230
lines changed

nbdev/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
__version__ = "2.0.1.dev3"
22

33
from .doclinks import nbdev_export
4+
from .showdoc import show_doc
5+

nbdev/_modidx.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@
146146
'nbdev.processors.is_frontmatter': 'https://nbdev.fast.ai/processors#is_frontmatter',
147147
'nbdev.processors.lang_identify': 'https://nbdev.fast.ai/processors#lang_identify',
148148
'nbdev.processors.nb_fmdict': 'https://nbdev.fast.ai/processors#nb_fmdict',
149+
'nbdev.processors.nbflags_': 'https://nbdev.fast.ai/processors#nbflags_',
149150
'nbdev.processors.populate_language': 'https://nbdev.fast.ai/processors#populate_language',
150151
'nbdev.processors.rm_export': 'https://nbdev.fast.ai/processors#rm_export',
151152
'nbdev.processors.rm_header_dash': 'https://nbdev.fast.ai/processors#rm_header_dash',

nbdev/cli.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def _nothing(self): return []
8686
def base_preprocs(self): return [populate_language, infer_frontmatter, add_show_docs, insert_warning]
8787
def base_postprocs(self): return []
8888
def base_procs(self):
89-
return [lang_identify, strip_ansi, hide_line, filter_stream_, rm_header_dash,
89+
return [nbflags_, lang_identify, strip_ansi, hide_line, filter_stream_, rm_header_dash,
9090
clean_show_doc, exec_show_docs, rm_export, clean_magics, hide_, add_links,
9191
strip_hidden_metadata]
9292

nbdev/doclinks.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ def write_nbdev_idx(self:DocLinks):
5252
# %% ../nbs/04b_doclinks.ipynb 15
5353
def _binop_leafs(bo, o):
5454
if isinstance(bo.left, ast.BinOp): left = _binop_leafs(bo.left, o)
55-
else: left = [f'{bo.left.id}.{o.name}']
55+
else: left = [f'{_id_or_attr(bo.left)}.{o.name}']
5656
if isinstance(bo.right, ast.BinOp): right = _binop_leafs(bo.right, o)
57-
else: right = [f'{bo.right.id}.{o.name}']
57+
else: right = [f'{_id_or_attr(bo.right)}.{o.name}']
5858
return concat(left + right)
5959

6060
# %% ../nbs/04b_doclinks.ipynb 16
@@ -68,14 +68,18 @@ def _get_patch(o):
6868
if not isinstance(o, (ast.FunctionDef,ast.AsyncFunctionDef)): return
6969
return first([d for d in o.decorator_list if decor_id(d).startswith('patch')])
7070

71+
def _id_or_attr(a):
72+
if hasattr(a, 'id'): return a.id
73+
return a.attr
74+
7175
def get_patch_name(o):
7276
d = _get_patch(o)
7377
if not d: return
7478
nm = decor_id(d)
7579
if nm=='patch':
7680
a = o.args.args[0].annotation
7781
if isinstance(a, ast.BinOp): return _binop_leafs(a, o)
78-
else: pre = a.id
82+
else: pre = _id_or_attr(a)
7983
elif nm=='patch_to': pre = o.decorator_list[0].args[0].id
8084
else: return
8185
return f'{pre}.{o.name}'
@@ -140,7 +144,7 @@ def nbdev_export(
140144
file_re:str=None, # Only include files matching regex
141145
folder_re:str=None, # Only enter folders matching regex
142146
skip_file_glob:str=None, # Skip files matching glob
143-
skip_file_re:str=None # Skip files matching regex
147+
skip_file_re:str='^[_.]' # Skip files matching regex
144148
):
145149
"Export notebooks in `path` to Python modules"
146150
if os.environ.get('IN_TEST',0): return

nbdev/process.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,19 +128,30 @@ class NBProcessor:
128128
def __init__(self, path=None, procs=None, preprocs=None, postprocs=None, nb=None, debug=False, rm_directives=True, process=False):
129129
self.nb = read_nb(path) if nb is None else nb
130130
self.lang = nb_lang(self.nb)
131+
for cell in self.nb.cells: cell.directives_ = extract_directives(cell, remove=rm_directives, lang=self.lang)
131132
self.procs,self.preprocs,self.postprocs = map_ex((procs,preprocs,postprocs), _mk_procs, nb=self.nb)
132133
self.debug,self.rm_directives = debug,rm_directives
133134
if process: self.process()
134135

135136
def _process_cell(self, cell):
136137
self.cell = cell
138+
cell.nb = self.nb
137139
for proc in self.procs:
140+
if not hasattr(cell,'source'): return
141+
if not hasattr(cell, 'directives_'):
142+
cell.nb=None
143+
raise Exception(cell)
138144
if cell.cell_type=='code' and cell.directives_:
139145
for cmd,args in cell.directives_.items():
140146
self._process_comment(proc, cell, cmd, args)
141147
if not hasattr(cell,'source'): return
142-
if callable(proc) and not _is_direc(proc): cell = opt_set(cell, proc(cell))
143-
if not hasattr(cell,'source'): return
148+
if callable(proc) and not _is_direc(proc):
149+
cell = opt_set(cell, proc(cell))
150+
# try: cell = opt_set(cell, proc(cell))
151+
# except:
152+
# cell.nb = None
153+
# raise Exception((proc,cell))
154+
cell.nb = None
144155

145156
def _process_comment(self, proc, cell, cmd, args):
146157
if _is_direc(proc) and getattr(proc, '__name__', '-')[:-1]==cmd: f=proc
@@ -154,7 +165,6 @@ def process(self):
154165
for proc in self.preprocs:
155166
self.nb = opt_set(self.nb, proc(self.nb))
156167
for i,cell in enumerate(self.nb.cells): cell.idx_ = i
157-
for cell in self.nb.cells: cell.directives_ = extract_directives(cell, remove=self.rm_directives, lang=self.lang)
158168
for cell in self.nb.cells: self._process_cell(cell)
159169
for proc in self.postprocs: self.nb = opt_set(self.nb, proc(self.nb))
160170
self.nb.cells = [c for c in self.nb.cells if c and getattr(c,'source',None) is not None]

nbdev/processors.py

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

33
# %% auto 0
4-
__all__ = ['DEFAULT_FM_KEYS', 'cell_lang', 'add_links', 'strip_ansi', 'strip_hidden_metadata', 'hide_', 'hide_line',
4+
__all__ = ['DEFAULT_FM_KEYS', 'nbflags_', 'cell_lang', 'add_links', 'strip_ansi', 'strip_hidden_metadata', 'hide_', 'hide_line',
55
'filter_stream_', 'clean_magics', 'lang_identify', 'rm_header_dash', 'rm_export', 'clean_show_doc',
66
'exec_show_docs', 'populate_language', 'insert_warning', 'add_show_docs', 'is_frontmatter', 'nb_fmdict',
77
'construct_fm', 'insert_frontmatter', 'infer_frontmatter']
@@ -22,6 +22,11 @@
2222
import sys
2323

2424
# %% ../nbs/09_processors.ipynb 9
25+
def nbflags_(nbp, cell, *args):
26+
"Hide cell from output"
27+
nbp.nb._nbflags = args
28+
29+
# %% ../nbs/09_processors.ipynb 11
2530
def cell_lang(cell): return nested_attr(cell, 'metadata.language', 'python')
2631

2732
def add_links(cell):
@@ -32,25 +37,25 @@ def add_links(cell):
3237
if hasattr(o, 'data') and hasattr(o['data'], 'text/markdown'):
3338
o.data['text/markdown'] = [nl.link_line(s) for s in o.data['text/markdown']]
3439

35-
# %% ../nbs/09_processors.ipynb 12
40+
# %% ../nbs/09_processors.ipynb 14
3641
_re_ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
3742

3843
def strip_ansi(cell):
3944
"Strip Ansi Characters."
4045
for outp in cell.get('outputs', []):
4146
if outp.get('name')=='stdout': outp['text'] = [_re_ansi_escape.sub('', o) for o in outp.text]
4247

43-
# %% ../nbs/09_processors.ipynb 14
48+
# %% ../nbs/09_processors.ipynb 16
4449
def strip_hidden_metadata(cell):
4550
'''Strips "hidden" metadata property from code cells so it doesn't interfere with docs rendering'''
4651
if cell.cell_type == 'code' and 'metadata' in cell: cell.metadata.pop('hidden',None)
4752

48-
# %% ../nbs/09_processors.ipynb 16
53+
# %% ../nbs/09_processors.ipynb 17
4954
def hide_(nbp, cell):
5055
"Hide cell from output"
5156
del(cell['source'])
5257

53-
# %% ../nbs/09_processors.ipynb 18
58+
# %% ../nbs/09_processors.ipynb 19
5459
def _re_hideline(lang=None): return re.compile(fr'{langs[lang]}\|\s*hide_line\s*$', re.MULTILINE)
5560

5661
def hide_line(cell):
@@ -59,22 +64,22 @@ def hide_line(cell):
5964
if cell.cell_type == 'code' and _re_hideline(lang).search(cell.source):
6065
cell.source = '\n'.join([c for c in cell.source.splitlines() if not _re_hideline(lang).search(c)])
6166

62-
# %% ../nbs/09_processors.ipynb 20
67+
# %% ../nbs/09_processors.ipynb 21
6368
def filter_stream_(nbp, cell, *words):
6469
"Remove output lines containing any of `words` in `cell` stream output"
6570
if not words: return
6671
for outp in cell.get('outputs', []):
6772
if outp.output_type == 'stream':
6873
outp['text'] = [l for l in outp.text if not re.search('|'.join(words), l)]
6974

70-
# %% ../nbs/09_processors.ipynb 22
75+
# %% ../nbs/09_processors.ipynb 23
7176
_magics_pattern = re.compile(r'^\s*(%%|%).*', re.MULTILINE)
7277

7378
def clean_magics(cell):
7479
"A preprocessor to remove cell magic commands"
7580
if cell.cell_type == 'code': cell.source = _magics_pattern.sub('', cell.source).strip()
7681

77-
# %% ../nbs/09_processors.ipynb 24
82+
# %% ../nbs/09_processors.ipynb 25
7883
_langs = 'bash|html|javascript|js|latex|markdown|perl|ruby|sh|svg'
7984
_lang_pattern = re.compile(rf'^\s*%%\s*({_langs})\s*$', flags=re.MULTILINE)
8085

@@ -84,7 +89,7 @@ def lang_identify(cell):
8489
lang = _lang_pattern.findall(cell.source)
8590
if lang: cell.metadata.language = lang[0]
8691

87-
# %% ../nbs/09_processors.ipynb 27
92+
# %% ../nbs/09_processors.ipynb 28
8893
_re_hdr_dash = re.compile(r'^#+\s+.*\s+-\s*$', re.MULTILINE)
8994

9095
def rm_header_dash(cell):
@@ -93,15 +98,15 @@ def rm_header_dash(cell):
9398
src = cell.source.strip()
9499
if cell.cell_type == 'markdown' and src.startswith('#') and src.endswith(' -'): del(cell['source'])
95100

96-
# %% ../nbs/09_processors.ipynb 29
101+
# %% ../nbs/09_processors.ipynb 30
97102
_hide_dirs = {'export','exporti', 'hide','default_exp'}
98103

99104
def rm_export(cell):
100105
"Remove cells that are exported or hidden"
101106
if cell.directives_:
102107
if cell.directives_.keys() & _hide_dirs: del(cell['source'])
103108

104-
# %% ../nbs/09_processors.ipynb 31
109+
# %% ../nbs/09_processors.ipynb 32
105110
_re_showdoc = re.compile(r'^show_doc', re.MULTILINE)
106111
def _is_showdoc(cell): return cell['cell_type'] == 'code' and _re_showdoc.search(cell.source)
107112

@@ -110,7 +115,7 @@ def clean_show_doc(cell):
110115
if not _is_showdoc(cell): return
111116
cell.source = '#| echo: false\n' + cell.source
112117

113-
# %% ../nbs/09_processors.ipynb 32
118+
# %% ../nbs/09_processors.ipynb 33
114119
_imps = {ast.Import, ast.ImportFrom}
115120

116121
def _show_docs(trees):
@@ -126,47 +131,50 @@ def _do_eval(cell):
126131
if cell.directives_.keys() & _show_dirs or filter_ex(trees, risinstance(_imps)): return True
127132
if _show_docs(trees): return True
128133

129-
# %% ../nbs/09_processors.ipynb 33
134+
# %% ../nbs/09_processors.ipynb 34
130135
class exec_show_docs:
131136
"Execute cells needed for `show_docs` output, including exported cells and imports"
132137
def __init__(self, nb):
133138
self.k = CaptureShell()
134139
if nb_lang(nb) == 'python': self.k.run_cell('from nbdev.showdoc import show_doc')
135140

136141
def __call__(self, cell):
142+
flags = getattr(cell.nb, '_nbflags', [])
143+
if 'skip_showdoc' in flags: return
137144
if _do_eval(cell): self.k.cell(cell)
138145
if self.k.exc:
139146
sys.stderr.write(f'Error in cell {cell.idx_}:\n{cell.source}')
140147
raise self.k.exc[1] from None
141148

142-
# %% ../nbs/09_processors.ipynb 36
149+
# %% ../nbs/09_processors.ipynb 37
143150
def populate_language(nb):
144151
"Insert cell language indicator based on notebook metadata. You should to use this before `lang_identify`"
145152
for cell in nb.cells:
146153
if cell.cell_type == 'code': cell.metadata.language = nb_lang(nb)
147154

148-
# %% ../nbs/09_processors.ipynb 39
155+
# %% ../nbs/09_processors.ipynb 40
149156
def insert_warning(nb):
150157
"Insert Autogenerated Warning Into Notebook after the first cell."
151158
content = "<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->"
152-
nb.cells.insert(1, mk_cell(content, False))
159+
nb.cells.insert(1, mk_cell(content, 'markdown'))
153160

154-
# %% ../nbs/09_processors.ipynb 43
161+
# %% ../nbs/09_processors.ipynb 44
155162
_def_types = (ast.FunctionDef,ast.AsyncFunctionDef,ast.ClassDef)
156163
def _def_names(cell, shown):
157164
return [showdoc_nm(o) for o in concat(cell.parsed_())
158165
if isinstance(o,_def_types) and o.name not in shown and o.name[0]!='_']
159166

160-
_re_exps = re.compile(r'^\s*#\|\s*(?:export|exports)').search
161-
162167
def _get_nm(tree):
163168
i = tree.value.args[0]
164169
return f'{i.value.id}.{i.attr}' if isinstance(i, ast.Attribute) else i.id
165170

166-
# %% ../nbs/09_processors.ipynb 44
171+
# %% ../nbs/09_processors.ipynb 45
167172
def add_show_docs(nb):
168173
"Add show_doc cells after exported cells, unless they are already documented"
169-
exports = L(cell for cell in nb.cells if cell.source and _re_exps(cell.source))
174+
def _want(c):
175+
return c.source and c.cell_type=='code' and ('export' in c.directives_ or 'exports' in c.directives_)
176+
177+
exports = L(cell for cell in nb.cells if _want(cell))
170178
trees = nb.cells.map(NbCell.parsed_).concat()
171179
shown_docs = {_get_nm(t) for t in _show_docs(trees)}
172180
for cell in reversed(exports):
@@ -175,7 +183,7 @@ def add_show_docs(nb):
175183
for nm in _def_names(cell, shown_docs):
176184
nb.cells.insert(cell.idx_+1, mk_cell(f'show_doc({nm})'))
177185

178-
# %% ../nbs/09_processors.ipynb 48
186+
# %% ../nbs/09_processors.ipynb 49
179187
_re_title = re.compile(r'^#\s+(.*)[\n\r]+(?:^>\s+(.*))?', flags=re.MULTILINE)
180188
_re_fm = re.compile(r'^---.*\S+.*---', flags=re.DOTALL)
181189
_re_defaultexp = re.compile(r'^\s*#\|\s*default_exp\s+(\S+)', flags=re.MULTILINE)
@@ -186,14 +194,14 @@ def _istitle(cell):
186194
txt = cell.get('source', '')
187195
return bool(_re_title.search(txt)) if txt else False
188196

189-
# %% ../nbs/09_processors.ipynb 49
197+
# %% ../nbs/09_processors.ipynb 50
190198
def _default_exp(nb):
191199
"get the default_exp from a notebook"
192200
code_src = nb.cells.filter(lambda x: x.cell_type == 'code').attrgot('source')
193201
default_exp = first(code_src.filter().map(_re_defaultexp.search).filter())
194202
return default_exp.group(1) if default_exp else None
195203

196-
# %% ../nbs/09_processors.ipynb 51
204+
# %% ../nbs/09_processors.ipynb 52
197205
def nb_fmdict(nb, remove=True):
198206
"Infer the front matter from a notebook's markdown formatting"
199207
md_cells = _celltyp(nb, 'markdown').filter(_istitle)
@@ -209,21 +217,21 @@ def nb_fmdict(nb, remove=True):
209217
return flags
210218
else: return {}
211219

212-
# %% ../nbs/09_processors.ipynb 54
220+
# %% ../nbs/09_processors.ipynb 55
213221
DEFAULT_FM_KEYS = ['title', 'description', 'author', 'image', 'categories', 'output-file', 'aliases']
214222

215223
def construct_fm(fmdict:dict, keys = DEFAULT_FM_KEYS):
216224
"construct front matter from a dictionary, but only for `keys`"
217225
if not fmdict: return None
218226
return '---\n'+'\n'.join([f"{k}: {fmdict[k]}" for k in keys if k in fmdict])+'\n---'
219227

220-
# %% ../nbs/09_processors.ipynb 56
228+
# %% ../nbs/09_processors.ipynb 57
221229
def insert_frontmatter(nb, fm_dict:dict, filter_keys:list=DEFAULT_FM_KEYS):
222230
"Add frontmatter into notebook based on `filter_keys` that exist in `fmdict`."
223231
fm = construct_fm(fm_dict, keys=filter_keys)
224-
if fm: nb.cells.insert(0, NbCell(0, dict(cell_type='raw', metadata={}, source=fm)))
232+
if fm: nb.cells.insert(0, NbCell(0, dict(cell_type='raw', metadata={}, source=fm, directives_={})))
225233

226-
# %% ../nbs/09_processors.ipynb 57
234+
# %% ../nbs/09_processors.ipynb 58
227235
def infer_frontmatter(nb):
228236
"Insert front matter if it doesn't exist automatically from nbdev styled markdown."
229237
if is_frontmatter(nb): return

nbdev/read.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@
1818
from pprint import pformat,pprint
1919

2020
# %% ../nbs/01_read.ipynb 4
21-
def mk_cell(text, code=True):
21+
def mk_cell(text, cell_type='code'):
2222
"Create a `NbCell` containing `text`"
23-
return NbCell(0, dict(cell_type='code' if code else 'markdown', metadata={}, source=text))
23+
assert cell_type in {'code', 'markdown', 'raw'}
24+
return NbCell(0, dict(cell_type=cell_type, metadata={}, source=text, directives_={}))
2425

2526
# %% ../nbs/01_read.ipynb 5
2627
def create_output(txt, mime):

0 commit comments

Comments
 (0)