nbdev 2.4.6__tar.gz → 2.4.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. {nbdev-2.4.6/nbdev.egg-info → nbdev-2.4.8}/PKG-INFO +2 -2
  2. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/__init__.py +1 -1
  3. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/_modidx.py +7 -28
  4. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/cli.py +10 -3
  5. nbdev-2.4.8/nbdev/diff.py +92 -0
  6. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/export.py +1 -1
  7. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/process.py +1 -1
  8. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/quarto.py +1 -1
  9. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/release.py +1 -1
  10. nbdev-2.4.8/nbdev/showdoc.py +113 -0
  11. {nbdev-2.4.6 → nbdev-2.4.8/nbdev.egg-info}/PKG-INFO +2 -2
  12. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev.egg-info/SOURCES.txt +1 -0
  13. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev.egg-info/requires.txt +1 -1
  14. {nbdev-2.4.6 → nbdev-2.4.8}/settings.ini +2 -2
  15. nbdev-2.4.6/nbdev/showdoc.py +0 -255
  16. {nbdev-2.4.6 → nbdev-2.4.8}/CONTRIBUTING.md +0 -0
  17. {nbdev-2.4.6 → nbdev-2.4.8}/LICENSE +0 -0
  18. {nbdev-2.4.6 → nbdev-2.4.8}/MANIFEST.in +0 -0
  19. {nbdev-2.4.6 → nbdev-2.4.8}/README.md +0 -0
  20. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/clean.py +0 -0
  21. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/config.py +0 -0
  22. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/doclinks.py +0 -0
  23. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/extract_attachments.py +0 -0
  24. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/frontmatter.py +0 -0
  25. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/imports.py +0 -0
  26. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/maker.py +0 -0
  27. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/merge.py +0 -0
  28. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/migrate.py +0 -0
  29. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/processors.py +0 -0
  30. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/qmd.py +0 -0
  31. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/serve.py +0 -0
  32. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/serve_drv.py +0 -0
  33. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/sync.py +0 -0
  34. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/test.py +0 -0
  35. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev.egg-info/dependency_links.txt +0 -0
  36. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev.egg-info/entry_points.txt +0 -0
  37. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev.egg-info/not-zip-safe +0 -0
  38. {nbdev-2.4.6 → nbdev-2.4.8}/nbdev.egg-info/top_level.txt +0 -0
  39. {nbdev-2.4.6 → nbdev-2.4.8}/pyproject.toml +0 -0
  40. {nbdev-2.4.6 → nbdev-2.4.8}/setup.cfg +0 -0
  41. {nbdev-2.4.6 → nbdev-2.4.8}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nbdev
3
- Version: 2.4.6
3
+ Version: 2.4.8
4
4
  Summary: Create delightful software with Jupyter Notebooks
5
5
  Home-page: https://github.com/AnswerDotAI/nbdev
6
6
  Author: Jeremy Howard and Hamel Husain
@@ -20,7 +20,7 @@ Requires-Python: >=3.9
20
20
  Description-Content-Type: text/markdown
21
21
  License-File: LICENSE
22
22
  Requires-Dist: packaging
23
- Requires-Dist: fastcore>=1.8.0
23
+ Requires-Dist: fastcore>=1.11.0
24
24
  Requires-Dist: execnb>=0.1.12
25
25
  Requires-Dist: astunparse
26
26
  Requires-Dist: ghapi>=1.0.3
@@ -1,4 +1,4 @@
1
- __version__ = "2.4.6"
1
+ __version__ = "2.4.8"
2
2
 
3
3
  from .doclinks import nbdev_export
4
4
  from .showdoc import show_doc
@@ -49,6 +49,13 @@ d = { 'settings': { 'branch': 'main',
49
49
  'nbdev.config.update_proj': ('api/config.html#update_proj', 'nbdev/config.py'),
50
50
  'nbdev.config.update_version': ('api/config.html#update_version', 'nbdev/config.py'),
51
51
  'nbdev.config.write_cells': ('api/config.html#write_cells', 'nbdev/config.py')},
52
+ 'nbdev.diff': { 'nbdev.diff._cell_changes': ('api/diff.html#_cell_changes', 'nbdev/diff.py'),
53
+ 'nbdev.diff._nb_srcdict': ('api/diff.html#_nb_srcdict', 'nbdev/diff.py'),
54
+ 'nbdev.diff.cell_diffs': ('api/diff.html#cell_diffs', 'nbdev/diff.py'),
55
+ 'nbdev.diff.changed_cells': ('api/diff.html#changed_cells', 'nbdev/diff.py'),
56
+ 'nbdev.diff.nbs_pair': ('api/diff.html#nbs_pair', 'nbdev/diff.py'),
57
+ 'nbdev.diff.read_nb_from_git': ('api/diff.html#read_nb_from_git', 'nbdev/diff.py'),
58
+ 'nbdev.diff.source_diff': ('api/diff.html#source_diff', 'nbdev/diff.py')},
52
59
  'nbdev.doclinks': { 'nbdev.doclinks.NbdevLookup': ('api/doclinks.html#nbdevlookup', 'nbdev/doclinks.py'),
53
60
  'nbdev.doclinks.NbdevLookup.__getitem__': ( 'api/doclinks.html#nbdevlookup.__getitem__',
54
61
  'nbdev/doclinks.py'),
@@ -322,37 +329,9 @@ d = { 'settings': { 'branch': 'main',
322
329
  'nbdev.showdoc.BasicMarkdownRenderer': ('api/showdoc.html#basicmarkdownrenderer', 'nbdev/showdoc.py'),
323
330
  'nbdev.showdoc.BasicMarkdownRenderer._repr_markdown_': ( 'api/showdoc.html#basicmarkdownrenderer._repr_markdown_',
324
331
  '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'),
342
332
  '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'),
345
333
  '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'),
350
334
  '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'),
356
335
  'nbdev.showdoc.colab_link': ('api/showdoc.html#colab_link', 'nbdev/showdoc.py'),
357
336
  'nbdev.showdoc.doc': ('api/showdoc.html#doc', 'nbdev/showdoc.py'),
358
337
  'nbdev.showdoc.show_doc': ('api/showdoc.html#show_doc', 'nbdev/showdoc.py'),
@@ -101,7 +101,8 @@ def nbdev_new(**kwargs):
101
101
  if tag is None:
102
102
  with warnings.catch_warnings():
103
103
  warnings.simplefilter('ignore', UserWarning)
104
- tag = GhApi(gh_host='https://api.github.com', authenticate=False).repos.get_latest_release(org_or_usr, repo).tag_name
104
+ tag = GhApi(gh_host='https://api.github.com', authenticate=False
105
+ ).repos.get_latest_release(org_or_usr, repo).tag_name
105
106
 
106
107
  url = f"https://github.com/{org_or_usr}/{repo}/archive/{tag}.tar.gz"
107
108
  extract_tgz(url)
@@ -184,10 +185,16 @@ def watch_export(nbs:str=None, # Nb directory to watch for changes
184
185
  lib = lib or (cfg.lib_path if cfg else '.')
185
186
  if cfg and (nbs != cfg.nbs_path or lib != cfg.lib_path) and not force:
186
187
  raise ValueError("In nbdev project. Use --force to override config.")
188
+ run(f'nbdev_export')
187
189
  def _export(e,lib=lib):
188
190
  p = e.src_path
189
- if (not '.ipynb_checkpoints' in p and p.endswith('.ipynb') and not Path(p).name.startswith('.~')):
190
- if e.event_type == 'modified': run(f'nb_export --lib_path {lib} "{p}"')
191
+ if (not '.ipynb_checkpoints' in p and p.endswith('.ipynb') and not Path(p).name.startswith(('tmp','.~'))):
192
+ if e.event_type == 'modified':
193
+ time.sleep(0.1)
194
+ try: run(f'nb_export --lib_path {lib} "{p}"')
195
+ except IOError:
196
+ time.sleep(0.3)
197
+ run(f'nb_export --lib_path {lib} "{p}"')
191
198
  with fs_watchdog(_export, nbs):
192
199
  while True: time.sleep(1)
193
200
 
@@ -0,0 +1,92 @@
1
+ """Get ipynb diffs by cell"""
2
+
3
+ # AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/19_diff.ipynb.
4
+
5
+ # %% auto 0
6
+ __all__ = ['read_nb_from_git', 'nbs_pair', 'changed_cells', 'source_diff', 'cell_diffs']
7
+
8
+ # %% ../nbs/api/19_diff.ipynb
9
+ import json
10
+ from fastcore.utils import *
11
+ from fastcore.meta import delegates
12
+ from difflib import unified_diff
13
+ from fastgit import Git
14
+ from execnb.nbio import *
15
+
16
+ # %% ../nbs/api/19_diff.ipynb
17
+ def read_nb_from_git(
18
+ g:Git, # The git object
19
+ path, # The path to the notebook (absolute or relative to git root)
20
+ ref=None # The git ref to read from (e.g. HEAD); None for working dir
21
+ )->AttrDict: # The notebook
22
+ "Read notebook from git ref (e.g. HEAD) at path, or working dir if ref is None"
23
+ path = Path(path)
24
+ if path.is_absolute(): path = path.relative_to(g.top())
25
+ if ref is None: return read_nb(g.top()/path)
26
+ raw = g.show(f'{ref}:{path}', split=False)
27
+ return dict2nb(json.loads(raw))
28
+
29
+ # %% ../nbs/api/19_diff.ipynb
30
+ def _nb_srcdict(g:Git, nb_path, ref=None, f=noop):
31
+ "Dict of id->source"
32
+ nb = read_nb_from_git(g, nb_path, ref)
33
+ return {c['id']: f(c) for c in nb.cells}
34
+
35
+ # %% ../nbs/api/19_diff.ipynb
36
+ def nbs_pair(
37
+ nb_path, # Path to the notebook
38
+ ref_a='HEAD', # First git ref (None for working dir)
39
+ ref_b=None, # Second git ref (None for working dir)
40
+ f=noop # Function to call on contents
41
+ ): # Tuple of two notebooks
42
+ "NBs at two refs; None means working dir. By default provides HEAD and working dir"
43
+ nb_path = Path(nb_path).resolve()
44
+ g = Git(nb_path.parent)
45
+ return _nb_srcdict(g, nb_path, ref_a, f), _nb_srcdict(g, nb_path, ref_b, f)
46
+
47
+ # %% ../nbs/api/19_diff.ipynb
48
+ def _cell_changes(
49
+ nb_path, # Path to the notebook
50
+ fn, # function to call to get dict values
51
+ ref_a='HEAD', # First git ref (None for working dir)
52
+ ref_b=None, # Second git ref (None for working dir)
53
+ adds=True, # Include cells in b but not in a
54
+ changes=True, # Include cells with different content
55
+ dels=False, # Include cells in a but not in b
56
+ metadata=False, # Consider cell metadata when comparing
57
+ outputs=False # Consider cell outputs when comparing
58
+ ): # Dict of results
59
+ "Apply fn(cell_id, old_content, new_content) to changed cells between two refs"
60
+ def cell_content(c):
61
+ res = c.get('source', '')
62
+ if metadata: res += '\n# metadata: ' + json.dumps(c.get('metadata', {}), sort_keys=True)
63
+ if outputs: res += '\n# outputs: ' + json.dumps(c.get('outputs', []), sort_keys=True)
64
+ return res
65
+ old,new = nbs_pair(nb_path, ref_a, ref_b, f=cell_content)
66
+ res = {}
67
+ if adds: res |= {cid: fn(cid, '', new[cid]) for cid in new if cid not in old}
68
+ if changes: res |= {cid: fn(cid, old[cid], new[cid]) for cid in new if cid in old and new[cid] != old[cid]}
69
+ if dels: res |= {cid: fn(cid, old[cid], '') for cid in old if cid not in new}
70
+ return res
71
+
72
+ # %% ../nbs/api/19_diff.ipynb
73
+ @delegates(_cell_changes)
74
+ def changed_cells(nb_path, **kwargs):
75
+ "Return set of cell IDs for changed/added/deleted cells between two refs"
76
+ def f(cid,o,n): return cid
77
+ return set(_cell_changes(nb_path, f, **kwargs).keys())
78
+
79
+ # %% ../nbs/api/19_diff.ipynb
80
+ def source_diff(
81
+ old_source, # Original source string
82
+ new_source # New source string
83
+ ): # Unified diff string
84
+ "Return unified diff string for source change"
85
+ return '\n'.join(unified_diff(old_source.splitlines(), new_source.splitlines(), lineterm=''))
86
+
87
+ # %% ../nbs/api/19_diff.ipynb
88
+ @delegates(_cell_changes)
89
+ def cell_diffs(nb_path, **kwargs):
90
+ "{cell_id:diff} for changed/added/deleted cells between two refs"
91
+ def f(cid,o,n): return source_diff(o,n)
92
+ return _cell_changes(nb_path, f, **kwargs)
@@ -85,7 +85,7 @@ def nb_export(nbname:str, # Filename of notebook
85
85
  all_cells = exp.in_all[mod]
86
86
  nm = ifnone(name, getattr(exp, 'default_exp', None) if mod=='#' else mod)
87
87
  if not nm:
88
- warn(f"Notebook '{nbname}' uses `#|export` without `#|default_exp` cell.\n"
88
+ warn(f"Notebook '{nbname}' uses `#| export` without `#| default_exp` cell.\n"
89
89
  "Note nbdev2 no longer supports nbdev1 syntax. Run `nbdev_migrate` to upgrade.\n"
90
90
  "See https://nbdev.fast.ai/getting_started.html for more information.")
91
91
  return
@@ -35,7 +35,7 @@ def _quarto_re(lang=None): return re.compile(_dir_pre(lang) + r'\s*[\w|-]+\s*:')
35
35
  # %% ../nbs/api/03_process.ipynb
36
36
  def _directive(s, lang='python'):
37
37
  s = re.sub('^'+_dir_pre(lang), f"{langs[lang]}|", s)
38
- if s.strip().endswith(':'): s = s.replace(':', '') # You can append colon at the end to be Quarto compliant. Ex: #|hide:
38
+ if s.strip().endswith(':'): s = s.replace(':', '') # You can append colon at the end to be Quarto compliant. Ex: #| hide:
39
39
  if ':' in s: s = s.replace(':', ': ')
40
40
  s = (s.strip()[2:]).strip().split()
41
41
  if not s: return None
@@ -70,7 +70,7 @@ def _sort(a):
70
70
  x,y = a
71
71
  if y.startswith('index.'): return x,'00'
72
72
  return a
73
- #|export
73
+ #| export
74
74
  _def_file_re = r'\.(?:ipynb|qmd|html)$'
75
75
 
76
76
  @delegates(nbglob_cli)
@@ -63,7 +63,7 @@ class Release:
63
63
 
64
64
  def _issues(self, label):
65
65
  return self.gh.issues.list_for_repo(state='closed', sort='created', filter='all', since=self.commit_date, labels=label)
66
- def _issue_groups(self): return parallel(self._issues, self.groups.keys(), progress=False)
66
+ def _issue_groups(self): return parallel(self._issues, self.groups.keys(), progress=False, threadpool=True)
67
67
 
68
68
  # %% ../nbs/api/18_release.ipynb
69
69
  @patch
@@ -0,0 +1,113 @@
1
+ """Display symbol documentation in notebook and website"""
2
+
3
+ # AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/08_showdoc.ipynb.
4
+
5
+ # %% ../nbs/api/08_showdoc.ipynb 2
6
+ from __future__ import annotations
7
+ from .doclinks import *
8
+ from .config import get_config
9
+
10
+ from fastcore.docments import *
11
+ from fastcore.utils import *
12
+
13
+ from importlib import import_module
14
+ import inspect, sys
15
+ from collections import OrderedDict
16
+ from textwrap import fill
17
+ from types import FunctionType
18
+
19
+ # %% auto 0
20
+ __all__ = ['BasicMarkdownRenderer', 'show_doc', 'BasicHtmlRenderer', 'doc', 'showdoc_nm', 'colab_link']
21
+
22
+ # %% ../nbs/api/08_showdoc.ipynb
23
+ def _ext_link(url, txt, xtra=""): return f'[{txt}]({url}){{target="_blank" {xtra}}}'
24
+
25
+ class BasicMarkdownRenderer(MarkdownRenderer):
26
+ "Markdown renderer for `show_doc`"
27
+ def _repr_markdown_(self):
28
+ doc = '---\n\n'
29
+ src = NbdevLookup().code(self.fn)
30
+ if src: doc += _ext_link(src, 'source', 'style="float:right; font-size:smaller"') + '\n\n'
31
+ h = '#'*self.title_level
32
+ doc += f'{h} {self.nm}\n\n'
33
+ return doc+super()._repr_markdown_()
34
+
35
+ # %% ../nbs/api/08_showdoc.ipynb
36
+ def show_doc(sym, # Symbol to document
37
+ renderer=None, # Optional renderer (defaults to markdown)
38
+ name:str|None=None, # Optionally override displayed name of `sym`
39
+ title_level:int=3): # Heading level to use for symbol name
40
+ "Show signature and docstring for `sym`"
41
+ if renderer is None: renderer = get_config().get('renderer', None)
42
+ if renderer is None: renderer=BasicMarkdownRenderer
43
+ elif isinstance(renderer,str):
44
+ p,m = renderer.rsplit('.', 1)
45
+ renderer = getattr(import_module(p), m)
46
+ if isinstance_str(sym, "Function"): pass
47
+ elif isinstance_str(sym, "TypeDispatch"): pass # use _str as TypeDispatch will be removed from fastcore
48
+ else:return renderer(sym or show_doc, name=name, title_level=title_level)
49
+
50
+ # %% ../nbs/api/08_showdoc.ipynb
51
+ def _create_html_table(table_str):
52
+ def split_row(row):
53
+ return re.findall(r'\|(?:(?:\\.|[^|\\])*)', row)
54
+
55
+ def unescape_cell(cell):
56
+ return cell.strip(' *|').replace(r'\|', '|')
57
+
58
+ lines = table_str.strip().split('\n')
59
+ header = [f"<th>{unescape_cell(cell)}</th>" for cell in split_row(lines[0])]
60
+ rows = [[f"<td>{unescape_cell(cell)}</td>" for cell in split_row(line)] for line in lines[2:]]
61
+
62
+ return f'''<table>
63
+ <thead><tr>{' '.join(header)}</tr></thead>
64
+ <tbody>{''.join(f'<tr>{" ".join(row)}</tr>' for row in rows)}</tbody>
65
+ </table>'''
66
+
67
+ # %% ../nbs/api/08_showdoc.ipynb
68
+ def _html_link(url, txt): return f'<a href="{url}" target="_blank" rel="noreferrer noopener">{txt}</a>'
69
+
70
+ # %% ../nbs/api/08_showdoc.ipynb
71
+ from fastcore.docments import _fmt_sig
72
+
73
+ # %% ../nbs/api/08_showdoc.ipynb
74
+ class BasicHtmlRenderer(ShowDocRenderer):
75
+ "HTML renderer for `show_doc`"
76
+ def _repr_html_(self):
77
+ doc = '<hr/>\n'
78
+ src = NbdevLookup().code(self.fn)
79
+ doc += f'<h{self.title_level}>{self.nm}</h{self.title_level}>\n'
80
+ sig = _fmt_sig(self.sig) if self.sig else ''
81
+ # Escape < and > characters in the signature
82
+ sig = sig.replace('<', '&lt;').replace('>', '&gt;')
83
+ doc += f'<blockquote><pre><code>{self.nm} {sig}</code></pre></blockquote>'
84
+ if self.docs:
85
+ doc += f"<p><i>{self.docs}</i></p>"
86
+ if src: doc += f"<br/>{_html_link(src, 'source')}"
87
+ if self.dm.has_docment: doc += _create_html_table(str(self.dm))
88
+ return doc
89
+
90
+ def doc(self):
91
+ "Show `show_doc` info along with link to docs"
92
+ from IPython.display import display,HTML
93
+ res = self._repr_html_()
94
+ display(HTML(res))
95
+
96
+ # %% ../nbs/api/08_showdoc.ipynb
97
+ def doc(elt):
98
+ "Show `show_doc` info along with link to docs"
99
+ BasicHtmlRenderer(elt).doc()
100
+
101
+ # %% ../nbs/api/08_showdoc.ipynb
102
+ def showdoc_nm(tree):
103
+ "Get the fully qualified name for showdoc."
104
+ return ifnone(patch_name(tree), tree.name)
105
+
106
+ # %% ../nbs/api/08_showdoc.ipynb
107
+ def colab_link(path):
108
+ "Get a link to the notebook at `path` on Colab"
109
+ from IPython.display import Markdown
110
+ cfg = get_config()
111
+ pre = 'https://colab.research.google.com/github/'
112
+ res = f'{pre}{cfg.user}/{cfg.repo}/blob/{cfg.branch}/{cfg.nbs_path.name}/{path}.ipynb'
113
+ display(Markdown(f'[Open `{path}` in Colab]({res})'))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nbdev
3
- Version: 2.4.6
3
+ Version: 2.4.8
4
4
  Summary: Create delightful software with Jupyter Notebooks
5
5
  Home-page: https://github.com/AnswerDotAI/nbdev
6
6
  Author: Jeremy Howard and Hamel Husain
@@ -20,7 +20,7 @@ Requires-Python: >=3.9
20
20
  Description-Content-Type: text/markdown
21
21
  License-File: LICENSE
22
22
  Requires-Dist: packaging
23
- Requires-Dist: fastcore>=1.8.0
23
+ Requires-Dist: fastcore>=1.11.0
24
24
  Requires-Dist: execnb>=0.1.12
25
25
  Requires-Dist: astunparse
26
26
  Requires-Dist: ghapi>=1.0.3
@@ -10,6 +10,7 @@ nbdev/_modidx.py
10
10
  nbdev/clean.py
11
11
  nbdev/cli.py
12
12
  nbdev/config.py
13
+ nbdev/diff.py
13
14
  nbdev/doclinks.py
14
15
  nbdev/export.py
15
16
  nbdev/extract_attachments.py
@@ -1,5 +1,5 @@
1
1
  packaging
2
- fastcore>=1.8.0
2
+ fastcore>=1.11.0
3
3
  execnb>=0.1.12
4
4
  astunparse
5
5
  ghapi>=1.0.3
@@ -9,13 +9,13 @@ author = Jeremy Howard and Hamel Husain
9
9
  author_email = j@fast.ai
10
10
  branch = main
11
11
  min_python = 3.9
12
- version = 2.4.6
12
+ version = 2.4.8
13
13
  audience = Developers
14
14
  language = English
15
15
  custom_sidebar = True
16
16
  license = apache2
17
17
  status = 5
18
- requirements = fastcore>=1.8.0 execnb>=0.1.12 astunparse ghapi>=1.0.3 watchdog asttokens setuptools build
18
+ requirements = fastcore>=1.11.0 execnb>=0.1.12 astunparse ghapi>=1.0.3 watchdog asttokens setuptools build
19
19
  pip_requirements = PyYAML
20
20
  conda_requirements = pyyaml
21
21
  conda_user = fastai
@@ -1,255 +0,0 @@
1
- """Display symbol documentation in notebook and website"""
2
-
3
- # AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/08_showdoc.ipynb.
4
-
5
- # %% ../nbs/api/08_showdoc.ipynb 2
6
- from __future__ import annotations
7
- from .doclinks import *
8
- from .config import get_config
9
-
10
- from fastcore.docments import *
11
- from fastcore.utils import *
12
-
13
- from importlib import import_module
14
- import inspect, sys
15
- from collections import OrderedDict
16
- from textwrap import fill
17
- from types import FunctionType
18
-
19
- # %% 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)
161
-
162
- # %% ../nbs/api/08_showdoc.ipynb
163
- def _ext_link(url, txt, xtra=""): return f'[{txt}]({url}){{target="_blank" {xtra}}}'
164
-
165
- class BasicMarkdownRenderer(ShowDocRenderer):
166
- "Markdown renderer for `show_doc`"
167
- def _repr_markdown_(self):
168
- doc = '---\n\n'
169
- src = NbdevLookup().code(self.fn)
170
- if src: doc += _ext_link(src, 'source', 'style="float:right; font-size:smaller"') + '\n\n'
171
- h = '#'*self.title_level
172
- 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_
179
-
180
- # %% ../nbs/api/08_showdoc.ipynb
181
- def show_doc(sym, # Symbol to document
182
- renderer=None, # Optional renderer (defaults to markdown)
183
- name:str|None=None, # Optionally override displayed name of `sym`
184
- title_level:int=3): # Heading level to use for symbol name
185
- "Show signature and docstring for `sym`"
186
- if renderer is None: renderer = get_config().get('renderer', None)
187
- if renderer is None: renderer=BasicMarkdownRenderer
188
- elif isinstance(renderer,str):
189
- p,m = renderer.rsplit('.', 1)
190
- renderer = getattr(import_module(p), m)
191
- if isinstance_str(sym, "Function"): pass
192
- elif isinstance_str(sym, "TypeDispatch"): pass # use _str as TypeDispatch will be removed from fastcore
193
- else:return renderer(sym or show_doc, name=name, title_level=title_level)
194
-
195
- # %% ../nbs/api/08_showdoc.ipynb
196
- def _create_html_table(table_str):
197
- def split_row(row):
198
- return re.findall(r'\|(?:(?:\\.|[^|\\])*)', row)
199
-
200
- def unescape_cell(cell):
201
- return cell.strip(' *|').replace(r'\|', '|')
202
-
203
- lines = table_str.strip().split('\n')
204
- header = [f"<th>{unescape_cell(cell)}</th>" for cell in split_row(lines[0])]
205
- rows = [[f"<td>{unescape_cell(cell)}</td>" for cell in split_row(line)] for line in lines[2:]]
206
-
207
- return f'''<table>
208
- <thead><tr>{' '.join(header)}</tr></thead>
209
- <tbody>{''.join(f'<tr>{" ".join(row)}</tr>' for row in rows)}</tbody>
210
- </table>'''
211
-
212
- # %% ../nbs/api/08_showdoc.ipynb
213
- def _html_link(url, txt): return f'<a href="{url}" target="_blank" rel="noreferrer noopener">{txt}</a>'
214
-
215
- # %% ../nbs/api/08_showdoc.ipynb
216
- class BasicHtmlRenderer(ShowDocRenderer):
217
- "HTML renderer for `show_doc`"
218
- def _repr_html_(self):
219
- doc = '<hr/>\n'
220
- src = NbdevLookup().code(self.fn)
221
- doc += f'<h{self.title_level}>{self.nm}</h{self.title_level}>\n'
222
- sig = _fmt_sig(self.sig) if self.sig else ''
223
- # Escape < and > characters in the signature
224
- sig = sig.replace('<', '&lt;').replace('>', '&gt;')
225
- doc += f'<blockquote><pre><code>{self.nm} {sig}</code></pre></blockquote>'
226
- if self.docs:
227
- doc += f"<p><i>{self.docs}</i></p>"
228
- if src: doc += f"<br/>{_html_link(src, 'source')}"
229
- if self.dm.has_docment: doc += _create_html_table(str(self.dm))
230
- return doc
231
-
232
- def doc(self):
233
- "Show `show_doc` info along with link to docs"
234
- from IPython.display import display,HTML
235
- res = self._repr_html_()
236
- display(HTML(res))
237
-
238
- # %% ../nbs/api/08_showdoc.ipynb
239
- def doc(elt):
240
- "Show `show_doc` info along with link to docs"
241
- BasicHtmlRenderer(elt).doc()
242
-
243
- # %% ../nbs/api/08_showdoc.ipynb
244
- def showdoc_nm(tree):
245
- "Get the fully qualified name for showdoc."
246
- return ifnone(patch_name(tree), tree.name)
247
-
248
- # %% ../nbs/api/08_showdoc.ipynb
249
- def colab_link(path):
250
- "Get a link to the notebook at `path` on Colab"
251
- from IPython.display import Markdown
252
- cfg = get_config()
253
- pre = 'https://colab.research.google.com/github/'
254
- res = f'{pre}{cfg.user}/{cfg.repo}/blob/{cfg.branch}/{cfg.nbs_path.name}/{path}.ipynb'
255
- display(Markdown(f'[Open `{path}` in Colab]({res})'))
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes