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.
- {nbdev-2.4.6/nbdev.egg-info → nbdev-2.4.8}/PKG-INFO +2 -2
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/__init__.py +1 -1
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/_modidx.py +7 -28
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/cli.py +10 -3
- nbdev-2.4.8/nbdev/diff.py +92 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/export.py +1 -1
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/process.py +1 -1
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/quarto.py +1 -1
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/release.py +1 -1
- nbdev-2.4.8/nbdev/showdoc.py +113 -0
- {nbdev-2.4.6 → nbdev-2.4.8/nbdev.egg-info}/PKG-INFO +2 -2
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev.egg-info/SOURCES.txt +1 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev.egg-info/requires.txt +1 -1
- {nbdev-2.4.6 → nbdev-2.4.8}/settings.ini +2 -2
- nbdev-2.4.6/nbdev/showdoc.py +0 -255
- {nbdev-2.4.6 → nbdev-2.4.8}/CONTRIBUTING.md +0 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/LICENSE +0 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/MANIFEST.in +0 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/README.md +0 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/clean.py +0 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/config.py +0 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/doclinks.py +0 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/extract_attachments.py +0 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/frontmatter.py +0 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/imports.py +0 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/maker.py +0 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/merge.py +0 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/migrate.py +0 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/processors.py +0 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/qmd.py +0 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/serve.py +0 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/serve_drv.py +0 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/sync.py +0 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev/test.py +0 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev.egg-info/dependency_links.txt +0 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev.egg-info/entry_points.txt +0 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev.egg-info/not-zip-safe +0 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/nbdev.egg-info/top_level.txt +0 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/pyproject.toml +0 -0
- {nbdev-2.4.6 → nbdev-2.4.8}/setup.cfg +0 -0
- {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.
|
|
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.
|
|
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
|
|
@@ -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
|
|
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':
|
|
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
|
|
@@ -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('<', '<').replace('>', '>')
|
|
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.
|
|
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.
|
|
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
|
|
@@ -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.
|
|
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.
|
|
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
|
nbdev-2.4.6/nbdev/showdoc.py
DELETED
|
@@ -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('<', '<').replace('>', '>')
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|