nbdev 2.3.34__tar.gz → 2.4.9__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.3.34/nbdev.egg-info → nbdev-2.4.9}/PKG-INFO +22 -7
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev/__init__.py +1 -1
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev/_modidx.py +12 -30
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev/clean.py +1 -1
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev/cli.py +13 -5
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev/config.py +34 -6
- nbdev-2.4.9/nbdev/diff.py +92 -0
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev/doclinks.py +18 -8
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev/export.py +3 -2
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev/maker.py +7 -7
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev/process.py +1 -1
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev/quarto.py +39 -4
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev/release.py +15 -7
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev/serve.py +2 -1
- nbdev-2.4.9/nbdev/showdoc.py +113 -0
- {nbdev-2.3.34 → nbdev-2.4.9/nbdev.egg-info}/PKG-INFO +22 -7
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev.egg-info/SOURCES.txt +1 -0
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev.egg-info/entry_points.txt +1 -0
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev.egg-info/requires.txt +5 -2
- nbdev-2.4.9/pyproject.toml +11 -0
- {nbdev-2.3.34 → nbdev-2.4.9}/settings.ini +7 -5
- {nbdev-2.3.34 → nbdev-2.4.9}/setup.py +0 -3
- nbdev-2.3.34/nbdev/showdoc.py +0 -255
- nbdev-2.3.34/pyproject.toml +0 -3
- {nbdev-2.3.34 → nbdev-2.4.9}/CONTRIBUTING.md +0 -0
- {nbdev-2.3.34 → nbdev-2.4.9}/LICENSE +0 -0
- {nbdev-2.3.34 → nbdev-2.4.9}/MANIFEST.in +0 -0
- {nbdev-2.3.34 → nbdev-2.4.9}/README.md +0 -0
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev/extract_attachments.py +0 -0
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev/frontmatter.py +0 -0
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev/imports.py +0 -0
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev/merge.py +0 -0
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev/migrate.py +0 -0
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev/processors.py +0 -0
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev/qmd.py +0 -0
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev/serve_drv.py +0 -0
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev/sync.py +0 -0
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev/test.py +0 -0
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev.egg-info/dependency_links.txt +0 -0
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev.egg-info/not-zip-safe +0 -0
- {nbdev-2.3.34 → nbdev-2.4.9}/nbdev.egg-info/top_level.txt +0 -0
- {nbdev-2.3.34 → nbdev-2.4.9}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: nbdev
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.9
|
|
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
|
|
@@ -11,24 +11,24 @@ Keywords: nbdev fastai jupyter notebook export
|
|
|
11
11
|
Classifier: Development Status :: 5 - Production/Stable
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
13
13
|
Classifier: Natural Language :: English
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
16
14
|
Classifier: Programming Language :: Python :: 3.9
|
|
17
15
|
Classifier: Programming Language :: Python :: 3.10
|
|
18
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
17
|
Classifier: Programming Language :: Python :: 3.13
|
|
20
18
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
21
|
-
Requires-Python: >=3.
|
|
19
|
+
Requires-Python: >=3.9
|
|
22
20
|
Description-Content-Type: text/markdown
|
|
23
21
|
License-File: LICENSE
|
|
24
22
|
Requires-Dist: packaging
|
|
25
|
-
Requires-Dist: fastcore>=1.
|
|
26
|
-
Requires-Dist: execnb>=0.1.
|
|
23
|
+
Requires-Dist: fastcore>=1.11.0
|
|
24
|
+
Requires-Dist: execnb>=0.1.12
|
|
27
25
|
Requires-Dist: astunparse
|
|
28
26
|
Requires-Dist: ghapi>=1.0.3
|
|
29
27
|
Requires-Dist: watchdog
|
|
30
28
|
Requires-Dist: asttokens
|
|
31
29
|
Requires-Dist: setuptools
|
|
30
|
+
Requires-Dist: build
|
|
31
|
+
Requires-Dist: fastgit
|
|
32
32
|
Requires-Dist: PyYAML
|
|
33
33
|
Provides-Extra: dev
|
|
34
34
|
Requires-Dist: ipywidgets; extra == "dev"
|
|
@@ -42,6 +42,21 @@ Requires-Dist: nbclassic; extra == "dev"
|
|
|
42
42
|
Requires-Dist: pysymbol_llm; extra == "dev"
|
|
43
43
|
Requires-Dist: llms-txt; extra == "dev"
|
|
44
44
|
Requires-Dist: sphinx; extra == "dev"
|
|
45
|
+
Requires-Dist: plum-dispatch; extra == "dev"
|
|
46
|
+
Dynamic: author
|
|
47
|
+
Dynamic: author-email
|
|
48
|
+
Dynamic: classifier
|
|
49
|
+
Dynamic: description
|
|
50
|
+
Dynamic: description-content-type
|
|
51
|
+
Dynamic: home-page
|
|
52
|
+
Dynamic: keywords
|
|
53
|
+
Dynamic: license
|
|
54
|
+
Dynamic: license-file
|
|
55
|
+
Dynamic: project-url
|
|
56
|
+
Dynamic: provides-extra
|
|
57
|
+
Dynamic: requires-dist
|
|
58
|
+
Dynamic: requires-python
|
|
59
|
+
Dynamic: summary
|
|
45
60
|
|
|
46
61
|
# Getting Started
|
|
47
62
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Autogenerated by nbdev
|
|
2
2
|
|
|
3
|
-
d = { 'settings': { 'branch': '
|
|
3
|
+
d = { 'settings': { 'branch': 'main',
|
|
4
4
|
'doc_baseurl': '/',
|
|
5
5
|
'doc_host': 'https://nbdev.fast.ai',
|
|
6
6
|
'git_url': 'https://github.com/AnswerDotAI/nbdev',
|
|
@@ -46,8 +46,16 @@ d = { 'settings': { 'branch': 'master',
|
|
|
46
46
|
'nbdev.config.is_nbdev': ('api/config.html#is_nbdev', 'nbdev/config.py'),
|
|
47
47
|
'nbdev.config.nbdev_create_config': ('api/config.html#nbdev_create_config', 'nbdev/config.py'),
|
|
48
48
|
'nbdev.config.show_src': ('api/config.html#show_src', 'nbdev/config.py'),
|
|
49
|
+
'nbdev.config.update_proj': ('api/config.html#update_proj', 'nbdev/config.py'),
|
|
49
50
|
'nbdev.config.update_version': ('api/config.html#update_version', 'nbdev/config.py'),
|
|
50
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')},
|
|
51
59
|
'nbdev.doclinks': { 'nbdev.doclinks.NbdevLookup': ('api/doclinks.html#nbdevlookup', 'nbdev/doclinks.py'),
|
|
52
60
|
'nbdev.doclinks.NbdevLookup.__getitem__': ( 'api/doclinks.html#nbdevlookup.__getitem__',
|
|
53
61
|
'nbdev/doclinks.py'),
|
|
@@ -257,20 +265,22 @@ d = { 'settings': { 'branch': 'master',
|
|
|
257
265
|
'nbdev.quarto._SidebarYmlRemoved.__init__': ( 'api/quarto.html#_sidebarymlremoved.__init__',
|
|
258
266
|
'nbdev/quarto.py'),
|
|
259
267
|
'nbdev.quarto._copytree': ('api/quarto.html#_copytree', 'nbdev/quarto.py'),
|
|
268
|
+
'nbdev.quarto._doc_mtime_not_older': ('api/quarto.html#_doc_mtime_not_older', 'nbdev/quarto.py'),
|
|
260
269
|
'nbdev.quarto._ensure_quarto': ('api/quarto.html#_ensure_quarto', 'nbdev/quarto.py'),
|
|
261
270
|
'nbdev.quarto._install_linux': ('api/quarto.html#_install_linux', 'nbdev/quarto.py'),
|
|
262
271
|
'nbdev.quarto._install_mac': ('api/quarto.html#_install_mac', 'nbdev/quarto.py'),
|
|
263
272
|
'nbdev.quarto._nbglob_docs': ('api/quarto.html#_nbglob_docs', 'nbdev/quarto.py'),
|
|
264
273
|
'nbdev.quarto._pre': ('api/quarto.html#_pre', 'nbdev/quarto.py'),
|
|
265
274
|
'nbdev.quarto._pre_docs': ('api/quarto.html#_pre_docs', 'nbdev/quarto.py'),
|
|
266
|
-
'nbdev.quarto._readme_mtime_not_older': ('api/quarto.html#_readme_mtime_not_older', 'nbdev/quarto.py'),
|
|
267
275
|
'nbdev.quarto._recursive_parser': ('api/quarto.html#_recursive_parser', 'nbdev/quarto.py'),
|
|
276
|
+
'nbdev.quarto._save_cached_contributing': ('api/quarto.html#_save_cached_contributing', 'nbdev/quarto.py'),
|
|
268
277
|
'nbdev.quarto._save_cached_readme': ('api/quarto.html#_save_cached_readme', 'nbdev/quarto.py'),
|
|
269
278
|
'nbdev.quarto._sort': ('api/quarto.html#_sort', 'nbdev/quarto.py'),
|
|
270
279
|
'nbdev.quarto._sprun': ('api/quarto.html#_sprun', 'nbdev/quarto.py'),
|
|
271
280
|
'nbdev.quarto.fs_watchdog': ('api/quarto.html#fs_watchdog', 'nbdev/quarto.py'),
|
|
272
281
|
'nbdev.quarto.install': ('api/quarto.html#install', 'nbdev/quarto.py'),
|
|
273
282
|
'nbdev.quarto.install_quarto': ('api/quarto.html#install_quarto', 'nbdev/quarto.py'),
|
|
283
|
+
'nbdev.quarto.nbdev_contributing': ('api/quarto.html#nbdev_contributing', 'nbdev/quarto.py'),
|
|
274
284
|
'nbdev.quarto.nbdev_docs': ('api/quarto.html#nbdev_docs', 'nbdev/quarto.py'),
|
|
275
285
|
'nbdev.quarto.nbdev_preview': ('api/quarto.html#nbdev_preview', 'nbdev/quarto.py'),
|
|
276
286
|
'nbdev.quarto.nbdev_proc_nbs': ('api/quarto.html#nbdev_proc_nbs', 'nbdev/quarto.py'),
|
|
@@ -319,37 +329,9 @@ d = { 'settings': { 'branch': 'master',
|
|
|
319
329
|
'nbdev.showdoc.BasicMarkdownRenderer': ('api/showdoc.html#basicmarkdownrenderer', 'nbdev/showdoc.py'),
|
|
320
330
|
'nbdev.showdoc.BasicMarkdownRenderer._repr_markdown_': ( 'api/showdoc.html#basicmarkdownrenderer._repr_markdown_',
|
|
321
331
|
'nbdev/showdoc.py'),
|
|
322
|
-
'nbdev.showdoc.DocmentTbl': ('api/showdoc.html#docmenttbl', 'nbdev/showdoc.py'),
|
|
323
|
-
'nbdev.showdoc.DocmentTbl.__eq__': ('api/showdoc.html#docmenttbl.__eq__', 'nbdev/showdoc.py'),
|
|
324
|
-
'nbdev.showdoc.DocmentTbl.__init__': ('api/showdoc.html#docmenttbl.__init__', 'nbdev/showdoc.py'),
|
|
325
|
-
'nbdev.showdoc.DocmentTbl._columns': ('api/showdoc.html#docmenttbl._columns', 'nbdev/showdoc.py'),
|
|
326
|
-
'nbdev.showdoc.DocmentTbl._hdr_list': ('api/showdoc.html#docmenttbl._hdr_list', 'nbdev/showdoc.py'),
|
|
327
|
-
'nbdev.showdoc.DocmentTbl._repr_markdown_': ( 'api/showdoc.html#docmenttbl._repr_markdown_',
|
|
328
|
-
'nbdev/showdoc.py'),
|
|
329
|
-
'nbdev.showdoc.DocmentTbl._row': ('api/showdoc.html#docmenttbl._row', 'nbdev/showdoc.py'),
|
|
330
|
-
'nbdev.showdoc.DocmentTbl._row_list': ('api/showdoc.html#docmenttbl._row_list', 'nbdev/showdoc.py'),
|
|
331
|
-
'nbdev.showdoc.DocmentTbl.has_docment': ('api/showdoc.html#docmenttbl.has_docment', 'nbdev/showdoc.py'),
|
|
332
|
-
'nbdev.showdoc.DocmentTbl.has_return': ('api/showdoc.html#docmenttbl.has_return', 'nbdev/showdoc.py'),
|
|
333
|
-
'nbdev.showdoc.DocmentTbl.hdr_str': ('api/showdoc.html#docmenttbl.hdr_str', 'nbdev/showdoc.py'),
|
|
334
|
-
'nbdev.showdoc.DocmentTbl.params_str': ('api/showdoc.html#docmenttbl.params_str', 'nbdev/showdoc.py'),
|
|
335
|
-
'nbdev.showdoc.DocmentTbl.return_str': ('api/showdoc.html#docmenttbl.return_str', 'nbdev/showdoc.py'),
|
|
336
|
-
'nbdev.showdoc.ShowDocRenderer': ('api/showdoc.html#showdocrenderer', 'nbdev/showdoc.py'),
|
|
337
|
-
'nbdev.showdoc.ShowDocRenderer.__init__': ('api/showdoc.html#showdocrenderer.__init__', 'nbdev/showdoc.py'),
|
|
338
|
-
'nbdev.showdoc._bold': ('api/showdoc.html#_bold', 'nbdev/showdoc.py'),
|
|
339
332
|
'nbdev.showdoc._create_html_table': ('api/showdoc.html#_create_html_table', 'nbdev/showdoc.py'),
|
|
340
|
-
'nbdev.showdoc._docstring': ('api/showdoc.html#_docstring', 'nbdev/showdoc.py'),
|
|
341
|
-
'nbdev.showdoc._escape_markdown': ('api/showdoc.html#_escape_markdown', 'nbdev/showdoc.py'),
|
|
342
333
|
'nbdev.showdoc._ext_link': ('api/showdoc.html#_ext_link', 'nbdev/showdoc.py'),
|
|
343
|
-
'nbdev.showdoc._f_name': ('api/showdoc.html#_f_name', 'nbdev/showdoc.py'),
|
|
344
|
-
'nbdev.showdoc._fmt_anno': ('api/showdoc.html#_fmt_anno', 'nbdev/showdoc.py'),
|
|
345
|
-
'nbdev.showdoc._fmt_sig': ('api/showdoc.html#_fmt_sig', 'nbdev/showdoc.py'),
|
|
346
|
-
'nbdev.showdoc._fullname': ('api/showdoc.html#_fullname', 'nbdev/showdoc.py'),
|
|
347
334
|
'nbdev.showdoc._html_link': ('api/showdoc.html#_html_link', 'nbdev/showdoc.py'),
|
|
348
|
-
'nbdev.showdoc._list2row': ('api/showdoc.html#_list2row', 'nbdev/showdoc.py'),
|
|
349
|
-
'nbdev.showdoc._maybe_nm': ('api/showdoc.html#_maybe_nm', 'nbdev/showdoc.py'),
|
|
350
|
-
'nbdev.showdoc._non_empty_keys': ('api/showdoc.html#_non_empty_keys', 'nbdev/showdoc.py'),
|
|
351
|
-
'nbdev.showdoc._show_param': ('api/showdoc.html#_show_param', 'nbdev/showdoc.py'),
|
|
352
|
-
'nbdev.showdoc._wrap_sig': ('api/showdoc.html#_wrap_sig', 'nbdev/showdoc.py'),
|
|
353
335
|
'nbdev.showdoc.colab_link': ('api/showdoc.html#colab_link', 'nbdev/showdoc.py'),
|
|
354
336
|
'nbdev.showdoc.doc': ('api/showdoc.html#doc', 'nbdev/showdoc.py'),
|
|
355
337
|
'nbdev.showdoc.show_doc': ('api/showdoc.html#show_doc', 'nbdev/showdoc.py'),
|
|
@@ -69,7 +69,7 @@ def _clean_cell_output(cell, clean_ids):
|
|
|
69
69
|
if k.startswith('text') and clean_ids: data[k] = _clean_cell_output_id(data[k])
|
|
70
70
|
if k.startswith('image') and "svg" not in k: data[k] = data[k].rstrip()
|
|
71
71
|
if 'text' in o and clean_ids: o['text'] = _clean_cell_output_id(o['text'])
|
|
72
|
-
|
|
72
|
+
# o.get('metadata', {}).pop('tags', None)
|
|
73
73
|
|
|
74
74
|
# %% ../nbs/api/11_clean.ipynb
|
|
75
75
|
def _clean_cell(cell, clear_all, allowed_metadata_keys, clean_ids):
|
|
@@ -13,7 +13,7 @@ from .processors import *
|
|
|
13
13
|
from .doclinks import *
|
|
14
14
|
from .test import *
|
|
15
15
|
from .clean import *
|
|
16
|
-
from .quarto import nbdev_readme, refresh_quarto_yml, fs_watchdog
|
|
16
|
+
from .quarto import nbdev_readme, nbdev_contributing, refresh_quarto_yml, fs_watchdog
|
|
17
17
|
from .export import nb_export
|
|
18
18
|
from .frontmatter import FrontmatterProc
|
|
19
19
|
|
|
@@ -91,7 +91,7 @@ def nbdev_new(**kwargs):
|
|
|
91
91
|
_update_repo_meta(cfg)
|
|
92
92
|
path = Path()
|
|
93
93
|
|
|
94
|
-
_ORG_OR_USR,_REPOSITORY = '
|
|
94
|
+
_ORG_OR_USR,_REPOSITORY = 'answerdotai','nbdev-template'
|
|
95
95
|
_TEMPLATE = f'{_ORG_OR_USR}/{_REPOSITORY}'
|
|
96
96
|
template = kwargs.get('template', _TEMPLATE)
|
|
97
97
|
try: org_or_usr, repo = template.split('/')
|
|
@@ -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)
|
|
@@ -121,6 +122,7 @@ def nbdev_new(**kwargs):
|
|
|
121
122
|
refresh_quarto_yml()
|
|
122
123
|
nbdev_export.__wrapped__()
|
|
123
124
|
nbdev_readme.__wrapped__()
|
|
125
|
+
nbdev_contributing.__wrapped__()
|
|
124
126
|
|
|
125
127
|
# %% ../nbs/api/13_cli.ipynb
|
|
126
128
|
mapping = {
|
|
@@ -183,10 +185,16 @@ def watch_export(nbs:str=None, # Nb directory to watch for changes
|
|
|
183
185
|
lib = lib or (cfg.lib_path if cfg else '.')
|
|
184
186
|
if cfg and (nbs != cfg.nbs_path or lib != cfg.lib_path) and not force:
|
|
185
187
|
raise ValueError("In nbdev project. Use --force to override config.")
|
|
188
|
+
run(f'nbdev_export')
|
|
186
189
|
def _export(e,lib=lib):
|
|
187
190
|
p = e.src_path
|
|
188
|
-
if (not '.ipynb_checkpoints' in p and p.endswith('.ipynb') and not Path(p).name.startswith('.~')):
|
|
189
|
-
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}"')
|
|
190
198
|
with fs_watchdog(_export, nbs):
|
|
191
199
|
while True: time.sleep(1)
|
|
192
200
|
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/01_config.ipynb.
|
|
4
4
|
|
|
5
5
|
# %% auto 0
|
|
6
|
-
__all__ = ['nbdev_create_config', 'get_config', 'config_key', 'is_nbdev', 'create_output', 'show_src',
|
|
7
|
-
'add_init', 'write_cells']
|
|
6
|
+
__all__ = ['pyproj_tmpl', 'nbdev_create_config', 'get_config', 'config_key', 'is_nbdev', 'create_output', 'show_src',
|
|
7
|
+
'update_version', 'update_proj', 'add_init', 'write_cells']
|
|
8
8
|
|
|
9
9
|
# %% ../nbs/api/01_config.ipynb
|
|
10
10
|
from datetime import datetime
|
|
@@ -49,7 +49,7 @@ def _apply_defaults(
|
|
|
49
49
|
license='apache2', # License for the package
|
|
50
50
|
copyright:str=None, # Copyright for the package, defaults to '`current_year` onwards, `author`'
|
|
51
51
|
status='3', # Development status PyPI classifier
|
|
52
|
-
min_python='3.
|
|
52
|
+
min_python='3.9', # Minimum Python version PyPI classifier
|
|
53
53
|
audience='Developers', # Intended audience PyPI classifier
|
|
54
54
|
language='English', # Language PyPI classifier
|
|
55
55
|
recursive:bool_arg=True, # Include subfolders in notebook globs?
|
|
@@ -63,6 +63,7 @@ def _apply_defaults(
|
|
|
63
63
|
clear_all:bool_arg=False, # Remove all cell metadata and cell outputs?
|
|
64
64
|
cell_number:bool_arg=True, # Add cell number to the exported file
|
|
65
65
|
put_version_in_init:bool_arg=True, # Add the version to the main __init__.py in nbdev_export
|
|
66
|
+
update_pyproject:bool_arg=True, # Create/update pyproject.toml with correct project name
|
|
66
67
|
skip_procs:str='', # A comma-separated list of processors that you want to skip
|
|
67
68
|
):
|
|
68
69
|
"Apply default settings where missing in `cfg`."
|
|
@@ -142,7 +143,7 @@ _nbdev_cfg_head = '''# All sections below are required unless otherwise specifie
|
|
|
142
143
|
|
|
143
144
|
'''
|
|
144
145
|
_nbdev_cfg_sections = {'Python library': 'repo lib_name version min_python license black_formatting',
|
|
145
|
-
'nbdev': 'doc_path lib_path nbs_path recursive tst_flags put_version_in_init',
|
|
146
|
+
'nbdev': 'doc_path lib_path nbs_path recursive tst_flags put_version_in_init update_pyproject',
|
|
146
147
|
'Docs': 'branch custom_sidebar doc_host doc_baseurl git_url title',
|
|
147
148
|
'PyPI': 'audience author author_email copyright description keywords language status user'}
|
|
148
149
|
_nbdev_cfg_tail = '''### Optional ###
|
|
@@ -219,9 +220,26 @@ def create_output(txt, mime):
|
|
|
219
220
|
# %% ../nbs/api/01_config.ipynb
|
|
220
221
|
def show_src(src, lang='python'): return Markdown(f'```{lang}\n{src}\n```')
|
|
221
222
|
|
|
223
|
+
# %% ../nbs/api/01_config.ipynb
|
|
224
|
+
pyproj_tmpl = """[build-system]
|
|
225
|
+
requires = ["setuptools>=64.0"]
|
|
226
|
+
build-backend = "setuptools.build_meta"
|
|
227
|
+
|
|
228
|
+
[project]
|
|
229
|
+
name = "FILL_IN"
|
|
230
|
+
requires-python="FILL_IN"
|
|
231
|
+
dynamic = [ "keywords", "description", "version", "dependencies", "optional-dependencies", "readme", "license", "authors", "classifiers", "entry-points", "scripts", "urls"]
|
|
232
|
+
|
|
233
|
+
[tool.uv]
|
|
234
|
+
cache-keys = [{ file = "pyproject.toml" }, { file = "settings.ini" }, { file = "setup.py" }]
|
|
235
|
+
"""
|
|
236
|
+
|
|
222
237
|
# %% ../nbs/api/01_config.ipynb
|
|
223
238
|
_re_version = re.compile(r'^__version__\s*=.*$', re.MULTILINE)
|
|
239
|
+
_re_proj = re.compile(r'^name\s*=\s*".*$', re.MULTILINE)
|
|
240
|
+
_re_reqpy = re.compile(r'^requires-python\s*=\s*".*$', re.MULTILINE)
|
|
224
241
|
_init = '__init__.py'
|
|
242
|
+
_pyproj = 'pyproject.toml'
|
|
225
243
|
|
|
226
244
|
def update_version(path=None):
|
|
227
245
|
"Add or update `__version__` in the main `__init__.py` of the library."
|
|
@@ -236,6 +254,15 @@ def update_version(path=None):
|
|
|
236
254
|
|
|
237
255
|
def _has_py(fs): return any(1 for f in fs if f.endswith('.py'))
|
|
238
256
|
|
|
257
|
+
def update_proj(path):
|
|
258
|
+
"Create or update `pyproject.toml` in the project root."
|
|
259
|
+
fname = path/_pyproj
|
|
260
|
+
if not fname.exists(): fname.write_text(pyproj_tmpl)
|
|
261
|
+
txt = fname.read_text()
|
|
262
|
+
txt = _re_proj.sub(f'name="{get_config().lib_name}"', txt)
|
|
263
|
+
txt = _re_reqpy.sub(f'requires-python=">={get_config().min_python}"', txt)
|
|
264
|
+
fname.write_text(txt)
|
|
265
|
+
|
|
239
266
|
def add_init(path=None):
|
|
240
267
|
"Add `__init__.py` in all subdirs of `path` containing python files if it's not there already."
|
|
241
268
|
# we add the lowest-level `__init__.py` files first, which ensures _has_py succeeds for parent modules
|
|
@@ -247,14 +274,15 @@ def add_init(path=None):
|
|
|
247
274
|
subds = (os.listdir(r/d) for d in ds)
|
|
248
275
|
if _has_py(fs) or any(filter(_has_py, subds)) and not (r/_init).exists(): (r/_init).touch()
|
|
249
276
|
if get_config().get('put_version_in_init', True): update_version(path)
|
|
277
|
+
if get_config().get('update_pyproject', True): update_proj(path.parent)
|
|
250
278
|
|
|
251
279
|
# %% ../nbs/api/01_config.ipynb
|
|
252
|
-
def write_cells(cells, hdr, file, offset=0, cell_number=True):
|
|
280
|
+
def write_cells(cells, hdr, file, offset=0, cell_number=True, solo_nb=False):
|
|
253
281
|
"Write `cells` to `file` along with header `hdr` starting at index `offset` (mainly for nbdev internal use)."
|
|
254
282
|
for cell in cells:
|
|
255
283
|
if cell.cell_type=='code' and cell.source.strip():
|
|
256
284
|
idx = f" {cell.idx_+offset}" if cell_number else ""
|
|
257
|
-
file.write(f'\n\n{hdr}{idx}\n{cell.source}')
|
|
285
|
+
file.write(f'\n\n{hdr}{idx}\n{cell.source}') if not solo_nb else file.write(f'\n\n{cell.source}')
|
|
258
286
|
|
|
259
287
|
# %% ../nbs/api/01_config.ipynb
|
|
260
288
|
def _basic_export_nb(fname, name, dest=None):
|
|
@@ -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)
|
|
@@ -17,7 +17,7 @@ from fastcore.meta import delegates
|
|
|
17
17
|
from fastcore.net import urlread
|
|
18
18
|
|
|
19
19
|
import ast,builtins,contextlib
|
|
20
|
-
import
|
|
20
|
+
import importlib
|
|
21
21
|
|
|
22
22
|
from astunparse import unparse
|
|
23
23
|
from io import BytesIO
|
|
@@ -27,6 +27,8 @@ from urllib.parse import urljoin
|
|
|
27
27
|
from functools import lru_cache
|
|
28
28
|
from types import ModuleType
|
|
29
29
|
|
|
30
|
+
from importlib.metadata import entry_points
|
|
31
|
+
|
|
30
32
|
# %% ../nbs/api/05_doclinks.ipynb
|
|
31
33
|
def _sym_nm(klas, sym): return f'{unparse(klas).strip()}.{sym.name}'
|
|
32
34
|
|
|
@@ -111,7 +113,8 @@ def _build_modidx(dest=None, nbs_path=None, skip_exists=False):
|
|
|
111
113
|
if k in ('doc_host','doc_baseurl','lib_path','git_url','branch')}
|
|
112
114
|
code_root = dest.parent.resolve()
|
|
113
115
|
for file in globtastic(dest, file_glob="*.py", skip_file_re='^_', skip_folder_re=r"\.ipynb_checkpoints"):
|
|
114
|
-
res['syms'].update(_get_modidx((dest.parent/file).resolve(), code_root, nbs_path=nbs_path))
|
|
116
|
+
try: res['syms'].update(_get_modidx((dest.parent/file).resolve(), code_root, nbs_path=nbs_path))
|
|
117
|
+
except ValueError: pass
|
|
115
118
|
idxfile.write_text("# Autogenerated by nbdev\n\nd = "+pformat(res, width=140, indent=2, compact=True)+'\n')
|
|
116
119
|
|
|
117
120
|
# %% ../nbs/api/05_doclinks.ipynb
|
|
@@ -236,17 +239,24 @@ def _build_lookup_table(strip_libs=None, incl_libs=None, skip_mods=None):
|
|
|
236
239
|
strip_libs = L(strip_libs)
|
|
237
240
|
if incl_libs is not None: incl_libs = (L(incl_libs)+strip_libs).unique()
|
|
238
241
|
entries = {}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
+
try: eps = entry_points(group='nbdev')
|
|
243
|
+
# Python 3.9 fallback - entry_points() doesn't accept group parameter
|
|
244
|
+
except TypeError: eps = entry_points().get('nbdev', [])
|
|
245
|
+
|
|
246
|
+
for o in eps:
|
|
247
|
+
if incl_libs is not None and o.dist.name not in incl_libs: continue
|
|
248
|
+
try: entries[o.name] = _qual_syms(o.load())
|
|
242
249
|
except Exception: pass
|
|
243
250
|
py_syms = merge(*L(o['syms'].values() for o in entries.values()).concat())
|
|
244
251
|
for m in strip_libs:
|
|
245
252
|
if m in entries:
|
|
246
253
|
_d = entries[m]
|
|
247
|
-
stripped = {
|
|
248
|
-
|
|
249
|
-
|
|
254
|
+
stripped = {}
|
|
255
|
+
for mod, dets in _d['syms'].items():
|
|
256
|
+
if mod not in skip_mods:
|
|
257
|
+
for k,v in dets.items():
|
|
258
|
+
k = remove_prefix(k,f"{mod}.")
|
|
259
|
+
if k not in stripped: stripped[k] = v
|
|
250
260
|
py_syms = merge(stripped, py_syms)
|
|
251
261
|
return entries,py_syms
|
|
252
262
|
|
|
@@ -73,6 +73,7 @@ def nb_export(nbname:str, # Filename of notebook
|
|
|
73
73
|
name:str=None, # Name of python script {name}.py to create.
|
|
74
74
|
mod_maker=ModuleMaker,
|
|
75
75
|
debug:bool=False, # Debug mode
|
|
76
|
+
solo_nb:bool=False # Export single notebook outside of an nbdev project.
|
|
76
77
|
):
|
|
77
78
|
"Create module(s) from notebook"
|
|
78
79
|
if lib_path is None: lib_path = get_config().lib_path if is_nbdev() else '.'
|
|
@@ -84,9 +85,9 @@ def nb_export(nbname:str, # Filename of notebook
|
|
|
84
85
|
all_cells = exp.in_all[mod]
|
|
85
86
|
nm = ifnone(name, getattr(exp, 'default_exp', None) if mod=='#' else mod)
|
|
86
87
|
if not nm:
|
|
87
|
-
warn(f"Notebook '{nbname}' uses `#|export` without `#|default_exp` cell.\n"
|
|
88
|
+
warn(f"Notebook '{nbname}' uses `#| export` without `#| default_exp` cell.\n"
|
|
88
89
|
"Note nbdev2 no longer supports nbdev1 syntax. Run `nbdev_migrate` to upgrade.\n"
|
|
89
90
|
"See https://nbdev.fast.ai/getting_started.html for more information.")
|
|
90
91
|
return
|
|
91
|
-
mm = mod_maker(dest=lib_path, name=nm, nb_path=nbname, is_new=bool(name) or mod=='#')
|
|
92
|
+
mm = mod_maker(dest=lib_path, name=nm, nb_path=nbname, is_new=bool(name) or mod=='#', solo_nb=solo_nb)
|
|
92
93
|
mm.make(cells, all_cells, lib_path=lib_path)
|
|
@@ -63,7 +63,7 @@ def update_var(varname, func, fn=None, code=None):
|
|
|
63
63
|
# %% ../nbs/api/02_maker.ipynb
|
|
64
64
|
class ModuleMaker:
|
|
65
65
|
"Helper class to create exported library from notebook source cells"
|
|
66
|
-
def __init__(self, dest, name, nb_path, is_new=True, parse=True):
|
|
66
|
+
def __init__(self, dest, name, nb_path, is_new=True, parse=True, solo_nb=False):
|
|
67
67
|
dest,nb_path = Path(dest),Path(nb_path)
|
|
68
68
|
store_attr()
|
|
69
69
|
self.fname = dest/(name.replace('.','/') + ".py")
|
|
@@ -170,10 +170,10 @@ def _last_future(self:ModuleMaker, cells):
|
|
|
170
170
|
except ValueError: return 0
|
|
171
171
|
|
|
172
172
|
# %% ../nbs/api/02_maker.ipynb
|
|
173
|
-
def _import2relative(cells,
|
|
174
|
-
"Converts `cells` to use `import2relative` based on `
|
|
175
|
-
if
|
|
176
|
-
for cell in cells: cell.import2relative(
|
|
173
|
+
def _import2relative(cells, lib_path=None):
|
|
174
|
+
"Converts `cells` to use `import2relative` based on `lib_path`"
|
|
175
|
+
if lib_path is None: lib_path = get_config().lib_path
|
|
176
|
+
for cell in cells: cell.import2relative(lib_path)
|
|
177
177
|
|
|
178
178
|
# %% ../nbs/api/02_maker.ipynb
|
|
179
179
|
def _retr_mdoc(cells):
|
|
@@ -208,8 +208,8 @@ def make(self:ModuleMaker, cells, all_cells=None, lib_path=None):
|
|
|
208
208
|
f.write(_retr_mdoc(cells))
|
|
209
209
|
f.write(f"# AUTOGENERATED! DO NOT EDIT! File to edit: {self.dest2nb}.")
|
|
210
210
|
if last_future > 0: write_cells(cells[:last_future], self.hdr, f)
|
|
211
|
-
if self.parse: f.write(f"\n\n# %% auto 0\n__all__ = {all_str}")
|
|
212
|
-
write_cells(cells[last_future:], self.hdr, f, cell_number=get_config().cell_number)
|
|
211
|
+
if self.parse and not self.solo_nb: f.write(f"\n\n# %% auto 0\n__all__ = {all_str}")
|
|
212
|
+
write_cells(cells[last_future:], self.hdr, f, cell_number=get_config().cell_number, solo_nb=self.solo_nb)
|
|
213
213
|
f.write('\n')
|
|
214
214
|
|
|
215
215
|
# %% ../nbs/api/02_maker.ipynb
|
|
@@ -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
|
|
@@ -21,7 +21,8 @@ import yaml
|
|
|
21
21
|
|
|
22
22
|
# %% auto 0
|
|
23
23
|
__all__ = ['BASE_QUARTO_URL', 'install_quarto', 'install', 'IndentDumper', 'nbdev_sidebar', 'refresh_quarto_yml',
|
|
24
|
-
'nbdev_proc_nbs', 'nbdev_readme', 'nbdev_docs', 'prepare', 'fs_watchdog',
|
|
24
|
+
'nbdev_proc_nbs', 'nbdev_readme', 'nbdev_contributing', 'nbdev_docs', 'prepare', 'fs_watchdog',
|
|
25
|
+
'nbdev_preview']
|
|
25
26
|
|
|
26
27
|
# %% ../nbs/api/14_quarto.ipynb
|
|
27
28
|
def _sprun(cmd):
|
|
@@ -69,7 +70,7 @@ def _sort(a):
|
|
|
69
70
|
x,y = a
|
|
70
71
|
if y.startswith('index.'): return x,'00'
|
|
71
72
|
return a
|
|
72
|
-
#|export
|
|
73
|
+
#| export
|
|
73
74
|
_def_file_re = r'\.(?:ipynb|qmd|html)$'
|
|
74
75
|
|
|
75
76
|
@delegates(nbglob_cli)
|
|
@@ -214,7 +215,7 @@ def nbdev_proc_nbs(**kwargs):
|
|
|
214
215
|
_pre_docs(**kwargs)[0]
|
|
215
216
|
|
|
216
217
|
# %% ../nbs/api/14_quarto.ipynb
|
|
217
|
-
def
|
|
218
|
+
def _doc_mtime_not_older(readme_path, readme_nb_path):
|
|
218
219
|
if not readme_nb_path.exists():
|
|
219
220
|
print(f"Could not find {readme_nb_path}")
|
|
220
221
|
return True
|
|
@@ -259,7 +260,7 @@ def nbdev_readme(
|
|
|
259
260
|
"Create README.md from readme_nb (index.ipynb by default)"
|
|
260
261
|
cfg = get_config()
|
|
261
262
|
path = Path(path) if path else cfg.nbs_path
|
|
262
|
-
if chk_time and
|
|
263
|
+
if chk_time and _doc_mtime_not_older(cfg.config_path/'README.md', path/cfg.readme_nb): return
|
|
263
264
|
|
|
264
265
|
with _SidebarYmlRemoved(path): # to avoid rendering whole website
|
|
265
266
|
cache = proc_nbs(path)
|
|
@@ -267,6 +268,38 @@ def nbdev_readme(
|
|
|
267
268
|
|
|
268
269
|
_save_cached_readme(cache, cfg)
|
|
269
270
|
|
|
271
|
+
# %% ../nbs/api/14_quarto.ipynb
|
|
272
|
+
def _save_cached_contributing(cache, cfg, contrib_nb):
|
|
273
|
+
"Move CONTRIBUTING.md (and any `_files` assets) from the Quarto build cache to the repo root."
|
|
274
|
+
tmp_doc_path = cache / cfg.doc_path.name
|
|
275
|
+
contrib_file = tmp_doc_path / 'CONTRIBUTING.md'
|
|
276
|
+
if contrib_file.exists():
|
|
277
|
+
final_path = cfg.config_path / 'CONTRIBUTING.md'
|
|
278
|
+
if final_path.exists(): final_path.unlink() # py37 doesn't have `missing_ok`
|
|
279
|
+
move(contrib_file, final_path)
|
|
280
|
+
assets_folder = tmp_doc_path / (Path(contrib_nb).stem + '_files') # Supporting files for CONTRIBUTING
|
|
281
|
+
if assets_folder.exists(): _copytree(assets_folder, cfg.config_path / assets_folder.name)
|
|
282
|
+
|
|
283
|
+
# %% ../nbs/api/14_quarto.ipynb
|
|
284
|
+
@call_parse
|
|
285
|
+
def nbdev_contributing(
|
|
286
|
+
path:str=None, # Path to notebooks
|
|
287
|
+
chk_time:bool=False # Only build if out-of-date
|
|
288
|
+
):
|
|
289
|
+
"""Create CONTRIBUTING.md from contributing_nb (defaults to 'contributing.ipynb' if present). Skips if the file doesn't exist."""
|
|
290
|
+
cfg = get_config()
|
|
291
|
+
path = Path(path) if path else cfg.nbs_path
|
|
292
|
+
contrib_nb_name = cfg.get('contributing_nb', 'contributing.ipynb')
|
|
293
|
+
contrib_nb_path = path / contrib_nb_name
|
|
294
|
+
if not contrib_nb_path.exists(): return
|
|
295
|
+
if chk_time and _doc_mtime_not_older(cfg.config_path / 'CONTRIBUTING.md' , contrib_nb_path): return
|
|
296
|
+
|
|
297
|
+
with _SidebarYmlRemoved(path): # to avoid rendering whole website
|
|
298
|
+
cache = proc_nbs(path)
|
|
299
|
+
_sprun(f'cd "{cache}" && quarto render "{cache/contrib_nb_name}" -o CONTRIBUTING.md -t gfm --no-execute')
|
|
300
|
+
|
|
301
|
+
_save_cached_contributing(cache, cfg, contrib_nb_name)
|
|
302
|
+
|
|
270
303
|
# %% ../nbs/api/14_quarto.ipynb
|
|
271
304
|
@call_parse
|
|
272
305
|
@delegates(_nbglob_docs)
|
|
@@ -277,6 +310,7 @@ def nbdev_docs(
|
|
|
277
310
|
"Create Quarto docs and README.md"
|
|
278
311
|
cache,cfg,path = _pre_docs(path, n_workers=n_workers, **kwargs)
|
|
279
312
|
nbdev_readme.__wrapped__(path=path, chk_time=True)
|
|
313
|
+
nbdev_contributing.__wrapped__(path=path, chk_time=True)
|
|
280
314
|
_sprun(f'cd "{cache}" && quarto render --no-cache')
|
|
281
315
|
shutil.rmtree(cfg.doc_path, ignore_errors=True)
|
|
282
316
|
move(cache/cfg.doc_path.name, cfg.config_path)
|
|
@@ -291,6 +325,7 @@ def prepare():
|
|
|
291
325
|
nbdev.clean.nbdev_clean.__wrapped__()
|
|
292
326
|
refresh_quarto_yml()
|
|
293
327
|
nbdev_readme.__wrapped__(chk_time=True)
|
|
328
|
+
nbdev_contributing.__wrapped__(chk_time=True)
|
|
294
329
|
|
|
295
330
|
# %% ../nbs/api/14_quarto.ipynb
|
|
296
331
|
@contextmanager
|