Skip to content

Commit d42de3c

Browse files
committed
Revise new command and remove global spinner
1 parent 503fcd6 commit d42de3c

File tree

5 files changed

+121
-71
lines changed

5 files changed

+121
-71
lines changed

nbs/00_core.ipynb

-30
Original file line numberDiff line numberDiff line change
@@ -163,33 +163,6 @@
163163
"}"
164164
]
165165
},
166-
{
167-
"cell_type": "markdown",
168-
"metadata": {},
169-
"source": [
170-
"Show the user that during delays the system is thinking, not stopped. "
171-
]
172-
},
173-
{
174-
"cell_type": "code",
175-
"execution_count": null,
176-
"metadata": {},
177-
"outputs": [],
178-
"source": [
179-
"#| export\n",
180-
"def with_spinner(f):\n",
181-
" \"Wraps a command with a spinner using rich.console.status\"\n",
182-
" @wraps(f)\n",
183-
" def _inner(*args, **kwargs): \n",
184-
" with console.status(\"\", spinner=\"dots\") as status: \n",
185-
" try:\n",
186-
" result = f(*args, **kwargs)\n",
187-
" return result\n",
188-
" except Exception as e:\n",
189-
" raise e\n",
190-
" return _inner"
191-
]
192-
},
193166
{
194167
"cell_type": "markdown",
195168
"metadata": {},
@@ -209,9 +182,6 @@
209182
"\n",
210183
" # Remove call_parse so it doesn't conflict with typer\n",
211184
" func = getattr(func, '__wrapped__', func)\n",
212-
" \n",
213-
" # Wrap the function in a spinner\n",
214-
" func = with_spinner(func) \n",
215185
"\n",
216186
" # dd to typer.app and \n",
217187
" kwargs = dict(\n",

nbs/01_commands.ipynb

+64-10
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@
3535
"from fastcore.docments import *\n",
3636
"from fastcore.meta import delegates\n",
3737
"from fastcore.script import call_parse\n",
38+
"from fastcore.shutil import rmtree,move\n",
3839
"from fastcore.utils import *\n",
40+
"from nbdev.quarto import nbdev_readme, refresh_quarto_yml, fs_watchdog\n",
3941
"from rich import print\n",
4042
"from rich.console import Console\n",
4143
"from shutil import which"
@@ -49,7 +51,10 @@
4951
"outputs": [],
5052
"source": [
5153
"#| export\n",
52-
"from nbdev import cli, release, config, quarto, doclinks, merge, migrate, sync\n",
54+
"from nbdev import cli, release, quarto, doclinks, merge, migrate, sync\n",
55+
"from nbdev.cli import _update_repo_meta, extract_tgz, _render_nb\n",
56+
"from nbdev.config import *\n",
57+
"from nbdev.doclinks import nbdev_export\n",
5358
"from nbdev import clean as nbclean\n",
5459
"from nbdev import test as nbtest"
5560
]
@@ -226,7 +231,7 @@
226231
" target: Annotated[pathlib.Path, typer.Argument(help=\"Path to create project\")],\n",
227232
" **kwargs):\n",
228233
" \"\"\"\n",
229-
" Create an nbdev project. If the target directory does not exist, it creates it.\n",
234+
" Create an nbdev project. If the target directory does not exist, creates it.\n",
230235
" \n",
231236
" Usage:\n",
232237
" \n",
@@ -238,16 +243,54 @@
238243
" \n",
239244
" Learn more [nbz.answer.ai/commands#new](https://nbz.answer.ai/commands#new)\n",
240245
" \"\"\"\n",
246+
" # Target directory\n",
241247
" if not target.exists(): \n",
242-
" console.print(f'Creating {target} directory')\n",
248+
" console.print(f'Creating and changing to {target} directory')\n",
243249
" target.mkdir()\n",
244-
" console.print(f'Changing directory to {target}')\n",
250+
" os.chdir(target)\n",
245251
" olddir = pathlib.Path('.')\n",
246-
" os.chdir(target)\n",
247-
" resp=nbdev_new(**kwargs)\n",
248-
" os.chdir(olddir)\n",
249-
" console.print(f'Changing directory back')\n",
250-
" return resp\n",
252+
" \n",
253+
" \"Create an nbdev project.\"\n",
254+
" from ghapi.core import GhApi\n",
255+
" nbdev_create_config.__wrapped__(**kwargs)\n",
256+
" with console.status('',spinner=\"dots\"):\n",
257+
" cfg = get_config()\n",
258+
" _update_repo_meta(cfg)\n",
259+
" path = Path()\n",
260+
"\n",
261+
" _ORG_OR_USR,_REPOSITORY = 'fastai','nbdev-template'\n",
262+
" _TEMPLATE = f'{_ORG_OR_USR}/{_REPOSITORY}'\n",
263+
" template = kwargs.get('template', _TEMPLATE)\n",
264+
" try: org_or_usr, repo = template.split('/')\n",
265+
" except ValueError: org_or_usr, repo = _ORG_OR_USR, _REPOSITORY\n",
266+
"\n",
267+
" tag = kwargs.get('tag', None)\n",
268+
" if tag is None:\n",
269+
" with warnings.catch_warnings():\n",
270+
" warnings.simplefilter('ignore', UserWarning)\n",
271+
" tag = GhApi(gh_host='https://api.github.com', authenticate=False).repos.get_latest_release(org_or_usr, repo).tag_name\n",
272+
"\n",
273+
" url = f\"https://github.com/{org_or_usr}/{repo}/archive/{tag}.tar.gz\"\n",
274+
" extract_tgz(url)\n",
275+
" tmpl_path = path/f'{repo}-{tag}'\n",
276+
"\n",
277+
" cfg.nbs_path.mkdir(exist_ok=True)\n",
278+
" nbexists = bool(first(cfg.nbs_path.glob('*.ipynb')))\n",
279+
" _nbs_path_sufs = ('.ipynb','.css')\n",
280+
" for o in tmpl_path.ls():\n",
281+
" p = cfg.nbs_path if o.suffix in _nbs_path_sufs else path\n",
282+
" if o.name == '_quarto.yml': continue\n",
283+
" if o.name == 'index.ipynb': _render_nb(o, cfg)\n",
284+
" if o.name == '00_core.ipynb' and not nbexists: move(o, p)\n",
285+
" elif not (path/o.name).exists(): move(o, p)\n",
286+
" rmtree(tmpl_path)\n",
287+
"\n",
288+
" refresh_quarto_yml()\n",
289+
" nbdev_export.__wrapped__()\n",
290+
" nbdev_readme.__wrapped__()\n",
291+
"\n",
292+
" # return back to the original directory\n",
293+
" os.chdir(olddir)\n",
251294
"new.rich_help_panel = 'Getting started'\n",
252295
"new.no_args_is_help=False\n"
253296
]
@@ -257,7 +300,18 @@
257300
"execution_count": null,
258301
"id": "5f1dda42",
259302
"metadata": {},
260-
"outputs": [],
303+
"outputs": [
304+
{
305+
"data": {
306+
"text/plain": [
307+
"<bound method Path.exists of Path('.')>"
308+
]
309+
},
310+
"execution_count": null,
311+
"metadata": {},
312+
"output_type": "execute_result"
313+
}
314+
],
261315
"source": [
262316
"path = pathlib.Path()\n",
263317
"path.exists"

nbz/_modidx.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,4 @@
1010
'nbz.commands.delegates_sorted': ('commands.html#delegates_sorted', 'nbz/commands.py'),
1111
'nbz.commands.new': ('commands.html#new', 'nbz/commands.py')},
1212
'nbz.core': { 'nbz.core.add_nyi_command': ('core.html#add_nyi_command', 'nbz/core.py'),
13-
'nbz.core.helper': ('core.html#helper', 'nbz/core.py'),
14-
'nbz.core.with_spinner': ('core.html#with_spinner', 'nbz/core.py')}}}
13+
'nbz.core.helper': ('core.html#helper', 'nbz/core.py')}}}

nbz/commands.py

+52-9
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,18 @@
1313
from fastcore.docments import *
1414
from fastcore.meta import delegates
1515
from fastcore.script import call_parse
16+
from fastcore.shutil import rmtree,move
1617
from fastcore.utils import *
18+
from nbdev.quarto import nbdev_readme, refresh_quarto_yml, fs_watchdog
1719
from rich import print
1820
from rich.console import Console
1921
from shutil import which
2022

2123
# %% ../nbs/01_commands.ipynb 3
22-
from nbdev import cli, release, config, quarto, doclinks, merge, migrate, sync
24+
from nbdev import cli, release, quarto, doclinks, merge, migrate, sync
25+
from nbdev.cli import _update_repo_meta, extract_tgz, _render_nb
26+
from nbdev.config import *
27+
from nbdev.doclinks import nbdev_export
2328
from nbdev import clean as nbclean
2429
from nbdev import test as nbtest
2530

@@ -132,7 +137,7 @@ def new(
132137
target: Annotated[pathlib.Path, typer.Argument(help="Path to create project")],
133138
**kwargs):
134139
"""
135-
Create an nbdev project. If the target directory does not exist, it creates it.
140+
Create an nbdev project. If the target directory does not exist, creates it.
136141
137142
Usage:
138143
@@ -144,16 +149,54 @@ def new(
144149
145150
Learn more [nbz.answer.ai/commands#new](https://nbz.answer.ai/commands#new)
146151
"""
152+
# Target directory
147153
if not target.exists():
148-
console.print(f'Creating {target} directory')
154+
console.print(f'Creating and changing to {target} directory')
149155
target.mkdir()
150-
console.print(f'Changing directory to {target}')
156+
os.chdir(target)
151157
olddir = pathlib.Path('.')
152-
os.chdir(target)
153-
resp=nbdev_new(**kwargs)
154-
os.chdir(olddir)
155-
console.print(f'Changing directory back')
156-
return resp
158+
159+
"Create an nbdev project."
160+
from ghapi.core import GhApi
161+
nbdev_create_config.__wrapped__(**kwargs)
162+
with console.status('',spinner="dots"):
163+
cfg = get_config()
164+
_update_repo_meta(cfg)
165+
path = Path()
166+
167+
_ORG_OR_USR,_REPOSITORY = 'fastai','nbdev-template'
168+
_TEMPLATE = f'{_ORG_OR_USR}/{_REPOSITORY}'
169+
template = kwargs.get('template', _TEMPLATE)
170+
try: org_or_usr, repo = template.split('/')
171+
except ValueError: org_or_usr, repo = _ORG_OR_USR, _REPOSITORY
172+
173+
tag = kwargs.get('tag', None)
174+
if tag is None:
175+
with warnings.catch_warnings():
176+
warnings.simplefilter('ignore', UserWarning)
177+
tag = GhApi(gh_host='https://api.github.com', authenticate=False).repos.get_latest_release(org_or_usr, repo).tag_name
178+
179+
url = f"https://github.com/{org_or_usr}/{repo}/archive/{tag}.tar.gz"
180+
extract_tgz(url)
181+
tmpl_path = path/f'{repo}-{tag}'
182+
183+
cfg.nbs_path.mkdir(exist_ok=True)
184+
nbexists = bool(first(cfg.nbs_path.glob('*.ipynb')))
185+
_nbs_path_sufs = ('.ipynb','.css')
186+
for o in tmpl_path.ls():
187+
p = cfg.nbs_path if o.suffix in _nbs_path_sufs else path
188+
if o.name == '_quarto.yml': continue
189+
if o.name == 'index.ipynb': _render_nb(o, cfg)
190+
if o.name == '00_core.ipynb' and not nbexists: move(o, p)
191+
elif not (path/o.name).exists(): move(o, p)
192+
rmtree(tmpl_path)
193+
194+
refresh_quarto_yml()
195+
nbdev_export.__wrapped__()
196+
nbdev_readme.__wrapped__()
197+
198+
# return back to the original directory
199+
os.chdir(olddir)
157200
new.rich_help_panel = 'Getting started'
158201
new.no_args_is_help=False
159202

nbz/core.py

+4-20
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/00_core.ipynb.
44

55
# %% auto 0
6-
__all__ = ['app', 'commands', 'console', 'nyi_commands', 'helper', 'with_spinner', 'add_nyi_command']
6+
__all__ = ['app', 'commands', 'console', 'nyi_commands', 'helper', 'add_nyi_command']
77

88
# %% ../nbs/00_core.ipynb 4
99
import types
@@ -71,27 +71,11 @@ def helper(ctx: typer.Context):
7171
}
7272

7373
# %% ../nbs/00_core.ipynb 14
74-
def with_spinner(f):
75-
"Wraps a command with a spinner using rich.console.status"
76-
@wraps(f)
77-
def _inner(*args, **kwargs):
78-
with console.status("", spinner="dots") as status:
79-
try:
80-
result = f(*args, **kwargs)
81-
return result
82-
except Exception as e:
83-
raise e
84-
return _inner
85-
86-
# %% ../nbs/00_core.ipynb 16
8774
console = Console()
8875
for fname,func in commands.items():
8976

9077
# Remove call_parse so it doesn't conflict with typer
9178
func = getattr(func, '__wrapped__', func)
92-
93-
# Wrap the function in a spinner
94-
func = with_spinner(func)
9579

9680
# dd to typer.app and
9781
kwargs = dict(
@@ -114,15 +98,15 @@ def _inner(*args, **kwargs):
11498
# Save to the global names
11599
globals()[fname] = func
116100

117-
# %% ../nbs/00_core.ipynb 19
101+
# %% ../nbs/00_core.ipynb 17
118102
# Not yet implemented
119103
# TODO: fix store_true on these commands.
120104
nyi_commands = {
121105
'export': doclinks.nbdev_export,
122106
'export_cli': cli.nb_export_cli,
123107
}
124108

125-
# %% ../nbs/00_core.ipynb 20
109+
# %% ../nbs/00_core.ipynb 18
126110
def add_nyi_command(fname):
127111
@app.command(rich_help_panel='Not yet implemented')
128112
def func():
@@ -131,7 +115,7 @@ def func():
131115
func.__name__ = fname
132116
globals()[fname] = func
133117

134-
# %% ../nbs/00_core.ipynb 22
118+
# %% ../nbs/00_core.ipynb 20
135119
# Add NYI panel
136120
for fname in nyi_commands.keys():
137121
add_nyi_command(fname)

0 commit comments

Comments
 (0)