remotivelabs-cli 0.0.42__py3-none-any.whl → 0.1.0a2__py3-none-any.whl

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.
Files changed (44) hide show
  1. cli/.DS_Store +0 -0
  2. cli/api/cloud/tokens.py +62 -0
  3. cli/broker/brokers.py +0 -1
  4. cli/broker/export.py +4 -4
  5. cli/broker/lib/broker.py +9 -13
  6. cli/broker/license_flows.py +1 -1
  7. cli/broker/scripting.py +2 -1
  8. cli/broker/signals.py +9 -10
  9. cli/cloud/auth/cmd.py +37 -13
  10. cli/cloud/auth/login.py +279 -24
  11. cli/cloud/auth_tokens.py +319 -12
  12. cli/cloud/brokers.py +3 -4
  13. cli/cloud/cloud_cli.py +5 -5
  14. cli/cloud/configs.py +1 -2
  15. cli/cloud/organisations.py +101 -2
  16. cli/cloud/projects.py +5 -6
  17. cli/cloud/recordings.py +9 -16
  18. cli/cloud/recordings_playback.py +6 -8
  19. cli/cloud/sample_recordings.py +2 -3
  20. cli/cloud/service_account_tokens.py +21 -5
  21. cli/cloud/service_accounts.py +32 -4
  22. cli/cloud/storage/cmd.py +1 -1
  23. cli/cloud/storage/copy.py +3 -4
  24. cli/connect/connect.py +1 -1
  25. cli/connect/protopie/protopie.py +12 -14
  26. cli/errors.py +6 -1
  27. cli/remotive.py +30 -6
  28. cli/settings/__init__.py +1 -2
  29. cli/settings/config_file.py +92 -0
  30. cli/settings/core.py +188 -45
  31. cli/settings/migrate_all_token_files.py +74 -0
  32. cli/settings/migrate_token_file.py +52 -0
  33. cli/settings/token_file.py +69 -4
  34. cli/tools/can/can.py +2 -2
  35. cli/typer/typer_utils.py +18 -1
  36. cli/utils/__init__.py +0 -0
  37. cli/{cloud → utils}/rest_helper.py +114 -39
  38. {remotivelabs_cli-0.0.42.dist-info → remotivelabs_cli-0.1.0a2.dist-info}/METADATA +6 -4
  39. remotivelabs_cli-0.1.0a2.dist-info/RECORD +59 -0
  40. {remotivelabs_cli-0.0.42.dist-info → remotivelabs_cli-0.1.0a2.dist-info}/WHEEL +1 -1
  41. cli/settings/cmd.py +0 -72
  42. remotivelabs_cli-0.0.42.dist-info/RECORD +0 -54
  43. {remotivelabs_cli-0.0.42.dist-info → remotivelabs_cli-0.1.0a2.dist-info}/LICENSE +0 -0
  44. {remotivelabs_cli-0.0.42.dist-info → remotivelabs_cli-0.1.0a2.dist-info}/entry_points.txt +0 -0
@@ -3,20 +3,85 @@ from __future__ import annotations
3
3
  import dataclasses
4
4
  import json
5
5
  from dataclasses import dataclass
6
+ from datetime import date, datetime
7
+ from typing import Any, Literal
8
+
9
+ DEFAULT_EMAIL = "unknown@remotivecloud.com"
10
+
11
+ TokenType = Literal["authorized_user", "service_account"]
12
+
13
+
14
+ def _parse_date(date_str: str) -> date:
15
+ normalized = date_str.replace("Z", "+00:00")
16
+ return datetime.fromisoformat(normalized).date()
17
+
18
+
19
+ def _parse_token_type(token: str) -> TokenType:
20
+ if token.startswith("pa"):
21
+ return "authorized_user"
22
+ if token.startswith("sa"):
23
+ return "service_account"
24
+ raise ValueError(f"Unknown token type for token: {token}")
25
+
26
+
27
+ def _from_dict(d: dict[str, Any]) -> TokenFile:
28
+ if "version" not in d:
29
+ token_type = _parse_token_type(d["token"])
30
+ return TokenFile(
31
+ version="1.0",
32
+ type=token_type,
33
+ name=d["name"],
34
+ token=d["token"],
35
+ created=_parse_date(d["created"]),
36
+ expires=_parse_date(d["expires"]),
37
+ account=TokenFileAccount(email=DEFAULT_EMAIL),
38
+ )
39
+
40
+ account_email = d.get("account", {}).get("email", DEFAULT_EMAIL)
41
+ return TokenFile(
42
+ version=d["version"],
43
+ type=d["type"],
44
+ name=d["name"],
45
+ token=d["token"],
46
+ created=_parse_date(d["created"]),
47
+ expires=_parse_date(d["expires"]),
48
+ account=TokenFileAccount(email=account_email),
49
+ )
6
50
 
7
51
 
8
52
  def loads(data: str) -> TokenFile:
9
- d = json.loads(data)
10
- return TokenFile(name=d["name"], token=d["token"], created=d["created"], expires=d["expires"])
53
+ return _from_dict(json.loads(data))
11
54
 
12
55
 
13
56
  def dumps(token: TokenFile) -> str:
14
57
  return json.dumps(dataclasses.asdict(token), default=str)
15
58
 
16
59
 
60
+ @dataclass
61
+ class TokenFileAccount:
62
+ email: str
63
+
64
+
17
65
  @dataclass
18
66
  class TokenFile:
67
+ version: str
68
+ type: TokenType
19
69
  name: str
20
70
  token: str
21
- created: str
22
- expires: str
71
+ created: date
72
+ expires: date
73
+ account: TokenFileAccount
74
+
75
+ def is_expired(self) -> bool:
76
+ return datetime.today().date() > self.expires
77
+
78
+ def expires_in_days(self) -> int:
79
+ return (self.expires - datetime.today().date()).days
80
+
81
+ @staticmethod
82
+ def from_json_str(data: str) -> TokenFile:
83
+ return loads(data)
84
+
85
+ @staticmethod
86
+ def from_dict(data: dict[str, Any]) -> TokenFile:
87
+ return _from_dict(data)
cli/tools/can/can.py CHANGED
@@ -48,7 +48,7 @@ def convert(
48
48
  with can.Logger(out_file) as writer:
49
49
  for msg in reader:
50
50
  writer.on_message_received(msg)
51
- except Exception as e: # pylint: disable=W0718
51
+ except Exception as e:
52
52
  err_console.print(f":boom: [bold red]Failed to convert file[/bold red]: {e}")
53
53
 
54
54
 
@@ -77,5 +77,5 @@ def validate(
77
77
  if print_to_terminal:
78
78
  writer.on_message_received(msg)
79
79
  console.print(f"Successfully verified {in_file}")
80
- except Exception as e: # pylint: disable=W0718
80
+ except Exception as e:
81
81
  err_console.print(f":boom: [bold red]Failed to convert file[/bold red]: {e}")
cli/typer/typer_utils.py CHANGED
@@ -1,8 +1,25 @@
1
1
  from typing import Any
2
2
 
3
3
  import typer
4
+ from click import Context
5
+ from rich.console import Console
6
+ from typer.core import TyperGroup
7
+
8
+
9
+ class OrderCommands(TyperGroup):
10
+ def list_commands(self, _ctx: Context): # type: ignore
11
+ return list(self.commands)
12
+
13
+
14
+ console = Console()
4
15
 
5
16
 
6
17
  def create_typer(**kwargs: Any) -> typer.Typer:
7
18
  """Create a Typer instance with default settings."""
8
- return typer.Typer(no_args_is_help=True, **kwargs)
19
+ # return typer.Typer(no_args_is_help=True, **kwargs)
20
+ return typer.Typer(cls=OrderCommands, no_args_is_help=True, **kwargs)
21
+
22
+
23
+ def print_padded(label: str, right_text: str, length: int = 30) -> None:
24
+ padded_label = label.ljust(length) # pad to 30 characters
25
+ console.print(f"{padded_label} {right_text}")
cli/utils/__init__.py ADDED
File without changes
@@ -8,7 +8,7 @@ import shutil
8
8
  import sys
9
9
  from importlib.metadata import version
10
10
  from pathlib import Path
11
- from typing import Any, BinaryIO, Dict, List, Union, cast
11
+ from typing import Any, BinaryIO, Dict, List, Optional, Union, cast
12
12
 
13
13
  import requests
14
14
  from requests.exceptions import JSONDecodeError
@@ -32,10 +32,15 @@ class RestHelper:
32
32
  """Static Class with various helper functions for the rest API"""
33
33
 
34
34
  __base_url = "https://cloud.remotivelabs.com"
35
+ __frontend_url = __base_url
35
36
  __license_server_base_url = "https://license.cloud.remotivelabs.com"
36
37
 
37
38
  if "REMOTIVE_CLOUD_BASE_URL" in os.environ:
38
39
  __base_url = os.environ["REMOTIVE_CLOUD_BASE_URL"]
40
+ __frontend_url = os.environ["REMOTIVE_CLOUD_BASE_URL"]
41
+
42
+ if "REMOTIVE_CLOUD_FRONTEND_BASE_URL" in os.environ:
43
+ __frontend_url = os.environ["REMOTIVE_CLOUD_FRONTEND_BASE_URL"]
39
44
 
40
45
  if "cloud-dev" in __base_url:
41
46
  __license_server_base_url = "https://license.cloud-dev.remotivelabs.com"
@@ -47,11 +52,14 @@ class RestHelper:
47
52
  # token = os.environ["REMOTIVE_CLOUD_AUTH_TOKEN"]
48
53
  # headers = {"Authorization": "Bearer " + token}
49
54
 
50
- __headers: Dict[str, str] = {}
55
+ __headers: Dict[str, str] = {"User-Agent": f"remotivelabs-cli {version('remotivelabs-cli')}"}
51
56
  __org: str = ""
52
57
 
53
58
  __token: str = ""
54
59
 
60
+ def _cli_version(self) -> str:
61
+ return ""
62
+
55
63
  @staticmethod
56
64
  def get_cli_version() -> str:
57
65
  return version("remotivelabs-cli")
@@ -60,6 +68,10 @@ class RestHelper:
60
68
  def get_base_url() -> str:
61
69
  return RestHelper.__base_url
62
70
 
71
+ @staticmethod
72
+ def get_base_frontend_url() -> str:
73
+ return RestHelper.__frontend_url
74
+
63
75
  @staticmethod
64
76
  def get_license_server_base_url() -> str:
65
77
  return RestHelper.__license_server_base_url
@@ -77,41 +89,63 @@ class RestHelper:
77
89
  return RestHelper.__token
78
90
 
79
91
  @staticmethod
80
- def ensure_auth_token() -> None:
81
- # if 'REMOTIVE_CLOUD_ORGANISATION' not in os.environ:
82
- # print('You must first set the organisation id to use: export REMOTIVE_CLOUD_ORGANISATION=organisationUid')
83
- # raise typer.Exit()
84
- # org = os.environ["REMOTIVE_CLOUD_ORGANISATION"]
85
- # os.environ['REMOTIVE_CLOUD_AUTH_TOKEN'] = token
86
- try:
87
- token = settings.get_active_token()
88
- except TokenNotFoundError:
89
- ErrorPrinter.print_hint("you are not logged in, please login using [green]remotive cloud auth login[/green]")
90
- sys.exit(1)
92
+ def ensure_auth_token(quiet: bool = False, access_token: Optional[str] = None) -> None:
93
+ if "REMOTIVE_CLOUD_ORGANIZATION" not in os.environ:
94
+ org = settings.get_cli_config().get_active_default_organisation()
95
+ if org is not None:
96
+ os.environ["REMOTIVE_CLOUD_ORGANIZATION"] = org
97
+
98
+ token = None
99
+
100
+ if access_token is None:
101
+ if "REMOTIVE_CLOUD_ACCESS_TOKEN" in os.environ:
102
+ token = os.environ["REMOTIVE_CLOUD_ACCESS_TOKEN"]
103
+ else:
104
+ try:
105
+ token = settings.get_active_token()
106
+ except TokenNotFoundError:
107
+ if quiet:
108
+ return
109
+ ErrorPrinter.print_hint("you are not logged in, please login using [green]remotive cloud auth login[/green]")
110
+ sys.exit(1)
91
111
 
92
- RestHelper.__headers["Authorization"] = "Bearer " + token.strip()
93
- RestHelper.__headers["User-Agent"] = f"remotivelabs-cli {RestHelper.get_cli_version()}"
112
+ RestHelper.__headers["Authorization"] = f"Bearer {token.strip() if token is not None else access_token}"
94
113
 
95
114
  @staticmethod
96
- def handle_get(
115
+ def handle_get( # noqa: PLR0913
97
116
  url: str,
98
117
  params: Any = None,
99
118
  return_response: bool = False,
100
119
  allow_status_codes: List[int] | None = None,
101
120
  progress_label: str = "Fetching...",
102
121
  use_progress_indicator: bool = True,
122
+ allow_redirects: bool = False,
103
123
  timeout: int = 60,
124
+ access_token: Optional[str] = None,
125
+ skip_access_token: bool = False,
104
126
  ) -> requests.Response:
105
- # pylint: disable=R0913
106
127
  # Returns a Response object if succesfull otherwise None
107
128
  if params is None:
108
129
  params = {}
109
- RestHelper.ensure_auth_token()
130
+ if not skip_access_token:
131
+ RestHelper.ensure_auth_token(access_token=access_token)
110
132
  if use_progress_indicator:
111
133
  with RestHelper.use_progress(progress_label):
112
- r = requests.get(f"{RestHelper.__base_url}{url}", headers=RestHelper.__headers, params=params, timeout=timeout)
134
+ r = requests.get(
135
+ f"{RestHelper.__base_url}{url}",
136
+ headers=RestHelper.__headers,
137
+ params=params,
138
+ timeout=timeout,
139
+ allow_redirects=allow_redirects,
140
+ )
113
141
  else:
114
- r = requests.get(f"{RestHelper.__base_url}{url}", headers=RestHelper.__headers, params=params, timeout=timeout)
142
+ r = requests.get(
143
+ f"{RestHelper.__base_url}{url}",
144
+ headers=RestHelper.__headers,
145
+ params=params,
146
+ timeout=timeout,
147
+ allow_redirects=allow_redirects,
148
+ )
115
149
 
116
150
  if return_response:
117
151
  RestHelper.check_api_result(r, allow_status_codes)
@@ -120,27 +154,34 @@ class RestHelper:
120
154
  sys.exit(0)
121
155
 
122
156
  @staticmethod
123
- def has_access(url: str, params: Any = {}) -> bool: # pylint: disable=W0102
124
- RestHelper.ensure_auth_token()
157
+ def has_access(url: str, params: Any = {}, access_token: Optional[str] = None) -> bool:
158
+ RestHelper.ensure_auth_token(quiet=True, access_token=access_token)
125
159
  r = requests.get(f"{RestHelper.__base_url}{url}", headers=RestHelper.__headers, params=params, timeout=60)
126
- if r.status_code == 401:
127
- return False
128
- return True
160
+ if 200 <= r.status_code <= 299:
161
+ return True
162
+ return False
129
163
 
130
164
  @staticmethod
131
165
  def check_api_result(response: requests.Response, allow_status_codes: List[int] | None = None) -> None:
166
+ if response.status_code == 426: # CLI upgrade
167
+ ErrorPrinter.print_hint(response.text)
168
+ sys.exit(1)
132
169
  if response.status_code > 299:
133
170
  if allow_status_codes is not None and response.status_code in allow_status_codes:
134
171
  return
135
172
  err_console.print(f":boom: [bold red]Got status code[/bold red]: {response.status_code}")
136
173
  if response.status_code == 401:
137
- err_console.print("Your token has expired, please login again")
174
+ err_console.print("Your token is not valid or has expired, please login again or activate another account")
138
175
  else:
139
176
  err_console.print(response.text)
140
177
  sys.exit(1)
141
178
 
142
179
  @staticmethod
143
180
  def print_api_result(response: requests.Response) -> None:
181
+ if response.status_code == 426: # CLI upgrade
182
+ ErrorPrinter.print_hint(response.text)
183
+ sys.exit(1)
184
+
144
185
  if response.status_code >= 200 and response.status_code < 300:
145
186
  if len(response.content) >= 2:
146
187
  try:
@@ -151,31 +192,65 @@ class RestHelper:
151
192
  else:
152
193
  err_console.print(f":boom: [bold red]Got status code[/bold red]: {response.status_code}")
153
194
  if response.status_code == 401:
154
- err_console.print("Your token has expired, please login again")
195
+ err_console.print("Your token is not valid or has expired, please login again or activate another account")
155
196
  else:
156
197
  err_console.print(response.text)
157
198
  sys.exit(1)
158
- # typer.Exit(1) did not work as expected
159
199
 
160
200
  @staticmethod
161
- def handle_delete( # pylint: disable=W0102
162
- url: str, params: Any = {}, quiet: bool = False, progress_label: str = "Deleting..."
163
- ) -> None:
164
- RestHelper.ensure_auth_token()
201
+ def handle_patch( # noqa: PLR0913
202
+ url: str,
203
+ params: Any = {},
204
+ quiet: bool = False,
205
+ progress_label: str = "Deleting...",
206
+ access_token: Optional[str] = None,
207
+ allow_status_codes: Optional[List[int]] = None,
208
+ ) -> requests.Response:
209
+ if allow_status_codes is None:
210
+ allow_status_codes = []
211
+ RestHelper.ensure_auth_token(access_token=access_token)
212
+ with RestHelper.use_progress(progress_label):
213
+ r = requests.patch(f"{RestHelper.__base_url}{url}", headers=RestHelper.__headers, params=params, timeout=60)
214
+ if r.status_code in (200, 204):
215
+ if not quiet:
216
+ RestHelper.print_api_result(r)
217
+ elif r.status_code not in allow_status_codes:
218
+ RestHelper.print_api_result(r)
219
+ return r
220
+
221
+ @staticmethod
222
+ def handle_delete( # noqa: PLR0913
223
+ url: str,
224
+ params: Any = {},
225
+ quiet: bool = False,
226
+ progress_label: str = "Deleting...",
227
+ access_token: Optional[str] = None,
228
+ allow_status_codes: Optional[List[int]] = None,
229
+ ) -> requests.Response:
230
+ if allow_status_codes is None:
231
+ allow_status_codes = []
232
+ RestHelper.ensure_auth_token(access_token=access_token)
165
233
  with RestHelper.use_progress(progress_label):
166
234
  r = requests.delete(f"{RestHelper.__base_url}{url}", headers=RestHelper.__headers, params=params, timeout=60)
167
235
  if r.status_code in (200, 204):
168
236
  if not quiet:
169
237
  RestHelper.print_api_result(r)
170
- else:
238
+ elif r.status_code not in allow_status_codes:
171
239
  RestHelper.print_api_result(r)
240
+ return r
172
241
 
173
242
  @staticmethod
174
- def handle_post( # pylint: disable=W0102
175
- url: str, body: Any = None, params: Any = {}, progress_label: str = "Processing...", return_response: bool = False
243
+ def handle_post( # noqa: PLR0913
244
+ url: str,
245
+ body: Any = None,
246
+ params: Any = {},
247
+ progress_label: str = "Processing...",
248
+ return_response: bool = False,
249
+ access_token: Optional[str] = None,
176
250
  ) -> requests.Response:
177
251
  # Returns a Response object if succesfull otherwise, None
178
- RestHelper.ensure_auth_token()
252
+
253
+ RestHelper.ensure_auth_token(access_token=access_token)
179
254
  RestHelper.__headers["content-type"] = "application/json"
180
255
 
181
256
  with RestHelper.use_progress(progress_label):
@@ -189,7 +264,7 @@ class RestHelper:
189
264
  sys.exit(0)
190
265
 
191
266
  @staticmethod
192
- def handle_put(url: str, body: Any = None, params: Any = {}, return_response: bool = False) -> requests.Response | None: # pylint: disable=W0102
267
+ def handle_put(url: str, body: Any = None, params: Any = {}, return_response: bool = False) -> requests.Response | None:
193
268
  # Returns a Response object if succesfull otherwise, None
194
269
  RestHelper.ensure_auth_token()
195
270
  RestHelper.__headers["content-type"] = "application/json"
@@ -243,8 +318,8 @@ class RestHelper:
243
318
  return None
244
319
 
245
320
  @staticmethod
246
- def use_progress(label: str) -> Progress:
247
- p = Progress(SpinnerColumn(), TextColumn("[progress.description]{task.description}"), transient=True)
321
+ def use_progress(label: str, transient: bool = True) -> Progress:
322
+ p = Progress(SpinnerColumn(), TextColumn("[progress.description]{task.description}"), transient=transient)
248
323
  p.add_task(label, total=1)
249
324
  return p
250
325
 
@@ -1,16 +1,18 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: remotivelabs-cli
3
- Version: 0.0.42
3
+ Version: 0.1.0a2
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.8,<4
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)
@@ -0,0 +1,59 @@
1
+ cli/.DS_Store,sha256=7HTaExsH9zU3sluA0MFtZuyzNmSnUmH2Sh09uoek84E,8196
2
+ cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ cli/api/cloud/tokens.py,sha256=3UKfVM3NvZX_ynpPAXZ_cnrPAIIgg0vA1FuOzj8TV2o,1631
4
+ cli/broker/brokers.py,sha256=lfO0oAuOwLiJkuNIusXCnOGrxEKGvQjy75LMY9jP5-Y,3234
5
+ cli/broker/export.py,sha256=rr6OGZmkbqVUljy-gluC2CeRDKbI_p41EhleT3lcgXQ,4481
6
+ cli/broker/files.py,sha256=JMpyBYfqVX_ppIChDcUuWvCDIQHC8YI6IsljyIL0NZ8,4212
7
+ cli/broker/lib/__about__.py,sha256=xnZ5V6ZcHW9dhWLWdMzVjYJbEnMKpeXm0_S_mbNzypE,141
8
+ cli/broker/lib/broker.py,sha256=Qu6OuKt0P4aFPRSbmcdXUly9iQrnDgUcHTjVJzahTCQ,25006
9
+ cli/broker/license_flows.py,sha256=du5SSAdzr2VZeORWoAgbYrfi-mpnDUQfIVpfAJK6CSM,7216
10
+ cli/broker/licenses.py,sha256=jIuLB2qBGflzSjm952CBnErpzs7iIkmEgx9L8GDAPNc,4021
11
+ cli/broker/playback.py,sha256=fO-ZvzmB3ZzanmD1L09PeKkabx35uKsELMM-h-5brSE,4023
12
+ cli/broker/record.py,sha256=rVjvyWRSWNFtthZZkZeZZGvZdmhDB_qmYcrCocCJxY4,1445
13
+ cli/broker/scripting.py,sha256=LFLdaBNxe2sfpcxhDmRlAbEorjL3SJZNK-zEdLQ9ySU,3854
14
+ cli/broker/signals.py,sha256=MFj_bOLIxHY1v3XPkKk6n8U3JLaY8nrXHahRQaVse6s,8207
15
+ cli/cloud/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ cli/cloud/auth/__init__.py,sha256=MtQ01-n8CgZb9Y_SvxwZUgj44Yo0dFAU3_XwhQiUYtw,54
17
+ cli/cloud/auth/cmd.py,sha256=aOvbrzNb7moClgmde25T0coBs8Ge696xUB_w6qfvN8I,2920
18
+ cli/cloud/auth/login.py,sha256=PnmD2dMOP55_DOE6yM1lKBVhxyaZfO2DMQATaRuJrB4,11438
19
+ cli/cloud/auth_tokens.py,sha256=XHXrCwgK_akrCbFxcxtDr7GDM9cd-T_s40PrRovY4Lk,12344
20
+ cli/cloud/brokers.py,sha256=QTA9bmaK06LKEccF6IBgWBonC4VFrKwFQBsACX_IzYw,3896
21
+ cli/cloud/cloud_cli.py,sha256=q-oiaLcKC-BRamXfIFGn-BskRmJ3utA7-tI39lSs3Cs,1309
22
+ cli/cloud/configs.py,sha256=uv46nUoGXOr99smQHahv_ageDv6bGYfUnlRlxcS5D9A,5125
23
+ cli/cloud/organisations.py,sha256=QBD2RnCbpZ9XQrTIcvD74o321JHNnKxDleKlYmSZEuI,4116
24
+ cli/cloud/projects.py,sha256=ecn5Y8UKhgYnHSJQACUk1GNZt9EF8ug4B-6MCr8rZqM,1487
25
+ cli/cloud/recordings.py,sha256=B0XOj8LIm3hBqBzVKPLPvPUCXCKZBTEISssrijK481w,24855
26
+ cli/cloud/recordings_playback.py,sha256=XZoVyujufMQFN2v_Nwsf8tOqn61yLEpAf2z_u5uhXik,11532
27
+ cli/cloud/resumable_upload.py,sha256=8lEIdncJZoTZzNsQVHH3gm_GunxEmN5JbmWX7awy3p4,3713
28
+ cli/cloud/sample_recordings.py,sha256=RmuT-a2iMwGj3LXVcPkV5l66uFcf7nyWyJciUjnYkk4,721
29
+ cli/cloud/service_account_tokens.py,sha256=lZHrja2hIyeXGTNGsxaZ_NlS_iXcyWR_h62H4OYeTMk,2783
30
+ cli/cloud/service_accounts.py,sha256=AiktZW5QTbT6sAPJi4ubETOqbBDAIt4LOE-TZmIiIkk,2586
31
+ cli/cloud/storage/__init__.py,sha256=ijl9WwU5D4oASbwrFKJurYsBUyzwZCOhcdTQYj-ZSeM,159
32
+ cli/cloud/storage/cmd.py,sha256=UOPpzZeqtqAD2qAbFRGHnbpliq6T_8phKQSxU0EeaqI,2970
33
+ cli/cloud/storage/copy.py,sha256=tPvRcKFhzxbBhjvQ6ZGMe81hksfYwbn7dEgrjpYaC0Q,3237
34
+ cli/cloud/storage/uri_or_path.py,sha256=DLlyr0RAV-DRlL2C36U-jvUqwiLIlkw7c3mJ7SSGMdI,1158
35
+ cli/cloud/uri.py,sha256=QZCus--KJQlVwGCOzZqiglvj8VvSRKxfVvN33Pilgyg,3616
36
+ cli/connect/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
+ cli/connect/connect.py,sha256=SH2DNTTVLu2dNpk6xIah1-KJZAqrK_7Skt8RKp8Mjh8,4231
38
+ cli/connect/protopie/protopie.py,sha256=ElmrGaV0ivb85wo0gLzCAXZhmSmIDASaCVlF1iQblLI,6532
39
+ cli/errors.py,sha256=_P-qpayY06qgLA7wvoDFsyMaTfo_zjNY--fgHPAuhrs,1658
40
+ cli/remotive.py,sha256=PsxR3Hhp3zhj-A06sqvtSkmXwv9moWHT_ify8Vg5xQA,2756
41
+ cli/settings/__init__.py,sha256=5ZRq04PHp3WU_5e7mGwWUoFYUPWfnnS16yF45wUv7mY,248
42
+ cli/settings/config_file.py,sha256=6WHlJT74aQvqc5elcW1FDafcG0NttYvPawmArN5H2MQ,2869
43
+ cli/settings/core.py,sha256=vRS_3JZDKRMGMa65C3LT178BCUcZ2RAlp2knn158CA4,15669
44
+ cli/settings/migrate_all_token_files.py,sha256=7kvHbpP4BtILJ8kPtb_bFnTnBYX9isZ4rwB5lfnEkbA,2722
45
+ cli/settings/migrate_token_file.py,sha256=Fp7Z_lNqSdoWY05TYwFW2QH8q9QhmB2TYSok6hV1Mic,1530
46
+ cli/settings/token_file.py,sha256=KISVaSVV2pzfduCtJYUtCLtJa3htrpP4_qTODp5IhW8,2210
47
+ cli/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
+ cli/tools/can/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
+ cli/tools/can/can.py,sha256=TtP5w8vb0QG4ObNhkWIDpRMdNelirFffoc_lFZy8ePM,2260
50
+ cli/tools/tools.py,sha256=jhLfrFDqkmWV3eBAzNwBf6WgDGrz7sOhgVCia36Twn8,232
51
+ cli/typer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
+ cli/typer/typer_utils.py,sha256=8SkvG9aKkfK9fTRsLD9pOBtWn9XSwtOXWg2RAk9FhOI,708
53
+ cli/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
+ cli/utils/rest_helper.py,sha256=b_FJY6MxnFSqo11qaHxkBFHfVlKf7Zj28Uxv9Oj7XY4,14141
55
+ remotivelabs_cli-0.1.0a2.dist-info/LICENSE,sha256=qDPP_yfuv1fF-u7EfexN-cN3M8aFgGVndGhGLovLKz0,608
56
+ remotivelabs_cli-0.1.0a2.dist-info/METADATA,sha256=ikZ-W_JIYwAuG5JTEKQRo8O00WqQn6GvAAJmWvCk3KI,1430
57
+ remotivelabs_cli-0.1.0a2.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
58
+ remotivelabs_cli-0.1.0a2.dist-info/entry_points.txt,sha256=lvDhPgagLqW_KTnLPCwKSqfYlEp-1uYVosRiPjsVj10,45
59
+ remotivelabs_cli-0.1.0a2.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.0
2
+ Generator: poetry-core 2.1.3
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
cli/settings/cmd.py DELETED
@@ -1,72 +0,0 @@
1
- import typer
2
-
3
- from cli.errors import ErrorPrinter
4
- from cli.settings.core import TokenNotFoundError, settings
5
- from cli.typer import typer_utils
6
-
7
- app = typer_utils.create_typer()
8
-
9
-
10
- @app.command()
11
- def describe(file: str = typer.Argument(help="Token name or file path")) -> None:
12
- """
13
- Show contents of specified access token file
14
- """
15
- try:
16
- print(settings.get_token_file(file))
17
- except TokenNotFoundError:
18
- ErrorPrinter.print_generic_error(f"Token file {file} not found")
19
-
20
-
21
- @app.command()
22
- def activate(file: str = typer.Argument(..., help="Token name or file path")) -> None:
23
- """
24
- Activate a access token file to be used for authentication.
25
-
26
- This will be used as the current access token in all subsequent requests. This would
27
- be the same as login with a browser.
28
- """
29
- try:
30
- settings.activate_token(file)
31
- except FileNotFoundError as e:
32
- print(f"File could not be found: {e}")
33
-
34
-
35
- @app.command(name="list-personal-tokens")
36
- def list_pats() -> None:
37
- """
38
- List personal access token files in remotivelabs config directory
39
- """
40
- pats = settings.list_personal_tokens()
41
- for pat in pats:
42
- print(pat.name)
43
-
44
-
45
- @app.command(name="list-personal-tokens-files")
46
- def list_pats_files() -> None:
47
- """
48
- List personal access token files in remotivelabs config directory
49
- """
50
- personal_files = settings.list_personal_token_files()
51
- for file in personal_files:
52
- print(file)
53
-
54
-
55
- @app.command(name="list-service-account-tokens")
56
- def list_sats() -> None:
57
- """
58
- List service account access token files in remotivelabs config directory
59
- """
60
- sats = settings.list_service_account_tokens()
61
- for sat in sats:
62
- print(sat.name)
63
-
64
-
65
- @app.command(name="list-service-account-tokens-files")
66
- def list_sats_files() -> None:
67
- """
68
- List service account access token files in remotivelabs config directory
69
- """
70
- service_account_files = settings.list_service_account_token_files()
71
- for file in service_account_files:
72
- print(file)
@@ -1,54 +0,0 @@
1
- cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- cli/broker/brokers.py,sha256=xpwC6S5wCVn_9MOXa12Z-CbRvacjXETU0bqxOlFGKjo,3245
3
- cli/broker/export.py,sha256=rXWPP8JZgWt48l_sVZu5oJ7lEKT6Q1NnR5b493GZ50Q,4476
4
- cli/broker/files.py,sha256=JMpyBYfqVX_ppIChDcUuWvCDIQHC8YI6IsljyIL0NZ8,4212
5
- cli/broker/lib/__about__.py,sha256=xnZ5V6ZcHW9dhWLWdMzVjYJbEnMKpeXm0_S_mbNzypE,141
6
- cli/broker/lib/broker.py,sha256=HbGo83j6ipaol0uJ93Me78pOPjy7p8PUjYT9xZmRT-w,25086
7
- cli/broker/license_flows.py,sha256=qJplaeugkUiypFGPdEIl5Asqlf7W3geJ-wU-QbYMP_8,7216
8
- cli/broker/licenses.py,sha256=jIuLB2qBGflzSjm952CBnErpzs7iIkmEgx9L8GDAPNc,4021
9
- cli/broker/playback.py,sha256=fO-ZvzmB3ZzanmD1L09PeKkabx35uKsELMM-h-5brSE,4023
10
- cli/broker/record.py,sha256=rVjvyWRSWNFtthZZkZeZZGvZdmhDB_qmYcrCocCJxY4,1445
11
- cli/broker/scripting.py,sha256=RExHSruSyL8MjEhZHj9SVKi3z5OuSWwiz44hc9X3hiY,3839
12
- cli/broker/signals.py,sha256=1f3pwMBbhxg_x4ktGR9eivNDPJY678CpTBrjXbQaItg,8193
13
- cli/cloud/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
- cli/cloud/auth/__init__.py,sha256=MtQ01-n8CgZb9Y_SvxwZUgj44Yo0dFAU3_XwhQiUYtw,54
15
- cli/cloud/auth/cmd.py,sha256=rdM1Am0E5AcErn0s35x0KL5ys_dGSGaIE7nw0SNtF-0,1655
16
- cli/cloud/auth/login.py,sha256=Yrir9ThKJ7sqL4AsEivXxMKjP7QevEGxcm3f2BPUqFg,1898
17
- cli/cloud/auth_tokens.py,sha256=xTdL_wHVnOq1hW45XU9iDvQWW7ISDuf5RrDgVilg4-U,1263
18
- cli/cloud/brokers.py,sha256=TzUfd2PBfF3vDyTjZ4fMv8ndA4_37IUgOuZHgGHGSEE,3938
19
- cli/cloud/cloud_cli.py,sha256=a-LhunHPRPZkxaXQJ0evOYCVXZRYY_qzM6GJG75SjkY,1309
20
- cli/cloud/configs.py,sha256=y7uu9IRJjspSpxREvwRNNfx0N1ypstElaqtpt9tepgY,5117
21
- cli/cloud/organisations.py,sha256=FJvNjsQFTSqvHs8xWkyVaep1rlYmf1X8Im26Zbxb9iE,432
22
- cli/cloud/projects.py,sha256=gXvlaGER3zxBwvjdO3lOa6Fl1xHfQHVCaPdpUNi7G3k,1479
23
- cli/cloud/recordings.py,sha256=QrgXJC4csC73Gau-dV_YgL0EZaUzFbc9Nkz_qZHrp70,25067
24
- cli/cloud/recordings_playback.py,sha256=dRciL4Oiki6laxRiN8CLiJbsjdjcNpUbv8wxaP91_PA,11614
25
- cli/cloud/rest_helper.py,sha256=mm7kMPDVapJPL1X-xsn7wpY3wuOuawgzJgij5iKEaiE,11448
26
- cli/cloud/resumable_upload.py,sha256=8lEIdncJZoTZzNsQVHH3gm_GunxEmN5JbmWX7awy3p4,3713
27
- cli/cloud/sample_recordings.py,sha256=zHfzpo-YxuBaor95PeVJrbBYyPBXS5zOBf2j0lYnT9Q,738
28
- cli/cloud/service_account_tokens.py,sha256=7rwR8UoqG3Y1aPqf0lDcwpYd9X3sM7J9qTmL30iUBsY,1814
29
- cli/cloud/service_accounts.py,sha256=BmliX2w3LBoZoZ8fCR0fP3ph945YPIZBAb8Y13oWZuw,1707
30
- cli/cloud/storage/__init__.py,sha256=ijl9WwU5D4oASbwrFKJurYsBUyzwZCOhcdTQYj-ZSeM,159
31
- cli/cloud/storage/cmd.py,sha256=3j_SbM0Pvh7QklJPfF8DMhj-VpohAf6mcgO0TaaSuHc,2970
32
- cli/cloud/storage/copy.py,sha256=4FDBNZVcHKxDI9vU8qawOBcWNYobZu8RdtPUHZsY7iA,3253
33
- cli/cloud/storage/uri_or_path.py,sha256=DLlyr0RAV-DRlL2C36U-jvUqwiLIlkw7c3mJ7SSGMdI,1158
34
- cli/cloud/uri.py,sha256=QZCus--KJQlVwGCOzZqiglvj8VvSRKxfVvN33Pilgyg,3616
35
- cli/connect/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
- cli/connect/connect.py,sha256=ygpsd3ZMXQe7wZeJ_E1TBkRDgTxr9r5V7XeoUO_-68w,4239
37
- cli/connect/protopie/protopie.py,sha256=GRFN4P5zxWcgwuIwRKUeJ3ie0HqtHUxN7f6dsWPCfBc,6524
38
- cli/errors.py,sha256=8_BcTPX3mrPFDQJKKBg6ERjs6HSOiewrY86K1Jays74,1495
39
- cli/remotive.py,sha256=B9wCk1jeAd21VgWDW4ntziuwhFk1J5I4wr903l1AZ58,1951
40
- cli/settings/__init__.py,sha256=4Mj9DFvRBN0LKn6PPLrb-BmuObP707IYeRmg7t7aycg,288
41
- cli/settings/cmd.py,sha256=1riCR5oCjAtNEnyE9wnit1NPa-BJJtuFMUDMMtX-b7E,2039
42
- cli/settings/core.py,sha256=o9SDCiqYfihHbiepFebpEB5vEMW656vngyjCkXJaaeQ,9209
43
- cli/settings/token_file.py,sha256=UUSbnm6zrPS2HJmbyLzfoKWjmHVOh3IjiwDvLPCoyXc,455
44
- cli/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
- cli/tools/can/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
46
- cli/tools/can/can.py,sha256=42BwsIOx9NUPkp_rB-0MDqL1tCpeqYVOgWzpixm5ykk,2310
47
- cli/tools/tools.py,sha256=jhLfrFDqkmWV3eBAzNwBf6WgDGrz7sOhgVCia36Twn8,232
48
- cli/typer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
- cli/typer/typer_utils.py,sha256=DmGxdIo0_iK_DYJrZvpFT-tEaQZT1cJtrFR-5VmF_jo,199
50
- remotivelabs_cli-0.0.42.dist-info/LICENSE,sha256=qDPP_yfuv1fF-u7EfexN-cN3M8aFgGVndGhGLovLKz0,608
51
- remotivelabs_cli-0.0.42.dist-info/METADATA,sha256=gIn4oB_y8v29-ytAQXcHvfdUfGP-E04atfh8GHphRRA,1359
52
- remotivelabs_cli-0.0.42.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
53
- remotivelabs_cli-0.0.42.dist-info/entry_points.txt,sha256=lvDhPgagLqW_KTnLPCwKSqfYlEp-1uYVosRiPjsVj10,45
54
- remotivelabs_cli-0.0.42.dist-info/RECORD,,