remotivelabs-cli 0.0.41__tar.gz → 0.1.0__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.
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/PKG-INFO +6 -4
- remotivelabs_cli-0.1.0/cli/.DS_Store +0 -0
- remotivelabs_cli-0.1.0/cli/api/cloud/tokens.py +62 -0
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/broker/brokers.py +0 -1
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/broker/export.py +4 -4
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/broker/lib/broker.py +9 -13
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/broker/license_flows.py +1 -1
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/broker/scripting.py +2 -1
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/broker/signals.py +9 -10
- remotivelabs_cli-0.1.0/cli/cloud/auth/cmd.py +91 -0
- remotivelabs_cli-0.1.0/cli/cloud/auth/login.py +316 -0
- remotivelabs_cli-0.1.0/cli/cloud/auth_tokens.py +340 -0
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/cloud/brokers.py +3 -4
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/cloud/cloud_cli.py +5 -5
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/cloud/configs.py +1 -2
- remotivelabs_cli-0.1.0/cli/cloud/organisations.py +112 -0
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/cloud/projects.py +5 -6
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/cloud/recordings.py +9 -16
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/cloud/recordings_playback.py +6 -8
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/cloud/sample_recordings.py +2 -3
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/cloud/service_account_tokens.py +21 -5
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/cloud/service_accounts.py +32 -4
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/cloud/storage/cmd.py +1 -1
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/cloud/storage/copy.py +3 -4
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/connect/connect.py +1 -1
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/connect/protopie/protopie.py +12 -14
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/errors.py +6 -1
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/remotive.py +30 -6
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/settings/__init__.py +1 -2
- remotivelabs_cli-0.1.0/cli/settings/config_file.py +92 -0
- remotivelabs_cli-0.1.0/cli/settings/core.py +404 -0
- remotivelabs_cli-0.1.0/cli/settings/migrate_all_token_files.py +74 -0
- remotivelabs_cli-0.1.0/cli/settings/migrate_token_file.py +52 -0
- remotivelabs_cli-0.1.0/cli/settings/token_file.py +87 -0
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/tools/can/can.py +2 -2
- remotivelabs_cli-0.1.0/cli/typer/typer_utils.py +25 -0
- remotivelabs_cli-0.1.0/cli/utils/__init__.py +0 -0
- {remotivelabs_cli-0.0.41/cli/cloud → remotivelabs_cli-0.1.0/cli/utils}/rest_helper.py +114 -39
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/pyproject.toml +23 -38
- remotivelabs_cli-0.0.41/cli/cloud/auth/cmd.py +0 -67
- remotivelabs_cli-0.0.41/cli/cloud/auth/login.py +0 -62
- remotivelabs_cli-0.0.41/cli/cloud/auth_tokens.py +0 -33
- remotivelabs_cli-0.0.41/cli/cloud/organisations.py +0 -29
- remotivelabs_cli-0.0.41/cli/settings/cmd.py +0 -72
- remotivelabs_cli-0.0.41/cli/settings/core.py +0 -261
- remotivelabs_cli-0.0.41/cli/settings/token_file.py +0 -22
- remotivelabs_cli-0.0.41/cli/typer/typer_utils.py +0 -8
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/LICENSE +0 -0
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/README.md +0 -0
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/__init__.py +0 -0
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/broker/files.py +0 -0
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/broker/lib/__about__.py +0 -0
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/broker/licenses.py +0 -0
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/broker/playback.py +0 -0
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/broker/record.py +0 -0
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/cloud/__init__.py +0 -0
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/cloud/auth/__init__.py +0 -0
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/cloud/resumable_upload.py +0 -0
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/cloud/storage/__init__.py +0 -0
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/cloud/storage/uri_or_path.py +0 -0
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/cloud/uri.py +0 -0
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/connect/__init__.py +0 -0
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/tools/__init__.py +0 -0
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/tools/can/__init__.py +0 -0
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/tools/tools.py +0 -0
- {remotivelabs_cli-0.0.41 → remotivelabs_cli-0.1.0}/cli/typer/__init__.py +0 -0
@@ -1,16 +1,18 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.3
|
2
2
|
Name: remotivelabs-cli
|
3
|
-
Version: 0.0
|
3
|
+
Version: 0.1.0
|
4
4
|
Summary: CLI for operating RemotiveCloud and RemotiveBroker
|
5
5
|
Author: Johan Rask
|
6
6
|
Author-email: johan.rask@remotivelabs.com
|
7
|
-
Requires-Python: >=3.
|
7
|
+
Requires-Python: >=3.9,<4
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
9
|
-
Classifier: Programming Language :: Python :: 3.8
|
10
9
|
Classifier: Programming Language :: Python :: 3.9
|
11
10
|
Classifier: Programming Language :: Python :: 3.10
|
12
11
|
Classifier: Programming Language :: Python :: 3.11
|
13
12
|
Classifier: Programming Language :: Python :: 3.12
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
14
|
+
Requires-Dist: click (<8.2.0)
|
15
|
+
Requires-Dist: dacite (>=1.9.2,<2.0.0)
|
14
16
|
Requires-Dist: grpc-stubs (>=1.53.0.5)
|
15
17
|
Requires-Dist: mypy-protobuf (>=3.0.0)
|
16
18
|
Requires-Dist: plotext (>=5.2,<6.0)
|
Binary file
|
@@ -0,0 +1,62 @@
|
|
1
|
+
import dataclasses
|
2
|
+
from typing import Any
|
3
|
+
|
4
|
+
import requests
|
5
|
+
|
6
|
+
from cli.utils.rest_helper import RestHelper as Rest
|
7
|
+
|
8
|
+
#
|
9
|
+
# Attempt to start cloud-api.
|
10
|
+
# Might be better to generate somehow instead.
|
11
|
+
# Lets discuss further
|
12
|
+
#
|
13
|
+
|
14
|
+
|
15
|
+
@dataclasses.dataclass
|
16
|
+
class EmptyResponse:
|
17
|
+
is_success: bool
|
18
|
+
status_code: int
|
19
|
+
|
20
|
+
|
21
|
+
@dataclasses.dataclass
|
22
|
+
class JsonResponse:
|
23
|
+
is_success: bool
|
24
|
+
status_code: int
|
25
|
+
__response: requests.Response
|
26
|
+
|
27
|
+
def json(self) -> Any:
|
28
|
+
return self.__response.json()
|
29
|
+
|
30
|
+
def text(self) -> str:
|
31
|
+
return self.__response.text
|
32
|
+
|
33
|
+
|
34
|
+
def __delete_response_from_response(response: requests.Response) -> EmptyResponse:
|
35
|
+
if 200 > response.status_code > 299:
|
36
|
+
ok = False
|
37
|
+
else:
|
38
|
+
ok = True
|
39
|
+
return EmptyResponse(is_success=ok, status_code=response.status_code)
|
40
|
+
|
41
|
+
|
42
|
+
def __json_response_from_response(response: requests.Response) -> JsonResponse:
|
43
|
+
if 200 > response.status_code > 299:
|
44
|
+
ok = False
|
45
|
+
else:
|
46
|
+
ok = True
|
47
|
+
return JsonResponse(is_success=ok, status_code=response.status_code, __response=response)
|
48
|
+
|
49
|
+
|
50
|
+
def create() -> JsonResponse:
|
51
|
+
response = Rest.handle_post(url="/api/me/keys", return_response=True)
|
52
|
+
return __json_response_from_response(response)
|
53
|
+
|
54
|
+
|
55
|
+
def revoke(name: str) -> EmptyResponse:
|
56
|
+
res_revoke = Rest.handle_patch(f"/api/me/keys/{name}/revoke", quiet=True, allow_status_codes=[404, 401])
|
57
|
+
return __delete_response_from_response(res_revoke)
|
58
|
+
|
59
|
+
|
60
|
+
def delete(name: str) -> EmptyResponse:
|
61
|
+
res_delete = Rest.handle_delete(f"/api/me/keys/{name}", quiet=True, allow_status_codes=[404, 401])
|
62
|
+
return __delete_response_from_response(res_delete)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
import os
|
4
3
|
import signal as os_signal
|
4
|
+
import sys
|
5
5
|
from typing import Any, List
|
6
6
|
|
7
7
|
import grpc
|
@@ -57,7 +57,7 @@ def influxdb(
|
|
57
57
|
def exit_on_ctrlc(_sig: Any, _frame: Any) -> None:
|
58
58
|
if output is not None:
|
59
59
|
f.close()
|
60
|
-
|
60
|
+
sys.exit(0)
|
61
61
|
|
62
62
|
def per_frame_influx_line_protocol(x: Any) -> None:
|
63
63
|
signals = list(x)
|
@@ -67,7 +67,7 @@ def influxdb(
|
|
67
67
|
frame = signals[0]["name"].rsplit(".", 1)[0]
|
68
68
|
# frame_name = signals[0]["name"].split(".")[1]
|
69
69
|
namespace = signals[0]["namespace"]
|
70
|
-
signals_str = ",".join(list(map(lambda s: f
|
70
|
+
signals_str = ",".join(list(map(lambda s: f"{sig}={s['value']}", signals)))
|
71
71
|
influx_lp = f"{frame},namespace={namespace} {signals_str} {round(signals[0]['timestamp_us'] * 1000)}"
|
72
72
|
if output is not None:
|
73
73
|
f.write(f"{influx_lp}\n")
|
@@ -112,7 +112,7 @@ def influxdb(
|
|
112
112
|
arr = sig.split(":")
|
113
113
|
if len(arr) != 2:
|
114
114
|
ErrorPrinter.print_hint(f"--signal must have format namespace:signal ({sig})")
|
115
|
-
exit(1)
|
115
|
+
sys.exit(1)
|
116
116
|
|
117
117
|
return SubscribableSignal(namespace=arr[0], name=arr[1])
|
118
118
|
|
@@ -6,6 +6,7 @@ import os
|
|
6
6
|
import posixpath
|
7
7
|
import queue
|
8
8
|
import signal as os_signal
|
9
|
+
import sys
|
9
10
|
import tempfile
|
10
11
|
import time
|
11
12
|
import zipfile
|
@@ -59,9 +60,7 @@ class Broker:
|
|
59
60
|
os.environ["ACCESS_TOKEN"] = "false"
|
60
61
|
self.intercept_channel = br.create_channel(url, None, None)
|
61
62
|
else:
|
62
|
-
err_console.print(
|
63
|
-
"Option --api-key will is deprecated and will be removed. " "Use access access tokens by logging in with cli."
|
64
|
-
)
|
63
|
+
err_console.print("Option --api-key will is deprecated and will be removed. Use access access tokens by logging in with cli.")
|
65
64
|
os.environ["ACCESS_TOKEN"] = "false"
|
66
65
|
self.intercept_channel = br.create_channel(url, api_key, None)
|
67
66
|
|
@@ -303,11 +302,10 @@ class Broker:
|
|
303
302
|
|
304
303
|
for r in response:
|
305
304
|
if r["data"]:
|
306
|
-
print(f
|
305
|
+
print(f"Successfully received traffic on {r['namespace']}")
|
307
306
|
keep_running = False
|
308
|
-
|
309
|
-
|
310
|
-
print(f'Namespace {r["namespace"]} did not receive any traffic')
|
307
|
+
elif not wait_for_traffic or (not keep_running and not keep_running_during_recording):
|
308
|
+
print(f"Namespace {r['namespace']} did not receive any traffic")
|
311
309
|
|
312
310
|
def upload(self, file: str, dest: str) -> None:
|
313
311
|
try:
|
@@ -456,10 +454,8 @@ class Broker:
|
|
456
454
|
if ns not in existing_ns:
|
457
455
|
ns_not_matching.append(ns)
|
458
456
|
if len(ns_not_matching) > 0:
|
459
|
-
ErrorPrinter.print_hint(
|
460
|
-
|
461
|
-
)
|
462
|
-
exit(1)
|
457
|
+
ErrorPrinter.print_hint(f"Namespace(s) {ns_not_matching} does not exist on broker. Namespaces found on broker: {existing_ns}")
|
458
|
+
sys.exit(1)
|
463
459
|
|
464
460
|
available_signals = list(filter(verify_namespace, existing_signals)) # type: ignore
|
465
461
|
signals_to_subscribe_to = list(filter(find_subscribed_signal, available_signals)) # type: ignore
|
@@ -468,8 +464,8 @@ class Broker:
|
|
468
464
|
signals_subscribed_to_but_does_not_exist = set(subscribed_signals) - set(map(lambda s: s["signal"], signals_to_subscribe_to))
|
469
465
|
|
470
466
|
if len(signals_subscribed_to_but_does_not_exist) > 0:
|
471
|
-
ErrorPrinter.print_hint(f"One or more signals you subscribed to does not exist
|
472
|
-
exit(1)
|
467
|
+
ErrorPrinter.print_hint(f"One or more signals you subscribed to does not exist {signals_subscribed_to_but_does_not_exist}")
|
468
|
+
sys.exit(1)
|
473
469
|
|
474
470
|
return list(map(lambda s: SubscribableSignal(s["signal"], s["namespace"]), signals_to_subscribe_to))
|
475
471
|
|
@@ -11,7 +11,7 @@ from rich.console import Console
|
|
11
11
|
from rich.progress import Progress, SpinnerColumn, TextColumn
|
12
12
|
|
13
13
|
from cli.broker.lib.broker import Broker, LicenseInfo
|
14
|
-
from cli.
|
14
|
+
from cli.utils.rest_helper import RestHelper as Rest
|
15
15
|
|
16
16
|
console = Console(stderr=True)
|
17
17
|
|
@@ -1,5 +1,6 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
+
import sys
|
3
4
|
from string import Template
|
4
5
|
from typing import List
|
5
6
|
|
@@ -35,7 +36,7 @@ def new_script(
|
|
35
36
|
arr = sig.split(":")
|
36
37
|
if len(arr) != 2:
|
37
38
|
ErrorPrinter.print_hint(f"--input-signal must have format namespace:signal ({sig})")
|
38
|
-
exit(1)
|
39
|
+
sys.exit(1)
|
39
40
|
return arr[0], arr[1]
|
40
41
|
|
41
42
|
signals_to_subscribe_to = list(map(to_subscribable_signal, input_signal))
|
@@ -4,6 +4,7 @@ import json
|
|
4
4
|
import numbers
|
5
5
|
import os
|
6
6
|
import signal as os_signal
|
7
|
+
import sys
|
7
8
|
from datetime import datetime
|
8
9
|
from pathlib import Path
|
9
10
|
from typing import Any, Dict, Iterable, List, TypedDict, Union
|
@@ -60,11 +61,11 @@ def read_scripted_code_file(file_path: Path) -> bytes:
|
|
60
61
|
return file.read()
|
61
62
|
except FileNotFoundError:
|
62
63
|
print("File not found. Please check your file path.")
|
63
|
-
exit(1)
|
64
|
+
sys.exit(1)
|
64
65
|
|
65
66
|
|
66
67
|
@app.command()
|
67
|
-
def subscribe( # noqa: C901
|
68
|
+
def subscribe( # noqa: C901, PLR0913, PLR0915
|
68
69
|
url: str = typer.Option(DEFAULT_GRPC_URL, help="Broker URL", envvar="REMOTIVE_BROKER_URL"),
|
69
70
|
api_key: str = typer.Option(None, help="Cloud Broker API-KEY or access token", envvar="REMOTIVE_BROKER_API_KEY"),
|
70
71
|
signal: List[str] = typer.Option([], help="Signal names to subscribe to, mandatory when not using script"),
|
@@ -79,7 +80,7 @@ def subscribe( # noqa: C901
|
|
79
80
|
help="Supply a path to Lua script that to use for signal transformation",
|
80
81
|
),
|
81
82
|
on_change_only: bool = typer.Option(default=False, help="Only get signal if value is changed"),
|
82
|
-
x_plot: bool = typer.Option(default=False, help="Experimental: Plot the signal in terminal. Note graphs are not
|
83
|
+
x_plot: bool = typer.Option(default=False, help="Experimental: Plot the signal in terminal. Note graphs are not aligned by time"),
|
83
84
|
x_plot_size: int = typer.Option(default=100, help="Experimental: how many points show for each plot"),
|
84
85
|
# samples: int = typer.Option(default=0, he)
|
85
86
|
) -> None:
|
@@ -100,12 +101,12 @@ def subscribe( # noqa: C901
|
|
100
101
|
if script is None:
|
101
102
|
if len(signal) == 0:
|
102
103
|
ErrorPrinter.print_generic_error("You must use --signal or use --script when subscribing")
|
103
|
-
exit(1)
|
104
|
+
sys.exit(1)
|
104
105
|
|
105
106
|
if script is not None:
|
106
107
|
if len(signal) > 0:
|
107
108
|
ErrorPrinter.print_generic_error("You must must not specify --signal when using --script")
|
108
|
-
exit(1)
|
109
|
+
sys.exit(1)
|
109
110
|
|
110
111
|
plt.title("Signals")
|
111
112
|
|
@@ -113,8 +114,6 @@ def subscribe( # noqa: C901
|
|
113
114
|
os._exit(0)
|
114
115
|
|
115
116
|
def on_frame_plot(x: Iterable[Any]) -> None:
|
116
|
-
global signal_values
|
117
|
-
|
118
117
|
plt.clt() # to clear the terminal
|
119
118
|
plt.cld() # to clear the data only
|
120
119
|
frames = list(x)
|
@@ -146,9 +145,9 @@ def subscribe( # noqa: C901
|
|
146
145
|
signal_values[f"ts_{name}"] = signal_values[f"ts_{name}"][len(signal_values[f"ts_{name}"]) - x_plot_size :]
|
147
146
|
|
148
147
|
cnt = 1
|
149
|
-
for key in signal_values:
|
148
|
+
for key, value in signal_values.items():
|
150
149
|
if not key.startswith("ts_"):
|
151
|
-
plt.subplot(cnt, 1).plot(signal_values[f"ts_{key}"],
|
150
|
+
plt.subplot(cnt, 1).plot(signal_values[f"ts_{key}"], value, label=key, color=cnt)
|
152
151
|
cnt = cnt + 1
|
153
152
|
plt.sleep(0.001) # to add
|
154
153
|
plt.show()
|
@@ -174,7 +173,7 @@ def subscribe( # noqa: C901
|
|
174
173
|
arr = sig.split(":")
|
175
174
|
if len(arr) != 2:
|
176
175
|
ErrorPrinter.print_hint(f"--signal must have format namespace:signal ({sig})")
|
177
|
-
exit(1)
|
176
|
+
sys.exit(1)
|
178
177
|
return SubscribableSignal(namespace=arr[0], name=arr[1])
|
179
178
|
|
180
179
|
signals_to_subscribe_to = list(map(to_subscribable_signal, signal))
|
@@ -0,0 +1,91 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import sys
|
4
|
+
|
5
|
+
import typer
|
6
|
+
|
7
|
+
from cli.cloud.auth.login import login as do_login
|
8
|
+
from cli.errors import ErrorPrinter
|
9
|
+
from cli.settings import TokenNotFoundError, settings
|
10
|
+
from cli.typer import typer_utils
|
11
|
+
from cli.utils.rest_helper import RestHelper as Rest
|
12
|
+
|
13
|
+
from .. import auth_tokens
|
14
|
+
|
15
|
+
HELP = """
|
16
|
+
Manage how you authenticate with our cloud platform
|
17
|
+
"""
|
18
|
+
app = typer_utils.create_typer(help=HELP)
|
19
|
+
# app.add_typer(auth_tokens.app, name="credentials", help="Manage account credentials")
|
20
|
+
|
21
|
+
|
22
|
+
@app.command(name="login")
|
23
|
+
def login(browser: bool = typer.Option(default=True, help="Does not automatically open browser, instead shows a link")) -> None:
|
24
|
+
"""
|
25
|
+
Login to the cli using browser
|
26
|
+
|
27
|
+
If not able to open a browser it will show fallback to headless login and show a link that
|
28
|
+
users can copy into any browser when this is unsupported where running the cli - such as in docker,
|
29
|
+
virtual machine or ssh sessions.
|
30
|
+
|
31
|
+
This will be used as the current access token in all subsequent requests. This would
|
32
|
+
be the same as activating a personal access key or service-account access key.
|
33
|
+
"""
|
34
|
+
do_login(headless=not browser)
|
35
|
+
|
36
|
+
|
37
|
+
@app.command()
|
38
|
+
def whoami() -> None:
|
39
|
+
"""
|
40
|
+
Validates authentication and fetches your account information
|
41
|
+
"""
|
42
|
+
try:
|
43
|
+
Rest.handle_get("/api/whoami")
|
44
|
+
except TokenNotFoundError as e:
|
45
|
+
ErrorPrinter.print_hint(str(e))
|
46
|
+
sys.exit(1)
|
47
|
+
|
48
|
+
|
49
|
+
@app.command()
|
50
|
+
def print_access_token(
|
51
|
+
account: str = typer.Option(None, help="Email of the account you want to print access token for, defaults to active"),
|
52
|
+
) -> None:
|
53
|
+
"""
|
54
|
+
Print current active access token or the token for the specified account
|
55
|
+
"""
|
56
|
+
if account is None:
|
57
|
+
try:
|
58
|
+
print(settings.get_active_token())
|
59
|
+
except TokenNotFoundError:
|
60
|
+
ErrorPrinter.print_generic_error("You have no active account", exit_code=1)
|
61
|
+
else:
|
62
|
+
config = settings.get_cli_config()
|
63
|
+
if account in config.accounts:
|
64
|
+
token_name = config.accounts[account].credentials_name
|
65
|
+
try:
|
66
|
+
print(settings.get_token_file(token_name).token)
|
67
|
+
except TokenNotFoundError:
|
68
|
+
ErrorPrinter.print_generic_error(f"Token file for {account} could not be found", exit_code=1)
|
69
|
+
else:
|
70
|
+
ErrorPrinter.print_generic_error(f"No account for {account} was found", exit_code=1)
|
71
|
+
|
72
|
+
|
73
|
+
def print_access_token_file() -> None:
|
74
|
+
"""
|
75
|
+
Print current active token and its metadata
|
76
|
+
"""
|
77
|
+
try:
|
78
|
+
print(settings.get_active_token_file())
|
79
|
+
except TokenNotFoundError as e:
|
80
|
+
ErrorPrinter.print_hint(str(e))
|
81
|
+
sys.exit(1)
|
82
|
+
|
83
|
+
|
84
|
+
# @app.command(help="Clears active credentials")
|
85
|
+
def logout() -> None:
|
86
|
+
settings.clear_active_token()
|
87
|
+
print("Access token removed")
|
88
|
+
|
89
|
+
|
90
|
+
app.command("activate")(auth_tokens.select_personal_token)
|
91
|
+
app.command("list")(auth_tokens.list_pats_files)
|