Skip to content

Commit 58c2ad3

Browse files
caseneuvefiliplajszczak
authored andcommitted
#29 enables controlled logging (snakesay) in cli path commands, moves path sanitizing to PAPath; minor fixes
1 parent 7e8133c commit 58c2ad3

File tree

6 files changed

+115
-74
lines changed

6 files changed

+115
-74
lines changed

cli/path.py

Lines changed: 43 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,44 @@
1-
import getpass
21
import re
32
import sys
3+
from typing import Tuple
44

55
from collections import namedtuple
66
from pprint import pprint
77

88
import typer
99

1010
from pythonanywhere.files import PAPath
11+
from pythonanywhere.scripts_commons import get_logger
1112

1213
app = typer.Typer()
1314

1415

15-
def standarize_path(path):
16-
return path.replace("~", f"/home/{getpass.getuser()}") if path.startswith("~") else path
16+
def setup(path: str, quiet: bool) -> Tuple[str, PAPath]:
17+
logger = get_logger(set_info=True)
18+
if quiet:
19+
logger.disabled = True
20+
return PAPath(path)
1721

1822

1923
@app.command()
2024
def get(
21-
path: str = typer.Argument(..., help="Path to PythonAnywhere file or directory"),
22-
only_files: bool = typer.Option(False, "-f", "--files", help="List only files"),
23-
only_dirs: bool = typer.Option(False, "-d", "--dirs", help="List only directories"),
24-
sort_by_type: bool = typer.Option(False, "-t", "--type", help="Sort by type"),
25+
path: str = typer.Argument(..., help="Path to PythonAnywhere file or directory"),
26+
only_files: bool = typer.Option(False, "-f", "--files", help="List only files"),
27+
only_dirs: bool = typer.Option(False, "-d", "--dirs", help="List only directories"),
28+
sort_by_type: bool = typer.Option(False, "-t", "--type", help="Sort by type"),
2529
sort_reverse: bool = typer.Option(False, "-r", "--reverse", help="Sort in reverse order"),
26-
raw: bool = typer.Option(False, "-a", "--raw", help="Print API response (if PATH is file that's the only option)"),
30+
raw: bool = typer.Option(
31+
False, "-a", "--raw", help="Print API response (if PATH is file that's the only option)"
32+
),
33+
quiet: bool = typer.Option(False, "-q", "--quiet", help="Disable additional logging"),
2734
):
2835
"""
2936
Get contents of PATH.
3037
If PATH points to a directory, show list of it's contents.
3138
If PATH points to a file, print it's contents.
3239
"""
33-
path = standarize_path(path)
34-
contents = PAPath(path).contents
40+
pa_path = setup(path, quiet)
41+
contents = pa_path.contents
3542

3643
if contents is None:
3744
sys.exit(1)
@@ -47,7 +54,7 @@ def get(
4754
if sort_reverse or sort_by_type:
4855
data.sort(key=lambda x: x.type if sort_by_type else x.name, reverse=sort_reverse)
4956

50-
typer.echo(f"{path}:")
57+
typer.echo(f"{pa_path.path}:")
5158
for name, type_ in data:
5259
if item == "every":
5360
typer.echo(f"{type_[0].upper()} {name}")
@@ -79,14 +86,19 @@ def _format_tree(data, current):
7986

8087

8188
@app.command()
82-
def tree(path: str = typer.Argument(..., help="Path to PythonAnywhere file or directory")):
83-
path = standarize_path(path)
84-
tree = PAPath(path).tree
89+
def tree(
90+
path: str = typer.Argument(..., help="Path to PythonAnywhere file or directory"),
91+
quiet: bool = typer.Option(False, "-q", "--quiet", help="Disable additional logging")
92+
):
93+
pa_path = setup(path, quiet)
94+
tree = pa_path.tree
8595

8696
if tree is not None:
87-
typer.echo(f"{path}:")
97+
typer.echo(f"{pa_path.path}:")
8898
typer.echo(".")
89-
typer.echo(_format_tree(tree, path))
99+
typer.echo(_format_tree(tree, pa_path.path))
100+
else:
101+
sys.exit(1)
90102

91103

92104
@app.command()
@@ -104,47 +116,44 @@ def upload(
104116
"--contents",
105117
help="Path to exisitng file or stdin stream that should be uploaded to PATH"
106118
),
119+
quiet: bool = typer.Option(False, "-q", "--quiet", help="Disable additional logging")
107120
):
108-
path = standarize_path(path)
109-
pa_path = PAPath(path)
110-
121+
pa_path = setup(path, quiet)
111122
success = pa_path.upload(file)
112-
113123
sys.exit(0 if success else 1)
114124

115125

116126
@app.command()
117127
def delete(
118128
path: str = typer.Argument(..., help="Path to PythonAnywhere file or directory to be deleted"),
129+
quiet: bool = typer.Option(False, "-q", "--quiet", help="Disable additional logging")
119130
):
120-
path = standarize_path(path)
121-
pa_path = PAPath(path)
122-
131+
pa_path = setup(path, quiet)
123132
success = pa_path.delete()
124-
125133
sys.exit(0 if success else 1)
126134

127135

128136
@app.command()
129137
def share(
130138
path: str = typer.Argument(..., help="Path to PythonAnywhere file to be shared"),
131-
check: bool = typer.Option(False, "-c", "--check", help="Check sharing status")
139+
check: bool = typer.Option(False, "-c", "--check", help="Check sharing status"),
140+
porcelain: bool = typer.Option(False, "-p", "--porcelain", help="Return sharing url in easy-to-parse format"),
141+
quiet: bool = typer.Option(False, "-q", "--quiet", help="Disable logging"),
132142
):
133-
path = standarize_path(path)
134-
pa_path = PAPath(path)
135-
143+
pa_path = setup(path, quiet or porcelain)
136144
link = pa_path.get_sharing_url() if check else pa_path.share()
137145

138146
if not link:
139147
sys.exit(1)
140-
typer.echo(link)
148+
if porcelain:
149+
typer.echo(link)
141150

142151

143152
@app.command()
144-
def unshare(path: str = typer.Argument(..., help="Path to PythonAnywhere file to be unshared")):
145-
path = standarize_path(path)
146-
pa_path = PAPath(path)
147-
153+
def unshare(
154+
path: str = typer.Argument(..., help="Path to PythonAnywhere file to be unshared"),
155+
quiet: bool = typer.Option(False, "-q", "--quiet", help="Disable additional logging")
156+
):
157+
pa_path = setup(path, quiet)
148158
success = pa_path.unshare()
149-
150159
sys.exit(0 if success else 1)

pythonanywhere/api/files_api.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
`pythonanywhere.files.Path` class instead."""
44

55
import getpass
6-
from os import path
76
from urllib.parse import urljoin
87

98
from pythonanywhere.api.base import call_api, get_api_endpoint

pythonanywhere/files.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22
Provides a class `PAPath` which should be used by helper scripts
33
providing features for programmatic handling of user's files."""
44

5+
import getpass
56
import logging
67
from urllib.parse import urljoin
78

89
from pythonanywhere.api.files_api import Files
910
from pythonanywhere.snakesay import snakesay
1011

11-
logger = logging.getLogger(name=__name__)
12+
logger = logging.getLogger("pythonanywhere")
1213

1314

1415
class PAPath:
@@ -37,7 +38,7 @@ class PAPath:
3738
be created with :method:`PAPath.upload`."""
3839

3940
def __init__(self, path):
40-
self.path = path
41+
self.path = self._standarize_path(path)
4142
self.api = Files()
4243

4344
def __repr__(self):
@@ -46,6 +47,10 @@ def __repr__(self):
4647
def _make_sharing_url(self, path):
4748
return urljoin(self.api.base_url.split("api")[0], path)
4849

50+
def _standarize_path(self, path):
51+
return path.replace("~", f"/home/{getpass.getuser()}") if path.startswith("~") else path
52+
53+
4954
@property
5055
def url(self):
5156
"""Returns url to PythonAnywhere for `self.path`. Does not
@@ -135,25 +140,28 @@ def get_sharing_url(self):
135140

136141
url = self.api.sharing_get(self.path)
137142
if url:
138-
logger.info(snakesay(f"{self.path} is shared at {url}"))
139-
return self._make_sharing_url(url)
143+
sharing_url = self._make_sharing_url(url)
144+
logger.info(snakesay(f"{self.path} is shared at {sharing_url}"))
145+
return sharing_url
140146

141147
logger.info(snakesay(f"{self.path} has not been shared"))
148+
142149
return ""
143150

144151
def share(self):
145152
"""Returns PythonAnywhere sharing link for `self.path` or an
146153
empty string when share not successful."""
147154

148155
try:
149-
code, shared_url = self.api.sharing_post(self.path)
156+
code, url = self.api.sharing_post(self.path)
150157
except Exception as e:
151158
logger.warning(snakesay(str(e)))
152159
return ""
153160

154161
msg = {200: "was already", 201: "successfully"}[code]
155-
logger.info(snakesay(f"{self.path} {msg} shared at {shared_url}"))
156-
return self._make_sharing_url(shared_url)
162+
sharing_url = self._make_sharing_url(url)
163+
logger.info(snakesay(f"{self.path} {msg} shared at {sharing_url}"))
164+
return sharing_url
157165

158166
def unshare(self):
159167
"""Returns `True` when file unshared or has not been shared,

0 commit comments

Comments
 (0)