Skip to content

Commit ab94328

Browse files
authored
Merge pull request #65 from AnswerDotAI/download
Feat: plash_download can overwrite empty dirs
2 parents 2e68384 + b99b716 commit ab94328

3 files changed

Lines changed: 75 additions & 25 deletions

File tree

nbs/00_cli.ipynb

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@
106106
"outputs": [],
107107
"source": [
108108
"#| export\n",
109-
"def _mk_auth_req(url:str, method:str='get', **kwargs):\n",
110-
" r = getattr(_get_client(PLASH_CONFIG_HOME), method)(url, **kwargs)\n",
109+
"def _mk_auth_req(url:str, method:str='get', timeout=300., **kwargs):\n",
110+
" r = getattr(_get_client(PLASH_CONFIG_HOME), method)(url, timeout=timeout, **kwargs)\n",
111111
" if r.status_code == 200: return r\n",
112112
" else: print(f'Failure: {r.headers[\"X-Plash-Error\"]}')"
113113
]
@@ -406,7 +406,7 @@
406406
" plash_app.write_text(f'export PLASH_APP_NAME={name}')\n",
407407
" \n",
408408
" tarz, _ = create_tar_archive(path, force_data)\n",
409-
" r = _mk_auth_req(_endpoint(rt=\"/upload\"), \"post\", files={'file': tarz}, timeout=300.0, \n",
409+
" r = _mk_auth_req(_endpoint(rt=\"/upload\"), \"post\", files={'file': tarz},\n",
410410
" data={'name': name, 'force_data': force_data})\n",
411411
" if r:\n",
412412
" print('✅ Upload complete! Your app is currently being built.')\n",
@@ -434,9 +434,9 @@
434434
"usage: plash_deploy [-h] [--path PATH] [--name NAME] [--force_data]\n",
435435
"\n",
436436
"Deploys app to production. By default, this command erases all files in your app which are not in data/. Then uploads\n",
437-
"all files and folders, except paths starting with '.' and except the local data/ directory. If `--force data` is used,\n",
437+
"all files and folders, except paths starting with `.` and except the local data/ directory. If `--force_data` is used,\n",
438438
"then it erases all files in production. Then it uploads all files and folders, including `data/`, except paths starting\n",
439-
"with '.'.\n",
439+
"with `.`.\n",
440440
"\n",
441441
"options:\n",
442442
" -h, --help show this help message and exit\n",
@@ -739,6 +739,55 @@
739739
"plash_logs --help"
740740
]
741741
},
742+
{
743+
"cell_type": "code",
744+
"execution_count": null,
745+
"id": "b8959fc4",
746+
"metadata": {},
747+
"outputs": [],
748+
"source": [
749+
"#| hide\n",
750+
"import tempfile\n",
751+
"temp_dir = tempfile.TemporaryDirectory()\n",
752+
"td = Path(temp_dir.name)"
753+
]
754+
},
755+
{
756+
"cell_type": "code",
757+
"execution_count": null,
758+
"id": "f8441125",
759+
"metadata": {},
760+
"outputs": [],
761+
"source": [
762+
"#| export\n",
763+
"@patch\n",
764+
"def _is_dir_empty(self:Path): return next(self.iterdir(), None) is None"
765+
]
766+
},
767+
{
768+
"cell_type": "code",
769+
"execution_count": null,
770+
"id": "c18149e1",
771+
"metadata": {},
772+
"outputs": [],
773+
"source": [
774+
"#| hide\n",
775+
"test_eq(td.is_dir_empty(), True)\n",
776+
"(td/'.temp').write_text('Hello, world!')\n",
777+
"test_eq(d.is_dir_empty(), False)"
778+
]
779+
},
780+
{
781+
"cell_type": "code",
782+
"execution_count": null,
783+
"id": "e54db8a2",
784+
"metadata": {},
785+
"outputs": [],
786+
"source": [
787+
"#| hide\n",
788+
"temp_dir.cleanup()"
789+
]
790+
},
742791
{
743792
"cell_type": "code",
744793
"execution_count": null,
@@ -754,13 +803,11 @@
754803
" save_path:Path=Path(\"./download/\")): # Save path (optional)\n",
755804
" 'Download your deployed app'\n",
756805
" if not name: name = _get_app_name(path)\n",
757-
" try: save_path.mkdir(exist_ok=False)\n",
758-
" except: print(f\"ERROR: Save path ({save_path}) already exists. Please rename or delete this folder to avoid accidental overwrites.\")\n",
759-
" else:\n",
760-
" if r := _mk_auth_req(_endpoint(rt=f'/download?name={name}')):\n",
761-
" file_bytes = io.BytesIO(r.content)\n",
762-
" with tarfile.open(fileobj=file_bytes, mode=\"r:gz\") as tar: tar.extractall(path=save_path)\n",
763-
" print(f\"Downloaded your app to: {save_path}\") "
806+
" save_path.mkdir(exist_ok=True)\n",
807+
" if not save_path._is_dir_empty(): return print(f'ERROR: Save path ({save_path}) is not empty.')\n",
808+
" if r := _mk_auth_req(_endpoint(rt=f'/download?name={name}')):\n",
809+
" with tarfile.open(fileobj=io.BytesIO(r.content), mode=\"r:gz\") as tar: tar.extractall(path=save_path)\n",
810+
" print(f\"Downloaded your app to: {save_path}\") "
764811
]
765812
},
766813
{

plash_cli/_modidx.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
'plash_cli.auth._signin_url': ('auth.html#_signin_url', 'plash_cli/auth.py'),
1111
'plash_cli.auth.goog_id_from_signin_reply': ('auth.html#goog_id_from_signin_reply', 'plash_cli/auth.py'),
1212
'plash_cli.auth.mk_signin_url': ('auth.html#mk_signin_url', 'plash_cli/auth.py')},
13-
'plash_cli.cli': { 'plash_cli.cli.PlashError': ('cli.html#plasherror', 'plash_cli/cli.py'),
13+
'plash_cli.cli': { 'plash_cli.cli.Path._is_dir_empty': ('cli.html#path._is_dir_empty', 'plash_cli/cli.py'),
14+
'plash_cli.cli.PlashError': ('cli.html#plasherror', 'plash_cli/cli.py'),
1415
'plash_cli.cli._deps': ('cli.html#_deps', 'plash_cli/cli.py'),
1516
'plash_cli.cli._endpoint': ('cli.html#_endpoint', 'plash_cli/cli.py'),
1617
'plash_cli.cli._gen_app_name': ('cli.html#_gen_app_name', 'plash_cli/cli.py'),

plash_cli/cli.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ def _get_client(cookie_file):
3232
return client
3333

3434
# %% ../nbs/00_cli.ipynb 8
35-
def _mk_auth_req(url:str, method:str='get', **kwargs):
36-
r = getattr(_get_client(PLASH_CONFIG_HOME), method)(url, **kwargs)
35+
def _mk_auth_req(url:str, method:str='get', timeout=300., **kwargs):
36+
r = getattr(_get_client(PLASH_CONFIG_HOME), method)(url, timeout=timeout, **kwargs)
3737
if r.status_code == 200: return r
3838
else: print(f'Failure: {r.headers["X-Plash-Error"]}')
3939

@@ -167,7 +167,7 @@ def deploy(
167167
plash_app.write_text(f'export PLASH_APP_NAME={name}')
168168

169169
tarz, _ = create_tar_archive(path, force_data)
170-
r = _mk_auth_req(_endpoint(rt="/upload"), "post", files={'file': tarz}, timeout=300.0,
170+
r = _mk_auth_req(_endpoint(rt="/upload"), "post", files={'file': tarz},
171171
data={'name': name, 'force_data': force_data})
172172
if r:
173173
print('✅ Upload complete! Your app is currently being built.')
@@ -240,23 +240,25 @@ def logs(
240240
except KeyboardInterrupt: return "\nExiting"
241241
if r := _mk_auth_req(_endpoint(rt=f"/logs?name={name}&mode={mode}")): return r.text
242242

243-
# %% ../nbs/00_cli.ipynb 43
243+
# %% ../nbs/00_cli.ipynb 44
244+
@patch
245+
def _is_dir_empty(self:Path): return next(self.iterdir(), None) is None
246+
247+
# %% ../nbs/00_cli.ipynb 47
244248
@call_parse
245249
def download(
246250
path:Path=Path('.'), # Path to project
247251
name:str=None, # Overrides the .plash file in project root if provided
248252
save_path:Path=Path("./download/")): # Save path (optional)
249253
'Download your deployed app'
250254
if not name: name = _get_app_name(path)
251-
try: save_path.mkdir(exist_ok=False)
252-
except: print(f"ERROR: Save path ({save_path}) already exists. Please rename or delete this folder to avoid accidental overwrites.")
253-
else:
254-
if r := _mk_auth_req(_endpoint(rt=f'/download?name={name}')):
255-
file_bytes = io.BytesIO(r.content)
256-
with tarfile.open(fileobj=file_bytes, mode="r:gz") as tar: tar.extractall(path=save_path)
257-
print(f"Downloaded your app to: {save_path}")
255+
save_path.mkdir(exist_ok=True)
256+
if not save_path._is_dir_empty(): return print(f'ERROR: Save path ({save_path}) is not empty.')
257+
if r := _mk_auth_req(_endpoint(rt=f'/download?name={name}')):
258+
with tarfile.open(fileobj=io.BytesIO(r.content), mode="r:gz") as tar: tar.extractall(path=save_path)
259+
print(f"Downloaded your app to: {save_path}")
258260

259-
# %% ../nbs/00_cli.ipynb 46
261+
# %% ../nbs/00_cli.ipynb 50
260262
@call_parse
261263
def apps(verbose:bool=False):
262264
"List your deployed apps (verbose shows status table: 1=running, 0=stopped)"

0 commit comments

Comments
 (0)