nbdevAuto 0.3.63__tar.gz → 0.3.65__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nbdevAuto
3
- Version: 0.3.63
3
+ Version: 0.3.65
4
4
  Summary: automating nbdev
5
5
  Author-email: Benedict Thekkel <bthekkel1@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -23,6 +23,7 @@ Description-Content-Type: text/markdown
23
23
  License-File: LICENSE
24
24
  Requires-Dist: graphviz
25
25
  Requires-Dist: fastcore
26
+ Requires-Dist: rich
26
27
  Provides-Extra: gh
27
28
  Requires-Dist: githubkit>=0.12; extra == "gh"
28
29
  Dynamic: license-file
@@ -0,0 +1 @@
1
+ __version__ = "0.3.65"
@@ -5,7 +5,24 @@ d = { 'settings': { 'branch': 'main',
5
5
  'doc_host': 'https://bthek1.github.io',
6
6
  'git_url': 'https://github.com/bthek1/nbdevAuto',
7
7
  'lib_path': 'nbdevAuto'},
8
- 'syms': { 'nbdevAuto.automate': { 'nbdevAuto.automate.gacp': ('automate.html#gacp', 'nbdevAuto/automate.py'),
8
+ 'syms': { 'nbdevAuto.automate': { 'nbdevAuto.automate.StepFailed': ('automate.html#stepfailed', 'nbdevAuto/automate.py'),
9
+ 'nbdevAuto.automate.StepFailed.__init__': ( 'automate.html#stepfailed.__init__',
10
+ 'nbdevAuto/automate.py'),
11
+ 'nbdevAuto.automate._auto_msg': ('automate.html#_auto_msg', 'nbdevAuto/automate.py'),
12
+ 'nbdevAuto.automate._banner': ('automate.html#_banner', 'nbdevAuto/automate.py'),
13
+ 'nbdevAuto.automate._commit_summary': ('automate.html#_commit_summary', 'nbdevAuto/automate.py'),
14
+ 'nbdevAuto.automate._done': ('automate.html#_done', 'nbdevAuto/automate.py'),
15
+ 'nbdevAuto.automate._dur': ('automate.html#_dur', 'nbdevAuto/automate.py'),
16
+ 'nbdevAuto.automate._push_summary': ('automate.html#_push_summary', 'nbdevAuto/automate.py'),
17
+ 'nbdevAuto.automate._quiet': ('automate.html#_quiet', 'nbdevAuto/automate.py'),
18
+ 'nbdevAuto.automate._rule': ('automate.html#_rule', 'nbdevAuto/automate.py'),
19
+ 'nbdevAuto.automate._run': ('automate.html#_run', 'nbdevAuto/automate.py'),
20
+ 'nbdevAuto.automate._skip': ('automate.html#_skip', 'nbdevAuto/automate.py'),
21
+ 'nbdevAuto.automate._status_table': ('automate.html#_status_table', 'nbdevAuto/automate.py'),
22
+ 'nbdevAuto.automate._step': ('automate.html#_step', 'nbdevAuto/automate.py'),
23
+ 'nbdevAuto.automate._test_summary': ('automate.html#_test_summary', 'nbdevAuto/automate.py'),
24
+ 'nbdevAuto.automate._version_summary': ('automate.html#_version_summary', 'nbdevAuto/automate.py'),
25
+ 'nbdevAuto.automate.gacp': ('automate.html#gacp', 'nbdevAuto/automate.py'),
9
26
  'nbdevAuto.automate.help_output': ('automate.html#help_output', 'nbdevAuto/automate.py'),
10
27
  'nbdevAuto.automate.prep': ('automate.html#prep', 'nbdevAuto/automate.py'),
11
28
  'nbdevAuto.automate.release': ('automate.html#release', 'nbdevAuto/automate.py'),
@@ -0,0 +1,341 @@
1
+ """Automate
2
+
3
+ Docs: https://bthek1.github.io/nbdevAuto/automate.html.md"""
4
+
5
+ # AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/01_Automate.ipynb.
6
+
7
+ # %% auto #0
8
+ __all__ = ['prep', 'gacp', 'status', 'upload', 'release_git', 'release_pypi', 'release', 'help_output']
9
+
10
+ # %% ../nbs/01_Automate.ipynb #6d1499d1-aa55-47d8-92fd-fa056b1fb135
11
+ from fastcore.script import *
12
+ from rich import box
13
+ from rich.console import Console
14
+ from rich.markup import escape
15
+ from rich.rule import Rule
16
+ from rich.table import Table
17
+
18
+ # %% ../nbs/01_Automate.ipynb #7c1e5a90-3f52-4d21-9b6a-2c0f4e8d1a37
19
+ import re
20
+ import subprocess
21
+ from contextlib import contextmanager, redirect_stderr, redirect_stdout
22
+ from io import StringIO
23
+ from time import perf_counter
24
+
25
+ from nbdevAuto import __version__
26
+
27
+ console = Console()
28
+
29
+ # A rule drawn across a 200-column terminal is a wall of dashes. 88 reads as a header.
30
+ _RULE_W = 88
31
+
32
+ # `git status -s` codes: colour, the word for the third column, and the verb a commit
33
+ # subject gets when every staged path carries that same code.
34
+ _CODE_STYLE = {"M":"yellow", "A":"green", "D":"red", "R":"cyan", "C":"cyan", "U":"magenta", "?":"dim"}
35
+ _CODE_LABEL = {"M":"modified", "A":"added", "D":"deleted", "R":"renamed", "C":"copied",
36
+ "U":"conflict", "?":"untracked"}
37
+ _CODE_VERB = {"M":"update", "A":"add", "D":"remove", "R":"rename", "C":"copy",
38
+ "U":"merge", "?":"add"}
39
+
40
+ _RE_VERSION = re.compile(r"^(Old|New) version:\s*(\S+)", re.M)
41
+ _RE_TIMING = re.compile(r"^(?P<nb>.+?):\s+(?P<secs>[\d.]+)\s*secs?$")
42
+ _RE_COMMIT = re.compile(r"^\[(?P<branch>\S+)\s+(?P<sha>[0-9a-f]+)\]")
43
+ _RE_COUNTS = re.compile(r"(\d+) files? changed(?:, (\d+) insertions?\(\+\))?(?:, (\d+) deletions?\(-\))?")
44
+ _RE_WROTE = re.compile(r"Writing objects:.*?,\s*(?P<size>[\d.]+\s*[KMG]?i?B)")
45
+
46
+ class StepFailed(Exception):
47
+ "A stage exited non-zero. Carries the output so `_step` can show what went wrong"
48
+ def __init__(self, cmd, code, output=""):
49
+ self.cmd, self.code, self.output = cmd, code, output
50
+ super().__init__(f"{cmd} exited {code}")
51
+
52
+ def _dur(t0):
53
+ "Elapsed time since `t0`, at a readable scale"
54
+ s = perf_counter() - t0
55
+ if s < 1: return f"{s*1000:.0f}ms"
56
+ if s < 60: return f"{s:.1f}s"
57
+ return f"{int(s)//60}m{int(s)%60:02d}s"
58
+
59
+ def _rule(text, style):
60
+ "A rule capped at `_RULE_W`; `console.rule` otherwise spans the whole terminal"
61
+ console.print(Rule(text, style=style), width=min(console.width, _RULE_W))
62
+
63
+ def _banner(cmd):
64
+ "Command header, with the package version alongside"
65
+ _rule(f"[bold cyan]{cmd}[/bold cyan] [dim]nbdevAuto {__version__}[/dim]", "cyan")
66
+
67
+ def _done(cmd, t0):
68
+ "Closing summary for a multi-stage command"
69
+ _rule(f"[green]{cmd} finished[/green] [dim]in {_dur(t0)}[/dim]", "green")
70
+
71
+ @contextmanager
72
+ def _step(n, total, label):
73
+ """Run one stage, reporting its outcome and duration.
74
+
75
+ Yields a list: append short strings and they print under the step, which is how a
76
+ stage says what it did without letting the underlying tool print it all. Re-raises
77
+ so nothing is swallowed, and a `StepFailed` shows the output it carries."""
78
+ console.print(f"[dim]{n}/{total}[/dim] [bold]{label}[/bold]")
79
+ t0, detail = perf_counter(), []
80
+ try:
81
+ yield detail
82
+ except StepFailed as e:
83
+ console.print(f" [bold red]FAIL[/bold red] [dim]{_dur(t0)}, exit {e.code}[/dim]")
84
+ for line in e.output.splitlines():
85
+ if line.strip(): console.print(f" [red]{escape(line.rstrip())}[/red]")
86
+ console.print()
87
+ raise
88
+ except BaseException:
89
+ console.print(f" [bold red]FAIL[/bold red] [dim]{_dur(t0)}[/dim]\n")
90
+ raise
91
+ for line in detail: console.print(f" [dim]{escape(line)}[/dim]")
92
+ console.print(f" [green]OK[/green] [dim]{_dur(t0)}[/dim]\n")
93
+
94
+ def _skip(n, total, label, why):
95
+ "Report a stage that was deliberately not run"
96
+ console.print(f"[dim]{n}/{total}[/dim] [bold]{label}[/bold]")
97
+ console.print(f" [yellow]SKIP[/yellow] [dim]{why}[/dim]\n")
98
+
99
+ def _run(*cmd):
100
+ """Run `cmd` with output captured, returning stdout+stderr.
101
+
102
+ A bare `subprocess.run` returns an exit code nobody reads, so a failed `git push`
103
+ still printed a green OK. Raising is what makes that OK mean something."""
104
+ r = subprocess.run(cmd, capture_output=True, text=True)
105
+ out = f"{r.stdout or ''}{r.stderr or ''}"
106
+ if r.returncode: raise StepFailed(" ".join(cmd), r.returncode, out)
107
+ return out
108
+
109
+ @contextmanager
110
+ def _quiet():
111
+ "Collect what a wrapped nbdev call prints, so the step can summarise it instead"
112
+ buf = StringIO()
113
+ try:
114
+ with redirect_stdout(buf), redirect_stderr(buf): yield buf
115
+ except BaseException:
116
+ # A failing stage is the one time every raw line is worth having.
117
+ text = buf.getvalue().strip()
118
+ if text: console.print(f"[dim]{escape(text)}[/dim]")
119
+ raise
120
+
121
+ def _version_summary(out):
122
+ "The two lines `nbdev_bump_version` prints, as one arrow"
123
+ v = dict(_RE_VERSION.findall(out))
124
+ if "Old" in v and "New" in v: return [f"{v['Old']} -> {v['New']}"]
125
+ return [l.strip() for l in out.splitlines() if l.strip()]
126
+
127
+ def _test_summary(out, slow_secs=1.0, keep=3):
128
+ "`nbdev_test` prints a line per notebook; keep the count and only the genuinely slow ones"
129
+ times = []
130
+ for line in out.splitlines():
131
+ m = _RE_TIMING.match(line.strip())
132
+ if m:
133
+ try: times.append((m["nb"], float(m["secs"])))
134
+ except ValueError: pass
135
+ if not times: return [l.strip() for l in out.splitlines() if l.strip()][-3:]
136
+ head = f"{len(times)} notebook{'' if len(times) == 1 else 's'}"
137
+ slow = [t for t in sorted(times, key=lambda t: -t[1]) if t[1] >= slow_secs][:keep]
138
+ if not slow: return [f"{head}, none slower than {slow_secs:g}s"]
139
+ return [f"{head}, slowest:"] + [f" {nb} {s:.1f}s" for nb, s in slow]
140
+
141
+ def _commit_summary(out):
142
+ "Where the commit landed and how big it was, without echoing the subject back"
143
+ lines = [l.strip() for l in out.splitlines() if l.strip()]
144
+ if not lines: return []
145
+ m, c = _RE_COMMIT.match(lines[0]), _RE_COUNTS.search(out)
146
+ head = f"{m['branch']} {m['sha']}" if m else lines[0]
147
+ if not c: return [head]
148
+ files, ins, dels = c.group(1), c.group(2) or "0", c.group(3) or "0"
149
+ return [f"{head} {files} file{'' if files == '1' else 's'}, +{ins} -{dels}"]
150
+
151
+ def _push_summary(out):
152
+ "What moved and how much went over the wire; the progress meters are noise"
153
+ lines = [l.rstrip() for l in out.splitlines() if l.strip()]
154
+ if not lines: return ["nothing to push"]
155
+ if any("Everything up-to-date" in l for l in lines): return ["everything up-to-date"]
156
+ detail = []
157
+ for i, l in enumerate(lines):
158
+ if l.startswith("To ") and i + 1 < len(lines):
159
+ detail += [lines[i + 1].strip(), f"to {l[3:].strip()}"]
160
+ break
161
+ m = _RE_WROTE.search(out)
162
+ if m: detail.append(f"{m['size'].strip()} written")
163
+ return detail or lines[-1:]
164
+
165
+ def _auto_msg(porcelain, limit=3):
166
+ "A commit subject built from the staged paths. The raw status output made a poor one"
167
+ rows = [(l[:2].strip()[:1], l[3:].strip()) for l in porcelain.splitlines() if l.strip()]
168
+ if not rows: return "update"
169
+ verb = _CODE_VERB.get(rows[0][0], "update") if len({c for c, _ in rows}) == 1 else "update"
170
+ names = [p.split(" -> ")[-1] for _, p in rows]
171
+ head = ", ".join(names[:limit])
172
+ if len(names) > limit: head += f" and {len(names) - limit} more"
173
+ return f"{verb} {head}"
174
+
175
+ def _status_table(porcelain):
176
+ "Render `git status -s` output as a table, one row per path"
177
+ t = Table(box=box.SIMPLE, show_header=False, pad_edge=False, expand=False)
178
+ t.add_column("code", no_wrap=True, justify="right")
179
+ t.add_column("path", overflow="fold")
180
+ t.add_column("what", style="dim", no_wrap=True)
181
+ n = 0
182
+ for line in porcelain.splitlines():
183
+ if not line.strip(): continue
184
+ code, path = line[:2].strip(), line[3:]
185
+ style = _CODE_STYLE.get(code[:1], "white")
186
+ t.add_row(f"[{style}]{code}[/{style}]", escape(path), _CODE_LABEL.get(code[:1], ""))
187
+ n += 1
188
+ return t, n
189
+
190
+ # %% ../nbs/01_Automate.ipynb #3a6f81d2-5c47-4e19-8b03-9d2a7f6c0e15
191
+ @call_parse
192
+ def prep(
193
+ p:int = 2, # Increment Part
194
+ ):
195
+ "Bump version part `p`, then export, test and clean the notebooks, refreshing _quarto.yml and README"
196
+
197
+ import nbdev.test, nbdev.clean, nbdev.quarto, nbdev.release
198
+ _banner("prep")
199
+ t0 = perf_counter()
200
+ with _step(1, 6, f"bump version (part {p})") as d, _quiet() as out:
201
+ nbdev.release.nbdev_bump_version(p)
202
+ d += _version_summary(out.getvalue())
203
+ with _step(2, 6, "nbdev_export"), _quiet():
204
+ nbdev.quarto.nbdev_export.__wrapped__()
205
+ with _step(3, 6, "nbdev_test") as d, _quiet() as out:
206
+ nbdev.test.nbdev_test.__wrapped__(
207
+ n_workers = 8, # Number of workers
208
+ timing = True, # Time each notebook to see which are slow
209
+ )
210
+ d += _test_summary(out.getvalue())
211
+ with _step(4, 6, "nbdev_clean"), _quiet():
212
+ nbdev.clean.nbdev_clean.__wrapped__()
213
+ with _step(5, 6, "refresh_quarto_yml"), _quiet():
214
+ nbdev.quarto.refresh_quarto_yml()
215
+ with _step(6, 6, "nbdev_readme"), _quiet():
216
+ nbdev.quarto.nbdev_readme.__wrapped__(chk_time=True)
217
+ _done("prep", t0)
218
+
219
+ # %% ../nbs/01_Automate.ipynb #f66ef35f-b7fa-4039-aa07-e9b782d204bb
220
+ @call_parse
221
+ def gacp(
222
+ m:str = '', # Commit message
223
+ ):
224
+ "git add, commit and push. Without `-m` the message is built from the staged paths"
225
+
226
+ _banner("gacp")
227
+ t0 = perf_counter()
228
+ with _step(1, 3, "git add"):
229
+ _run("git", "add", ".")
230
+ # NOT via `_run`: `git status -s` pads the code to two columns, and the capture has
231
+ # to keep that leading space or the first path shifts by one.
232
+ status = subprocess.check_output(["git", "status", "-s"]).decode('utf-8')
233
+ staged = bool(status.strip())
234
+ if staged:
235
+ table, n = _status_table(status)
236
+ console.print(table)
237
+ console.print(f"[dim]{n} path{'' if n == 1 else 's'} staged[/dim]\n")
238
+ else:
239
+ console.print("[dim]nothing staged, the tree is clean[/dim]\n")
240
+
241
+ if staged:
242
+ with _step(2, 3, "git commit") as d:
243
+ d += _commit_summary(_run("git", "commit", "-m", m if m != '' else _auto_msg(status)))
244
+ else:
245
+ # `git commit` exits 1 with nothing staged, which is now a hard failure rather
246
+ # than a silent one. There may still be unpushed commits, so go on to the push.
247
+ _skip(2, 3, "git commit", "nothing staged")
248
+ with _step(3, 3, "git push") as d:
249
+ d += _push_summary(_run("git", "push"))
250
+ _done("gacp", t0)
251
+
252
+ # %% ../nbs/01_Automate.ipynb #88017a1b-55c1-4833-aeb6-277a7e5b6314
253
+ def status():
254
+ "Show the working tree state"
255
+ import subprocess
256
+
257
+ def _git(*a, **kw): return subprocess.check_output(["git", *a], **kw).decode('utf-8').strip()
258
+
259
+ _banner("status")
260
+ branch = _git("branch", "--show-current") or "DETACHED"
261
+ line = f"on [bold]{branch}[/bold]"
262
+ try:
263
+ behind, ahead = _git("rev-list", "--left-right", "--count", "@{upstream}...HEAD",
264
+ stderr=subprocess.DEVNULL).split()
265
+ if behind != "0": line += f" [yellow]behind {behind}[/yellow]"
266
+ if ahead != "0": line += f" [cyan]ahead {ahead}[/cyan]"
267
+ if behind == ahead == "0": line += " [dim]in step with upstream[/dim]"
268
+ except subprocess.CalledProcessError:
269
+ line += " [dim]no upstream[/dim]"
270
+ console.print(line)
271
+
272
+ # NOT via _git: `git status -s` pads the code to two columns, so stripping the
273
+ # output would eat the leading space of the first line and shift its path by one.
274
+ porcelain = subprocess.check_output(["git", "status", "-s"]).decode('utf-8')
275
+ if not porcelain:
276
+ console.print("[green]clean[/green]")
277
+ return
278
+ table, n = _status_table(porcelain)
279
+ console.print(table)
280
+ console.print(f"[dim]{n} path{'' if n == 1 else 's'} changed[/dim]")
281
+
282
+ # %% ../nbs/01_Automate.ipynb #8d777a41-0160-47f8-b51c-b14360b62da4
283
+ @call_parse
284
+ def upload(
285
+ m:str = '', # Commit message
286
+ p:int = 2, # Increment part
287
+ ):
288
+ "prep then gacp: the everyday command for shipping a notebook change"
289
+ prep(p)
290
+ gacp(m)
291
+
292
+ # %% ../nbs/01_Automate.ipynb #dee37b06-c946-4b40-be0f-056e133751ea
293
+ def release_git():
294
+ "Bump the MINOR version, then tag and create a GitHub release"
295
+ import nbdev.release
296
+ _banner("gitrelease")
297
+ t0 = perf_counter()
298
+ with _step(1, 2, "bump minor version") as d, _quiet() as out:
299
+ nbdev.release.nbdev_bump_version(1)
300
+ d += _version_summary(out.getvalue())
301
+ with _step(2, 2, "tag and create the GitHub release"):
302
+ nbdev.release.release_git()
303
+ _done("gitrelease", t0)
304
+
305
+ # %% ../nbs/01_Automate.ipynb #288708c6-194a-4059-9ff0-ae330079c199
306
+ def release_pypi():
307
+ "Build the sdist and wheel, then upload to PyPI with twine. CI publishes on push, so this is the manual path"
308
+ import nbdev.release
309
+ _banner("piprelease")
310
+ t0 = perf_counter()
311
+ # Deliberately not quieted: a twine upload is worth watching line by line.
312
+ with _step(1, 1, "build and upload to PyPI"):
313
+ nbdev.release.release_pypi()
314
+ _done("piprelease", t0)
315
+
316
+ # %% ../nbs/01_Automate.ipynb #dd798178-9d58-457e-969a-d86a5e8bf875
317
+ def release():
318
+ "release_git then release_pypi"
319
+ release_git()
320
+ release_pypi()
321
+
322
+ # %% ../nbs/01_Automate.ipynb #c4d2bd52-04c4-43fe-890b-b4cb5da8d206
323
+ def help_output():
324
+ "Print every console script this package installs, with its help"
325
+ from importlib.metadata import distribution
326
+ try:
327
+ eps = [e for e in distribution("nbdevAuto").entry_points if e.group == "console_scripts"]
328
+ except Exception:
329
+ # Running from a source tree with nothing installed: fall back to fastcore.
330
+ from fastcore.xtras import console_help
331
+ return console_help('nbdevAuto')
332
+ _banner("commands")
333
+ t = Table(box=box.SIMPLE, show_header=False, pad_edge=False, expand=False)
334
+ t.add_column("command", style="bold cyan", no_wrap=True)
335
+ t.add_column("does", overflow="fold")
336
+ for e in sorted(eps, key=lambda e: e.name):
337
+ try: doc = escape((e.load().__doc__ or "").strip().splitlines()[0])
338
+ except Exception: doc = "[red]could not load[/red]"
339
+ t.add_row(e.name, doc)
340
+ console.print(t)
341
+ console.print(escape("ghstatus needs the gh extra: pip install 'nbdevAuto[gh]'"), style="dim")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nbdevAuto
3
- Version: 0.3.63
3
+ Version: 0.3.65
4
4
  Summary: automating nbdev
5
5
  Author-email: Benedict Thekkel <bthekkel1@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -23,6 +23,7 @@ Description-Content-Type: text/markdown
23
23
  License-File: LICENSE
24
24
  Requires-Dist: graphviz
25
25
  Requires-Dist: fastcore
26
+ Requires-Dist: rich
26
27
  Provides-Extra: gh
27
28
  Requires-Dist: githubkit>=0.12; extra == "gh"
28
29
  Dynamic: license-file
@@ -1,5 +1,6 @@
1
1
  graphviz
2
2
  fastcore
3
+ rich
3
4
 
4
5
  [gh]
5
6
  githubkit>=0.12
@@ -24,7 +24,7 @@ classifiers = [
24
24
  "Programming Language :: Python :: 3.13",
25
25
  "Programming Language :: Python :: 3.14",
26
26
  ]
27
- dependencies = ['graphviz', 'fastcore']
27
+ dependencies = ['graphviz', 'fastcore', 'rich']
28
28
 
29
29
  [project.optional-dependencies]
30
30
  # An extra, not a dependency: githubkit pulls pydantic + httpx + hishel, which is
@@ -1 +0,0 @@
1
- __version__ = "0.3.63"
@@ -1,97 +0,0 @@
1
- """Automate
2
-
3
- Docs: https://bthek1.github.io/nbdevAuto/automate.html.md"""
4
-
5
- # AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/01_Automate.ipynb.
6
-
7
- # %% auto #0
8
- __all__ = ['prep', 'gacp', 'status', 'upload', 'release_git', 'release_pypi', 'release', 'help_output']
9
-
10
- # %% ../nbs/01_Automate.ipynb #6d1499d1-aa55-47d8-92fd-fa056b1fb135
11
- from fastcore.script import *
12
-
13
- @call_parse
14
- def prep(
15
- p:int = 2, # Increment Part
16
- ):
17
- "Bump version part `p`, then export, test and clean the notebooks, refreshing _quarto.yml and README"
18
-
19
- import nbdev.test, nbdev.clean, nbdev.quarto, nbdev.release
20
- nbdev.release.nbdev_bump_version(p)
21
-
22
- nbdev.quarto.nbdev_export.__wrapped__()
23
- print(f'### nbdev_export finished ###')
24
- nbdev.test.nbdev_test.__wrapped__(
25
- n_workers = 8, # Number of workers
26
- timing = True, # Time each notebook to see which are slow
27
- )
28
- print(f'### nbdev_test finished ###')
29
- nbdev.clean.nbdev_clean.__wrapped__()
30
- print(f'### nbdev_clean finished ###')
31
- nbdev.quarto.refresh_quarto_yml()
32
- print(f'### refresh_quarto_yml finished ###')
33
- nbdev.quarto.nbdev_readme.__wrapped__(chk_time=True)
34
- print(f'### nbdev_readme finished ###')
35
-
36
- # %% ../nbs/01_Automate.ipynb #f66ef35f-b7fa-4039-aa07-e9b782d204bb
37
- @call_parse
38
- def gacp(
39
- m:str = '', # Commit message
40
- ):
41
- "git add, commit and push. Without `-m` the commit message is the status output"
42
-
43
- import subprocess
44
- subprocess.run(["git", "add", "."])
45
- print(f'### git added ###')
46
- status = subprocess.check_output(["git", "status", "-s"]).decode('utf-8')
47
- print(f'### git status: "{status}" ###')
48
-
49
- if m != '':
50
- subprocess.run(["git", "commit", "-m", f'{m}'])
51
- print(f'### git commited "{m}"###')
52
- else:
53
- subprocess.run(["git", "commit", "-m", f'{status}'])
54
- print(f'### git commited status ###')
55
- subprocess.run(["git", "push"])
56
- print(f'### git pushed ###')
57
-
58
- # %% ../nbs/01_Automate.ipynb #88017a1b-55c1-4833-aeb6-277a7e5b6314
59
- def status():
60
- "Show the working tree state"
61
- import subprocess
62
- subprocess.run(["git", "status"])
63
-
64
- # %% ../nbs/01_Automate.ipynb #8d777a41-0160-47f8-b51c-b14360b62da4
65
- @call_parse
66
- def upload(
67
- m:str = '', # Commit message
68
- p:int = 2, #Increment part
69
- ):
70
- "prep then gacp: the everyday command for shipping a notebook change"
71
- prep(p)
72
- gacp(m)
73
-
74
- # %% ../nbs/01_Automate.ipynb #dee37b06-c946-4b40-be0f-056e133751ea
75
- def release_git():
76
- "Bump the MINOR version, then tag and create a GitHub release"
77
- import nbdev.release
78
- nbdev.release.nbdev_bump_version(1)
79
- nbdev.release.release_git()
80
-
81
- # %% ../nbs/01_Automate.ipynb #288708c6-194a-4059-9ff0-ae330079c199
82
- def release_pypi():
83
- "Build the sdist and wheel, then upload to PyPI with twine. CI publishes on push, so this is the manual path"
84
- import nbdev.release
85
- nbdev.release.release_pypi()
86
-
87
- # %% ../nbs/01_Automate.ipynb #dd798178-9d58-457e-969a-d86a5e8bf875
88
- def release():
89
- "release_git then release_pypi"
90
- release_git()
91
- release_pypi()
92
-
93
- # %% ../nbs/01_Automate.ipynb #c4d2bd52-04c4-43fe-890b-b4cb5da8d206
94
- def help_output():
95
- "Print every console script this package installs, with its help"
96
- from fastcore.xtras import console_help
97
- console_help('nbdevAuto')
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes