Skip to content

Commit 78cca71

Browse files
authored
Send errors and warnings to stderr (#644)
1 parent 89e7b7a commit 78cca71

File tree

14 files changed

+96
-57
lines changed

14 files changed

+96
-57
lines changed

linodecli/__init__.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def main(): # pylint: disable=too-many-branches,too-many-statements
101101
# handle a bake - this is used to parse a spec and bake it as a pickle
102102
if parsed.command == "bake":
103103
if parsed.action is None:
104-
print("No spec provided, cannot bake")
104+
print("No spec provided, cannot bake", file=sys.stderr)
105105
sys.exit(ExitCodes.ARGUMENT_ERROR)
106106
bake_command(cli, parsed.action)
107107
sys.exit(ExitCodes.SUCCESS)
@@ -111,15 +111,18 @@ def main(): # pylint: disable=too-many-branches,too-many-statements
111111

112112
if parsed.command == "register-plugin":
113113
if parsed.action is None:
114-
print("register-plugin requires a module name!")
114+
print("register-plugin requires a module name!", file=sys.stderr)
115115
sys.exit(ExitCodes.ARGUMENT_ERROR)
116116
msg, code = register_plugin(parsed.action, cli.config, cli.ops)
117117
print(msg)
118118
sys.exit(code)
119119

120120
if parsed.command == "remove-plugin":
121121
if parsed.action is None:
122-
print("remove-plugin requires a plugin name to remove!")
122+
print(
123+
"remove-plugin requires a plugin name to remove!",
124+
file=sys.stderr,
125+
)
123126
sys.exit(ExitCodes.ARGUMENT_ERROR)
124127
msg, code = remove_plugin(parsed.action, cli.config)
125128
print(msg)
@@ -216,7 +219,7 @@ def main(): # pylint: disable=too-many-branches,too-many-statements
216219
and parsed.command not in plugins.available(cli.config)
217220
and parsed.command not in HELP_TOPICS
218221
):
219-
print(f"Unrecognized command {parsed.command}")
222+
print(f"Unrecognized command {parsed.command}", file=sys.stderr)
220223
sys.exit(ExitCodes.UNRECOGNIZED_COMMAND)
221224

222225
# handle a help for a command - either --help or no action triggers this

linodecli/arg_helpers.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,10 @@ def register_plugin(module, config, ops):
107107

108108
reregistering = False
109109
if plugin_name in plugins.available(config):
110-
print(f"WARNING: Plugin {plugin_name} is already registered.\n\n")
110+
print(
111+
f"WARNING: Plugin {plugin_name} is already registered.\n\n",
112+
file=sys.stderr,
113+
)
111114
answer = input(f"Allow re-registration of {plugin_name}? [y/N] ")
112115
if not answer or answer not in "yY":
113116
return "Registration aborted.", 0
@@ -183,7 +186,7 @@ def bake_command(cli, spec_loc):
183186
else:
184187
raise RuntimeError(f"Request failed to {spec_loc}")
185188
except Exception as e:
186-
print(f"Could not load spec: {e}")
189+
print(f"Could not load spec: {e}", file=sys.stderr)
187190
sys.exit(ExitCodes.REQUEST_FAILED)
188191

189192
cli.bake(spec)

linodecli/cli.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,10 @@ def load_baked(self):
102102
self.spec = self.ops.pop("_spec")
103103
else:
104104
print(
105-
"No spec baked. Please bake by calling this script as follows:"
105+
"No spec baked. Please bake by calling this script as follows:",
106+
file=sys.stderr,
106107
)
107-
print(" python3 gen_cli.py bake /path/to/spec")
108+
print(" python3 gen_cli.py bake /path/to/spec", file=sys.stderr)
108109
self.ops = None # this signals __init__.py to give up
109110

110111
def _get_data_file(self):

linodecli/configuration/auth.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,10 @@ def _handle_response_status(
5858
if 199 < response.status_code < 300:
5959
return
6060

61-
print(f"Could not contact {response.url} - Error: {response.status_code}")
61+
print(
62+
f"Could not contact {response.url} - Error: {response.status_code}",
63+
file=sys.stderr,
64+
)
6265
if exit_on_error:
6366
sys.exit(ExitCodes.REQUEST_FAILED)
6467

@@ -194,7 +197,7 @@ def _username_for_token(base_url: str, token: str) -> str:
194197
u = _do_get_request(base_url, "/profile", token=token, exit_on_error=False)
195198
if "errors" in u:
196199
reasons = ",".join([c["reason"] for c in u["errors"]])
197-
print(f"That token didn't work: {reasons}")
200+
print(f"That token didn't work: {reasons}", file=sys.stderr)
198201
return None
199202

200203
return u["username"]
@@ -243,7 +246,10 @@ def _get_token_web(base_url: str) -> Tuple[str, str]:
243246
username = _username_for_token(base_url, temp_token)
244247

245248
if username is None:
246-
print("OAuth failed. Please try again of use a token for auth.")
249+
print(
250+
"OAuth failed. Please try again of use a token for auth.",
251+
file=sys.stderr,
252+
)
247253
sys.exit(ExitCodes.OAUTH_ERROR)
248254

249255
# the token returned via public oauth will expire in 2 hours, which
@@ -340,11 +346,11 @@ def log_message(self, form, *args): # pylint: disable=arguments-differ
340346
# serve requests one at a time until we get a token or are interrupted
341347
serv.handle_request()
342348
except KeyboardInterrupt:
343-
print()
344349
print(
345-
"Giving up. If you couldn't get web authentication to work, please "
350+
"\nGiving up. If you couldn't get web authentication to work, please "
346351
"try token using a token by invoking with `linode-cli configure --token`, "
347-
"and open an issue at https://github.com/linode/linode-cli"
352+
"and open an issue at https://github.com/linode/linode-cli",
353+
file=sys.stderr,
348354
)
349355
sys.exit(ExitCodes.OAUTH_ERROR)
350356

linodecli/configuration/config.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ def set_user(self, username: str):
9696
:type username: str
9797
"""
9898
if not self.config.has_section(username):
99-
print(f"User {username} is not configured!")
99+
print(f"User {username} is not configured!", file=sys.stderr)
100100
sys.exit(ExitCodes.USERNAME_ERROR)
101101

102102
self.username = username
@@ -112,7 +112,8 @@ def remove_user(self, username: str):
112112
if self.default_username() == username:
113113
print(
114114
f"Cannot remove {username} as they are the default user! You can "
115-
"change the default user with: `linode-cli set-user USERNAME`"
115+
"change the default user with: `linode-cli set-user USERNAME`",
116+
file=sys.stderr,
116117
)
117118
sys.exit(ExitCodes.USERNAME_ERROR)
118119

@@ -138,7 +139,7 @@ def set_default_user(self, username: str):
138139
Sets the default user. If that user isn't in the config, exits with error
139140
"""
140141
if not self.config.has_section(username):
141-
print(f"User {username} is not configured!")
142+
print(f"User {username} is not configured!", file=sys.stderr)
142143
sys.exit(ExitCodes.USERNAME_ERROR)
143144

144145
self.config.set("DEFAULT", "default-user", username)
@@ -288,7 +289,7 @@ def update(
288289
if not self.config.has_option(username, "token") and not os.environ.get(
289290
ENV_TOKEN_NAME, None
290291
):
291-
print(f"User {username} is not configured.")
292+
print(f"User {username} is not configured.", file=sys.stderr)
292293
sys.exit(ExitCodes.USERNAME_ERROR)
293294
if (
294295
not self.config.has_section(username)
@@ -328,7 +329,8 @@ def update(
328329
):
329330
print(
330331
f"Using default values: {warn_dict}; "
331-
"use the --no-defaults flag to disable defaults"
332+
"use the --no-defaults flag to disable defaults",
333+
file=sys.stderr,
332334
)
333335
return argparse.Namespace(**ns_dict)
334336

linodecli/plugins/firewall-editor.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def input(input_text: str, validator: Callable[[str], None]):
4343
try:
4444
validator(value)
4545
except ValueError as err:
46-
print(f"Invalid Input: {'; '.join(err.args)}")
46+
print(f"Invalid Input: {'; '.join(err.args)}", file=sys.stderr)
4747
continue
4848

4949
return value
@@ -204,15 +204,15 @@ def _get_firewall(firewall_id, client):
204204
)
205205

206206
if code != 200:
207-
print(f"Error retrieving firewall: {code}")
207+
print(f"Error retrieving firewall: {code}", file=sys.stderr)
208208
sys.exit(ExitCodes.FIREWALL_ERROR)
209209

210210
code, rules = client.call_operation(
211211
"firewalls", "rules-list", args=[firewall_id]
212212
)
213213

214214
if code != 200:
215-
print(f"Error retrieving firewall rules: {code}")
215+
print(f"Error retrieving firewall rules: {code}", file=sys.stderr)
216216
sys.exit(ExitCodes.FIREWALL_ERROR)
217217

218218
return firewall, rules
@@ -449,7 +449,7 @@ def remove_rule(rules):
449449
change = InputValidation.input_io(rules)
450450

451451
if len(change) < 1:
452-
print("No entires to remove")
452+
print("No entires to remove", file=sys.stderr)
453453
return False
454454

455455
ind_str = InputValidation.input(
@@ -614,9 +614,9 @@ def call(args, context):
614614
if code == 200:
615615
print("Rules updated successfully!")
616616
break
617-
print(f"Error editing rules: {code}: {errors}")
617+
print(f"Error editing rules: {code}: {errors}", file=sys.stderr)
618618
# block to see the error, then re-enter the editor
619619
sys.stdin.read(1)
620620
else:
621-
print("Aborted.")
621+
print("Aborted.", file=sys.stderr)
622622
break

linodecli/plugins/image-upload.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -121,30 +121,36 @@ def call(args, context):
121121
results = glob.glob(filepath, recursive=True)
122122

123123
if len(results) < 1:
124-
print(f"No file found matching pattern {filepath}")
124+
print(f"No file found matching pattern {filepath}", file=sys.stderr)
125125
sys.exit(ExitCodes.FILE_ERROR)
126126

127127
if len(results) > 1:
128128
print(
129-
f"warn: Found multiple files matching pattern {filepath}, using {results[0]}"
129+
f"warn: Found multiple files matching pattern {filepath}, using {results[0]}",
130+
file=sys.stderr,
130131
)
131132

132133
filepath = results[0]
133134

134135
if not os.path.isfile(filepath):
135-
print(f"No file at {filepath}; must be a path to a valid file.")
136+
print(
137+
f"No file at {filepath}; must be a path to a valid file.",
138+
file=sys.stderr,
139+
)
136140
sys.exit(ExitCodes.FILE_ERROR)
137141

138142
# make sure it's not larger than the max upload size
139143
if os.path.getsize(filepath) > MAX_UPLOAD_SIZE:
140144
print(
141-
f"File {filepath} is too large; compressed size must be less than 5GB"
145+
f"File {filepath} is too large; compressed size must be less than 5GB",
146+
file=sys.stderr,
142147
)
143148
sys.exit(ExitCodes.FILE_ERROR)
144149

145150
if not parsed.region:
146151
print(
147-
"No region provided. Please set a default region or use --region"
152+
"No region provided. Please set a default region or use --region",
153+
file=sys.stderr,
148154
)
149155
sys.exit(ExitCodes.ARGUMENT_ERROR)
150156

@@ -165,17 +171,22 @@ def call(args, context):
165171
print(
166172
"Your token was not authorized to use this endpoint. Please "
167173
"reconfigure the CLI with `linode-cli configure` to ensure you "
168-
"can make this request."
174+
"can make this request.",
175+
file=sys.stderr,
169176
)
170177
sys.exit(ExitCodes.REQUEST_FAILED)
171178
if status == 404:
172179
print(
173180
"It looks like you are not in the Machine Images Beta, and therefore "
174181
"cannot upload images yet. Please stay tuned, or open a support ticket "
175-
"to request access."
182+
"to request access.",
183+
file=sys.stderr,
176184
)
177185
sys.exit(ExitCodes.REQUEST_FAILED)
178-
print(f"Upload failed with status {status}; response was {resp}")
186+
print(
187+
f"Upload failed with status {status}; response was {resp}",
188+
file=sys.stderr,
189+
)
179190
sys.exit(ExitCodes.REQUEST_FAILED)
180191

181192
# grab the upload URL and image data

0 commit comments

Comments
 (0)