Skip to content

Commit 53a47b1

Browse files
committed
fixes #1536
1 parent b77c323 commit 53a47b1

File tree

4 files changed

+36
-765
lines changed

4 files changed

+36
-765
lines changed

nbdev/_modidx.py

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -322,37 +322,9 @@
322322
'nbdev.showdoc.BasicMarkdownRenderer': ('api/showdoc.html#basicmarkdownrenderer', 'nbdev/showdoc.py'),
323323
'nbdev.showdoc.BasicMarkdownRenderer._repr_markdown_': ( 'api/showdoc.html#basicmarkdownrenderer._repr_markdown_',
324324
'nbdev/showdoc.py'),
325-
'nbdev.showdoc.DocmentTbl': ('api/showdoc.html#docmenttbl', 'nbdev/showdoc.py'),
326-
'nbdev.showdoc.DocmentTbl.__eq__': ('api/showdoc.html#docmenttbl.__eq__', 'nbdev/showdoc.py'),
327-
'nbdev.showdoc.DocmentTbl.__init__': ('api/showdoc.html#docmenttbl.__init__', 'nbdev/showdoc.py'),
328-
'nbdev.showdoc.DocmentTbl._columns': ('api/showdoc.html#docmenttbl._columns', 'nbdev/showdoc.py'),
329-
'nbdev.showdoc.DocmentTbl._hdr_list': ('api/showdoc.html#docmenttbl._hdr_list', 'nbdev/showdoc.py'),
330-
'nbdev.showdoc.DocmentTbl._repr_markdown_': ( 'api/showdoc.html#docmenttbl._repr_markdown_',
331-
'nbdev/showdoc.py'),
332-
'nbdev.showdoc.DocmentTbl._row': ('api/showdoc.html#docmenttbl._row', 'nbdev/showdoc.py'),
333-
'nbdev.showdoc.DocmentTbl._row_list': ('api/showdoc.html#docmenttbl._row_list', 'nbdev/showdoc.py'),
334-
'nbdev.showdoc.DocmentTbl.has_docment': ('api/showdoc.html#docmenttbl.has_docment', 'nbdev/showdoc.py'),
335-
'nbdev.showdoc.DocmentTbl.has_return': ('api/showdoc.html#docmenttbl.has_return', 'nbdev/showdoc.py'),
336-
'nbdev.showdoc.DocmentTbl.hdr_str': ('api/showdoc.html#docmenttbl.hdr_str', 'nbdev/showdoc.py'),
337-
'nbdev.showdoc.DocmentTbl.params_str': ('api/showdoc.html#docmenttbl.params_str', 'nbdev/showdoc.py'),
338-
'nbdev.showdoc.DocmentTbl.return_str': ('api/showdoc.html#docmenttbl.return_str', 'nbdev/showdoc.py'),
339-
'nbdev.showdoc.ShowDocRenderer': ('api/showdoc.html#showdocrenderer', 'nbdev/showdoc.py'),
340-
'nbdev.showdoc.ShowDocRenderer.__init__': ('api/showdoc.html#showdocrenderer.__init__', 'nbdev/showdoc.py'),
341-
'nbdev.showdoc._bold': ('api/showdoc.html#_bold', 'nbdev/showdoc.py'),
342325
'nbdev.showdoc._create_html_table': ('api/showdoc.html#_create_html_table', 'nbdev/showdoc.py'),
343-
'nbdev.showdoc._docstring': ('api/showdoc.html#_docstring', 'nbdev/showdoc.py'),
344-
'nbdev.showdoc._escape_markdown': ('api/showdoc.html#_escape_markdown', 'nbdev/showdoc.py'),
345326
'nbdev.showdoc._ext_link': ('api/showdoc.html#_ext_link', 'nbdev/showdoc.py'),
346-
'nbdev.showdoc._f_name': ('api/showdoc.html#_f_name', 'nbdev/showdoc.py'),
347-
'nbdev.showdoc._fmt_anno': ('api/showdoc.html#_fmt_anno', 'nbdev/showdoc.py'),
348-
'nbdev.showdoc._fmt_sig': ('api/showdoc.html#_fmt_sig', 'nbdev/showdoc.py'),
349-
'nbdev.showdoc._fullname': ('api/showdoc.html#_fullname', 'nbdev/showdoc.py'),
350327
'nbdev.showdoc._html_link': ('api/showdoc.html#_html_link', 'nbdev/showdoc.py'),
351-
'nbdev.showdoc._list2row': ('api/showdoc.html#_list2row', 'nbdev/showdoc.py'),
352-
'nbdev.showdoc._maybe_nm': ('api/showdoc.html#_maybe_nm', 'nbdev/showdoc.py'),
353-
'nbdev.showdoc._non_empty_keys': ('api/showdoc.html#_non_empty_keys', 'nbdev/showdoc.py'),
354-
'nbdev.showdoc._show_param': ('api/showdoc.html#_show_param', 'nbdev/showdoc.py'),
355-
'nbdev.showdoc._wrap_sig': ('api/showdoc.html#_wrap_sig', 'nbdev/showdoc.py'),
356328
'nbdev.showdoc.colab_link': ('api/showdoc.html#colab_link', 'nbdev/showdoc.py'),
357329
'nbdev.showdoc.doc': ('api/showdoc.html#doc', 'nbdev/showdoc.py'),
358330
'nbdev.showdoc.show_doc': ('api/showdoc.html#show_doc', 'nbdev/showdoc.py'),

nbdev/showdoc.py

Lines changed: 6 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -17,165 +17,20 @@
1717
from types import FunctionType
1818

1919
# %% auto 0
20-
__all__ = ['DocmentTbl', 'ShowDocRenderer', 'BasicMarkdownRenderer', 'show_doc', 'BasicHtmlRenderer', 'doc', 'showdoc_nm',
21-
'colab_link']
22-
23-
# %% ../nbs/api/08_showdoc.ipynb
24-
def _non_empty_keys(d:dict): return L([k for k,v in d.items() if v != inspect._empty])
25-
def _bold(s): return f'**{s}**' if s.strip() else s
26-
27-
# %% ../nbs/api/08_showdoc.ipynb
28-
def _escape_markdown(s):
29-
for c in '|^': s = re.sub(rf'\\?\{c}', rf'\{c}', s)
30-
return s.replace('\n', '<br>')
31-
32-
# %% ../nbs/api/08_showdoc.ipynb
33-
def _maybe_nm(o):
34-
if (o == inspect._empty): return ''
35-
else: return o.__name__ if hasattr(o, '__name__') else _escape_markdown(str(o))
36-
37-
# %% ../nbs/api/08_showdoc.ipynb
38-
def _list2row(l:list): return '| '+' | '.join([_maybe_nm(o) for o in l]) + ' |'
39-
40-
# %% ../nbs/api/08_showdoc.ipynb
41-
class DocmentTbl:
42-
# this is the column order we want these items to appear
43-
_map = OrderedDict({'anno':'Type', 'default':'Default', 'docment':'Details'})
44-
45-
def __init__(self, obj, verbose=True, returns=True):
46-
"Compute the docment table string"
47-
self.verbose = verbose
48-
self.returns = False if isdataclass(obj) else returns
49-
try: self.params = L(signature_ex(obj, eval_str=True).parameters.keys())
50-
except (ValueError,TypeError): self.params=[]
51-
try: _dm = docments(obj, full=True, returns=returns)
52-
except: _dm = {}
53-
if 'self' in _dm: del _dm['self']
54-
for d in _dm.values(): d['docment'] = ifnone(d['docment'], inspect._empty)
55-
self.dm = _dm
56-
57-
@property
58-
def _columns(self):
59-
"Compute the set of fields that have at least one non-empty value so we don't show tables empty columns"
60-
cols = set(flatten(L(self.dm.values()).filter().map(_non_empty_keys)))
61-
candidates = self._map if self.verbose else {'docment': 'Details'}
62-
return OrderedDict({k:v for k,v in candidates.items() if k in cols})
63-
64-
@property
65-
def has_docment(self): return 'docment' in self._columns and self._row_list
66-
67-
@property
68-
def has_return(self): return self.returns and bool(_non_empty_keys(self.dm.get('return', {})))
69-
70-
def _row(self, nm, props):
71-
"unpack data for single row to correspond with column names."
72-
return [nm] + [props[c] for c in self._columns]
73-
74-
@property
75-
def _row_list(self):
76-
"unpack data for all rows."
77-
ordered_params = [(p, self.dm[p]) for p in self.params if p != 'self' and p in self.dm]
78-
return L([self._row(nm, props) for nm,props in ordered_params])
79-
80-
@property
81-
def _hdr_list(self): return [' '] + [_bold(l) for l in L(self._columns.values())]
82-
83-
@property
84-
def hdr_str(self):
85-
"The markdown string for the header portion of the table"
86-
md = _list2row(self._hdr_list)
87-
return md + '\n' + _list2row(['-' * len(l) for l in self._hdr_list])
88-
89-
@property
90-
def params_str(self):
91-
"The markdown string for the parameters portion of the table."
92-
return '\n'.join(self._row_list.map(_list2row))
93-
94-
@property
95-
def return_str(self):
96-
"The markdown string for the returns portion of the table."
97-
return _list2row(['**Returns**']+[_bold(_maybe_nm(self.dm['return'][c])) for c in self._columns])
98-
99-
def _repr_markdown_(self):
100-
if not self.has_docment: return ''
101-
_tbl = [self.hdr_str, self.params_str]
102-
if self.has_return: _tbl.append(self.return_str)
103-
return '\n'.join(_tbl)
104-
105-
def __eq__(self,other): return self.__str__() == str(other).strip()
106-
107-
__str__ = _repr_markdown_
108-
__repr__ = basic_repr()
109-
110-
# %% ../nbs/api/08_showdoc.ipynb
111-
def _docstring(sym):
112-
npdoc = parse_docstring(sym)
113-
return '\n\n'.join([npdoc['Summary'], npdoc['Extended']]).strip()
114-
115-
# %% ../nbs/api/08_showdoc.ipynb
116-
def _fullname(o):
117-
module,name = getattr(o, "__module__", None),qual_name(o)
118-
return name if module is None or module in ('__main__','builtins') else module + '.' + name
119-
120-
class ShowDocRenderer:
121-
def __init__(self, sym, name:str|None=None, title_level:int=3):
122-
"Show documentation for `sym`"
123-
sym = getattr(sym, '__wrapped__', sym)
124-
sym = getattr(sym, 'fget', None) or getattr(sym, 'fset', None) or sym
125-
store_attr()
126-
self.nm = name or qual_name(sym)
127-
self.isfunc = inspect.isfunction(sym)
128-
try: self.sig = signature_ex(sym, eval_str=True)
129-
except (ValueError,TypeError): self.sig = None
130-
self.docs = _docstring(sym)
131-
self.dm = DocmentTbl(sym)
132-
self.fn = _fullname(sym)
133-
134-
__repr__ = basic_repr()
135-
136-
# %% ../nbs/api/08_showdoc.ipynb
137-
def _f_name(o): return f'<function {o.__name__}>' if isinstance(o, FunctionType) else None
138-
def _fmt_anno(o): return inspect.formatannotation(o).strip("'").replace(' ','')
139-
140-
def _show_param(param):
141-
"Like `Parameter.__str__` except removes: quotes in annos, spaces, ids in reprs"
142-
kind,res,anno,default = param.kind,param._name,param._annotation,param._default
143-
kind = '*' if kind==inspect._VAR_POSITIONAL else '**' if kind==inspect._VAR_KEYWORD else ''
144-
res = kind+res
145-
if anno is not inspect._empty: res += f':{_f_name(anno) or _fmt_anno(anno)}'
146-
if default is not inspect._empty: res += f'={_f_name(default) or repr(default)}'
147-
return res
148-
149-
# %% ../nbs/api/08_showdoc.ipynb
150-
def _fmt_sig(sig):
151-
if sig is None: return ''
152-
p = {k:v for k,v in sig.parameters.items()}
153-
_params = [_show_param(p[k]) for k in p.keys() if k != 'self']
154-
return "(" + ', '.join(_params) + ")"
155-
156-
def _wrap_sig(s):
157-
"wrap a signature to appear on multiple lines if necessary."
158-
pad = '> ' + ' ' * 5
159-
indent = pad + ' ' * (s.find('(') + 1)
160-
return fill(s, width=80, initial_indent=pad, subsequent_indent=indent)
20+
__all__ = ['BasicMarkdownRenderer', 'show_doc', 'BasicHtmlRenderer', 'doc', 'showdoc_nm', 'colab_link']
16121

16222
# %% ../nbs/api/08_showdoc.ipynb
16323
def _ext_link(url, txt, xtra=""): return f'[{txt}]({url}){{target="_blank" {xtra}}}'
16424

165-
class BasicMarkdownRenderer(ShowDocRenderer):
25+
class BasicMarkdownRenderer(MarkdownRenderer):
16626
"Markdown renderer for `show_doc`"
16727
def _repr_markdown_(self):
16828
doc = '---\n\n'
16929
src = NbdevLookup().code(self.fn)
17030
if src: doc += _ext_link(src, 'source', 'style="float:right; font-size:smaller"') + '\n\n'
17131
h = '#'*self.title_level
17232
doc += f'{h} {self.nm}\n\n'
173-
sig = _wrap_sig(f"{self.nm} {_fmt_sig(self.sig)}") if self.sig else ''
174-
doc += f'{sig}'
175-
if self.docs: doc += f"\n\n*{self.docs}*"
176-
if self.dm.has_docment: doc += f"\n\n{self.dm}"
177-
return doc
178-
__repr__=__str__=_repr_markdown_
33+
return doc+super()._repr_markdown_()
17934

18035
# %% ../nbs/api/08_showdoc.ipynb
18136
def show_doc(sym, # Symbol to document
@@ -212,6 +67,9 @@ def unescape_cell(cell):
21267
# %% ../nbs/api/08_showdoc.ipynb
21368
def _html_link(url, txt): return f'<a href="{url}" target="_blank" rel="noreferrer noopener">{txt}</a>'
21469

70+
# %% ../nbs/api/08_showdoc.ipynb
71+
from fastcore.docments import _fmt_sig
72+
21573
# %% ../nbs/api/08_showdoc.ipynb
21674
class BasicHtmlRenderer(ShowDocRenderer):
21775
"HTML renderer for `show_doc`"

0 commit comments

Comments
 (0)