Skip to content

Commit f3af3fe

Browse files
author
Eugene Wolfson
committed
Merge remote-tracking branch 'origin/master' into scrub-magics-squash
2 parents 9366c7f + 3acb976 commit f3af3fe

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+1275
-490
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
name: Bug report
3+
about: Create a minimal reproducible example to help us improve
4+
labels: ["bug"]
5+
6+
---
7+
8+
# Provide a minimally reproducible example
9+
10+
To maximize the chances of your issue being fixed, you should share a minimally reproducible example that allows us to reproduce your error. A good way to do this is to setup a new nbdev project which containts the minimal amount of code that reproduces your error.
11+
12+
If we are not able to reproduce your error, we may close your issue.
13+
14+
## Some background on minimal reproducible examples [^1]
15+
16+
The first benefit of a public reproduction is to prove that the problem is not caused by your environment or by a setting you left out of your description, thinking it wasn't relevant. If there were any doubts about whether you'd found a genuine problem before, they are usually removed once a reproduction is made.
17+
18+
Next, when a reproduction has minimal config and code, it can often let us narrow down or even identify the root cause, suggest workarounds, etc. This means we can often help you from code inspection alone.
19+
20+
Finally, by making the code/dependencies minimal, it usually makes the problem feasible to step through using a debugging if code inspection wasn't sufficient. Production repositories or non-minimal reproductions are often very difficult to debug because break points get triggered dozens or hundreds or times.
21+
22+
The basic idea of a minimal reproduction is to use the least amount of both code and config to trigger missing or wrong behavior. A minimal reproduction helps the developers see where the bug or missing feature is, and allows us to verify that the new code meets the requirements.
23+
24+
## Where to host your mimimal reproducible example
25+
26+
A new, **public** GitHub repo is the best place to host your minimal reproducible example.
27+
28+
[^1]: the below guidance was adapted [from this language](https://github.com/renovatebot/renovate/blob/main/docs/development/minimal-reproductions.md)

.github/workflows/deploy.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ jobs:
88
runs-on: ubuntu-latest
99
steps:
1010
- uses: fastai/workflows/quarto-ghp@master
11-
with: {pre: 1}
11+
# with: {pre: 1}

.pre-commit-hooks.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
name: nbdev_clean
44
entry: nbdev_clean
55
description: "Clean metadata from notebooks to avoid merge conflicts"
6-
language: system
6+
language: python
77
always_run: true
88
pass_filenames: false
99

CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,26 @@
22

33
<!-- do not remove -->
44

5+
## 2.3.11
6+
7+
### New Features
8+
9+
- add agplv3 license to project options ([#1268](https://github.com/fastai/nbdev/pull/1268)), thanks to [@joel-lbth](https://github.com/joel-lbth)
10+
- add 0 - Pre-planning status to project options ([#1262](https://github.com/fastai/nbdev/pull/1262)), thanks to [@ddobrinskiy](https://github.com/ddobrinskiy)
11+
- add conda installation docs to end-to-end tutorial ([#1215](https://github.com/fastai/nbdev/pull/1215)), thanks to [@restlessronin](https://github.com/restlessronin)
12+
13+
### Bugs Squashed
14+
15+
- Fix `nbdev_conda` error when there are prior release tarballs ([#1280](https://github.com/fastai/nbdev/pull/1280)), thanks to [@restlessronin](https://github.com/restlessronin)
16+
- delete build dir before pypi upload ([#1277](https://github.com/fastai/nbdev/pull/1277)), thanks to [@restlessronin](https://github.com/restlessronin)
17+
- copy contents of `_extensions` folder from nbs ([#1266](https://github.com/fastai/nbdev/pull/1266)), thanks to [@restlessronin](https://github.com/restlessronin)
18+
- Fix `nbdev_update` when `lib_name` and `lib_path` are not the same ([#1254](https://github.com/fastai/nbdev/pull/1254)), thanks to [@BirkhoffG](https://github.com/BirkhoffG)
19+
- Make `nbdev_create_config` write the `black_formatting` setting ([#1235](https://github.com/fastai/nbdev/pull/1235)), thanks to [@dmose](https://github.com/dmose)
20+
- fix order of categories for migration ([#1221](https://github.com/fastai/nbdev/pull/1221)), thanks to [@hamelsmu](https://github.com/hamelsmu)
21+
- make anaconda description links consistent with pypi ([#1214](https://github.com/fastai/nbdev/pull/1214)), thanks to [@restlessronin](https://github.com/restlessronin)
22+
- .get instead of acessing attr ([#1023](https://github.com/fastai/nbdev/pull/1023)), thanks to [@hamelsmu](https://github.com/hamelsmu)
23+
24+
525
## 2.3.9
626

727
### New Features

nbdev/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__ = "2.3.10"
1+
__version__ = "2.3.12"
22

33
from .doclinks import nbdev_export
44
from .showdoc import show_doc

nbdev/_modidx.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
'git_url': 'https://github.com/fastai/nbdev',
77
'lib_path': 'nbdev'},
88
'syms': { 'nbdev.clean': { 'nbdev.clean._add_jupyter_hooks': ('api/clean.html#_add_jupyter_hooks', 'nbdev/clean.py'),
9+
'nbdev.clean._add_trailing_n': ('api/clean.html#_add_trailing_n', 'nbdev/clean.py'),
910
'nbdev.clean._clean_cell': ('api/clean.html#_clean_cell', 'nbdev/clean.py'),
1011
'nbdev.clean._clean_cell_output': ('api/clean.html#_clean_cell_output', 'nbdev/clean.py'),
1112
'nbdev.clean._clean_cell_output_id': ('api/clean.html#_clean_cell_output_id', 'nbdev/clean.py'),
@@ -232,12 +233,22 @@
232233
'nbdev.qmd.meta': ('api/qmd.html#meta', 'nbdev/qmd.py'),
233234
'nbdev.qmd.tbl_row': ('api/qmd.html#tbl_row', 'nbdev/qmd.py'),
234235
'nbdev.qmd.tbl_sep': ('api/qmd.html#tbl_sep', 'nbdev/qmd.py')},
235-
'nbdev.quarto': { 'nbdev.quarto._ensure_quarto': ('api/quarto.html#_ensure_quarto', 'nbdev/quarto.py'),
236+
'nbdev.quarto': { 'nbdev.quarto._SidebarYmlRemoved': ('api/quarto.html#_sidebarymlremoved', 'nbdev/quarto.py'),
237+
'nbdev.quarto._SidebarYmlRemoved.__enter__': ( 'api/quarto.html#_sidebarymlremoved.__enter__',
238+
'nbdev/quarto.py'),
239+
'nbdev.quarto._SidebarYmlRemoved.__exit__': ( 'api/quarto.html#_sidebarymlremoved.__exit__',
240+
'nbdev/quarto.py'),
241+
'nbdev.quarto._SidebarYmlRemoved.__init__': ( 'api/quarto.html#_sidebarymlremoved.__init__',
242+
'nbdev/quarto.py'),
243+
'nbdev.quarto._copytree': ('api/quarto.html#_copytree', 'nbdev/quarto.py'),
244+
'nbdev.quarto._ensure_quarto': ('api/quarto.html#_ensure_quarto', 'nbdev/quarto.py'),
236245
'nbdev.quarto._install_linux': ('api/quarto.html#_install_linux', 'nbdev/quarto.py'),
237246
'nbdev.quarto._install_mac': ('api/quarto.html#_install_mac', 'nbdev/quarto.py'),
238247
'nbdev.quarto._nbglob_docs': ('api/quarto.html#_nbglob_docs', 'nbdev/quarto.py'),
239248
'nbdev.quarto._pre': ('api/quarto.html#_pre', 'nbdev/quarto.py'),
240249
'nbdev.quarto._pre_docs': ('api/quarto.html#_pre_docs', 'nbdev/quarto.py'),
250+
'nbdev.quarto._readme_mtime_not_older': ('api/quarto.html#_readme_mtime_not_older', 'nbdev/quarto.py'),
251+
'nbdev.quarto._save_cached_readme': ('api/quarto.html#_save_cached_readme', 'nbdev/quarto.py'),
241252
'nbdev.quarto._sort': ('api/quarto.html#_sort', 'nbdev/quarto.py'),
242253
'nbdev.quarto._sprun': ('api/quarto.html#_sprun', 'nbdev/quarto.py'),
243254
'nbdev.quarto.fs_watchdog': ('api/quarto.html#fs_watchdog', 'nbdev/quarto.py'),

nbdev/clean.py

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/clean.ipynb.
1+
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/11_clean.ipynb.
22

33
# %% auto 0
44
__all__ = ['nbdev_trust', 'clean_nb', 'process_write', 'nbdev_clean', 'clean_jupyter', 'nbdev_install_hooks']
55

6-
# %% ../nbs/api/clean.ipynb 2
6+
# %% ../nbs/api/11_clean.ipynb 2
77
import ast,warnings,stat
88
from astunparse import unparse
99
from textwrap import indent
@@ -18,7 +18,7 @@
1818
from .sync import *
1919
from .process import first_code_ln
2020

21-
# %% ../nbs/api/clean.ipynb 6
21+
# %% ../nbs/api/11_clean.ipynb 6
2222
@call_parse
2323
def nbdev_trust(
2424
fname:str=None, # A notebook name or glob to trust
@@ -44,7 +44,7 @@ def nbdev_trust(
4444
if not NotebookNotary().check_signature(nb): NotebookNotary().sign(nb)
4545
check_fname.touch(exist_ok=True)
4646

47-
# %% ../nbs/api/clean.ipynb 9
47+
# %% ../nbs/api/11_clean.ipynb 9
4848
_repr_id_re = re.compile('(<.*?)( at 0x[0-9a-fA-F]+)(>)')
4949

5050
_sub = partial(_repr_id_re.sub, r'\1\3')
@@ -54,21 +54,26 @@ def _skip_or_sub(x): return _sub(x) if "at 0x" in x else x
5454
def _clean_cell_output_id(lines):
5555
return _skip_or_sub(lines) if isinstance(lines,str) else [_skip_or_sub(o) for o in lines]
5656

57-
# %% ../nbs/api/clean.ipynb 11
57+
# %% ../nbs/api/11_clean.ipynb 11
58+
def _add_trailing_n(img):
59+
if not isinstance(img,str): return [ _add_trailing_n(o) for o in img ]
60+
return img + "\n" if img[-1] != "\n" else img
61+
62+
# %% ../nbs/api/11_clean.ipynb 12
5863
def _clean_cell_output(cell, clean_ids):
5964
"Remove `cell` output execution count and optionally ids from text reprs"
6065
outputs = cell.get('outputs', [])
6166
for o in outputs:
6267
if 'execution_count' in o: o['execution_count'] = None
6368
data = o.get('data', {})
6469
data.pop("application/vnd.google.colaboratory.intrinsic+json", None)
65-
if clean_ids:
66-
for k in data:
67-
if k.startswith('text'): data[k] = _clean_cell_output_id(data[k])
68-
if 'text' in o: o['text'] = _clean_cell_output_id(o['text'])
70+
for k in data:
71+
if k.startswith('text') and clean_ids: data[k] = _clean_cell_output_id(data[k])
72+
if k.startswith('image'): data[k] = _add_trailing_n(data[k])
73+
if 'text' in o and clean_ids: o['text'] = _clean_cell_output_id(o['text'])
6974
o.get('metadata', {}).pop('tags', None)
7075

71-
# %% ../nbs/api/clean.ipynb 12
76+
# %% ../nbs/api/11_clean.ipynb 13
7277
def _clean_cell(cell, clear_all, allowed_metadata_keys, clean_ids):
7378
"Clean `cell` by removing superfluous metadata or everything except the input if `clear_all`"
7479
if 'execution_count' in cell: cell['execution_count'] = None
@@ -79,7 +84,7 @@ def _clean_cell(cell, clear_all, allowed_metadata_keys, clean_ids):
7984
cell['metadata'] = {} if clear_all else {
8085
k:v for k,v in cell['metadata'].items() if k in allowed_metadata_keys}
8186

82-
# %% ../nbs/api/clean.ipynb 13
87+
# %% ../nbs/api/11_clean.ipynb 14
8388
def clean_nb(
8489
nb, # The notebook to clean
8590
clear_all=False, # Remove all cell metadata and cell outputs?
@@ -88,6 +93,7 @@ def clean_nb(
8893
clean_ids=True, # Remove ids from plaintext reprs?
8994
):
9095
"Clean `nb` from superfluous metadata"
96+
assert isinstance(nb, AttrDict)
9197
metadata_keys = {"kernelspec", "jekyll", "jupytext", "doc", "widgets"}
9298
if allowed_metadata_keys: metadata_keys.update(allowed_metadata_keys)
9399
cell_metadata_keys = {"hide_input"}
@@ -97,33 +103,33 @@ def clean_nb(
97103
nb['metadata']['kernelspec']['display_name'] = nb.metadata.kernelspec.name
98104
nb['metadata'] = {k:v for k,v in nb['metadata'].items() if k in metadata_keys}
99105

100-
# %% ../nbs/api/clean.ipynb 24
106+
# %% ../nbs/api/11_clean.ipynb 27
101107
def _reconfigure(*strms):
102108
for s in strms:
103109
if hasattr(s,'reconfigure'): s.reconfigure(encoding='utf-8')
104110

105-
# %% ../nbs/api/clean.ipynb 25
111+
# %% ../nbs/api/11_clean.ipynb 28
106112
def process_write(warn_msg, proc_nb, f_in, f_out=None, disp=False):
107113
if not f_out: f_out = f_in
108114
if isinstance(f_in, (str,Path)): f_in = Path(f_in).open()
109115
try:
110116
_reconfigure(f_in, f_out)
111-
nb = loads(f_in.read())
117+
nb = dict2nb(loads(f_in.read()))
112118
proc_nb(nb)
113119
write_nb(nb, f_out) if not disp else sys.stdout.write(nb2str(nb))
114120
except Exception as e:
115121
warn(f'{warn_msg}')
116122
warn(e)
117123

118-
# %% ../nbs/api/clean.ipynb 26
124+
# %% ../nbs/api/11_clean.ipynb 29
119125
def _nbdev_clean(nb, path=None, clear_all=None):
120126
cfg = get_config(path=path)
121127
clear_all = clear_all or cfg.clear_all
122128
allowed_metadata_keys = cfg.get("allowed_metadata_keys").split()
123129
allowed_cell_metadata_keys = cfg.get("allowed_cell_metadata_keys").split()
124130
return clean_nb(nb, clear_all, allowed_metadata_keys, allowed_cell_metadata_keys, cfg.clean_ids)
125131

126-
# %% ../nbs/api/clean.ipynb 27
132+
# %% ../nbs/api/11_clean.ipynb 30
127133
@call_parse
128134
def nbdev_clean(
129135
fname:str=None, # A notebook name or glob to clean
@@ -139,15 +145,15 @@ def nbdev_clean(
139145
if fname is None: fname = get_config().nbs_path
140146
for f in globtastic(fname, file_glob='*.ipynb', skip_folder_re='^[_.]'): _write(f_in=f, disp=disp)
141147

142-
# %% ../nbs/api/clean.ipynb 30
148+
# %% ../nbs/api/11_clean.ipynb 33
143149
def clean_jupyter(path, model, **kwargs):
144150
"Clean Jupyter `model` pre save to `path`"
145151
if not (model['type']=='notebook' and model['content']['nbformat']==4): return
146152
get_config.cache_clear() # Allow config changes without restarting Jupyter
147153
jupyter_hooks = get_config(path=path).jupyter_hooks
148154
if jupyter_hooks: _nbdev_clean(model['content'], path=path)
149155

150-
# %% ../nbs/api/clean.ipynb 33
156+
# %% ../nbs/api/11_clean.ipynb 36
151157
_pre_save_hook_src = '''
152158
def nbdev_clean_jupyter(**kwargs):
153159
try: from nbdev.clean import clean_jupyter
@@ -157,7 +163,7 @@ def nbdev_clean_jupyter(**kwargs):
157163
c.ContentsManager.pre_save_hook = nbdev_clean_jupyter'''.strip()
158164
_pre_save_hook_re = re.compile(r'c\.(File)?ContentsManager\.pre_save_hook')
159165

160-
# %% ../nbs/api/clean.ipynb 34
166+
# %% ../nbs/api/11_clean.ipynb 37
161167
def _add_jupyter_hooks(src, path):
162168
if _pre_save_hook_src in src: return
163169
mod = ast.parse(src)
@@ -175,12 +181,12 @@ def _add_jupyter_hooks(src, path):
175181
if src: src+='\n\n'
176182
return src+_pre_save_hook_src
177183

178-
# %% ../nbs/api/clean.ipynb 38
184+
# %% ../nbs/api/11_clean.ipynb 41
179185
def _git_root():
180186
try: return Path(run('git rev-parse --show-toplevel'))
181187
except OSError: return None
182188

183-
# %% ../nbs/api/clean.ipynb 41
189+
# %% ../nbs/api/11_clean.ipynb 44
184190
@call_parse
185191
def nbdev_install_hooks():
186192
"Install Jupyter and git hooks to automatically clean, trust, and fix merge conflicts in notebooks"

nbdev/cli.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/cli.ipynb.
1+
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/13_cli.ipynb.
22

3-
# %% ../nbs/api/cli.ipynb 2
3+
# %% ../nbs/api/13_cli.ipynb 2
44
from __future__ import annotations
55
import warnings
66

@@ -27,7 +27,7 @@
2727
# %% auto 0
2828
__all__ = ['nbdev_filter', 'extract_tgz', 'nbdev_new', 'chelp']
2929

30-
# %% ../nbs/api/cli.ipynb 5
30+
# %% ../nbs/api/13_cli.ipynb 5
3131
@call_parse
3232
def nbdev_filter(
3333
nb_txt:str=None, # Notebook text (uses stdin if not provided)
@@ -50,20 +50,20 @@ def nbdev_filter(
5050
if printit: print(res, flush=True)
5151
else: return res
5252

53-
# %% ../nbs/api/cli.ipynb 8
53+
# %% ../nbs/api/13_cli.ipynb 8
5454
def extract_tgz(url, dest='.'):
5555
from fastcore.net import urlopen
5656
with urlopen(url) as u: tarfile.open(mode='r:gz', fileobj=u).extractall(dest)
5757

58-
# %% ../nbs/api/cli.ipynb 9
58+
# %% ../nbs/api/13_cli.ipynb 9
5959
def _render_nb(fn, cfg):
6060
"Render templated values like `{{lib_name}}` in notebook at `fn` from `cfg`"
6161
txt = fn.read_text()
6262
txt = txt.replace('from your_lib.core', f'from {cfg.lib_path}.core') # for compatibility with old templates
6363
for k,v in cfg.d.items(): txt = txt.replace('{{'+k+'}}', v)
6464
fn.write_text(txt)
6565

66-
# %% ../nbs/api/cli.ipynb 10
66+
# %% ../nbs/api/13_cli.ipynb 10
6767
def _update_repo_meta(cfg):
6868
"Enable gh pages and update the homepage and description in your GitHub repo."
6969
token=os.getenv('GITHUB_TOKEN')
@@ -74,7 +74,7 @@ def _update_repo_meta(cfg):
7474
except HTTPError:print(f"Could not update the description & URL on the repo: {cfg.user}/{cfg.repo} using $GITHUB_TOKEN.\n"
7575
"Use a token with the correction permissions or perform these steps manually.")
7676

77-
# %% ../nbs/api/cli.ipynb 11
77+
# %% ../nbs/api/13_cli.ipynb 11
7878
@call_parse
7979
@delegates(nbdev_create_config)
8080
def nbdev_new(**kwargs):
@@ -108,7 +108,7 @@ def nbdev_new(**kwargs):
108108
nbdev_export.__wrapped__()
109109
nbdev_readme.__wrapped__()
110110

111-
# %% ../nbs/api/cli.ipynb 15
111+
# %% ../nbs/api/13_cli.ipynb 15
112112
@call_parse
113113
def chelp():
114114
"Show help for all console scripts"

0 commit comments

Comments
 (0)