remotivelabs-cli 0.0.21__tar.gz → 0.0.22__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.
Files changed (41) hide show
  1. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/PKG-INFO +1 -1
  2. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/cloud/recordings.py +84 -27
  3. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/cloud/rest_helper.py +1 -1
  4. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/pyproject.toml +1 -1
  5. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/LICENSE +0 -0
  6. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/README.md +0 -0
  7. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/__about__.py +0 -0
  8. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/__init__.py +0 -0
  9. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/broker/brokers.py +0 -0
  10. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/broker/export.py +0 -0
  11. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/broker/files.py +0 -0
  12. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/broker/lib/__about__.py +0 -0
  13. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/broker/lib/broker.py +0 -0
  14. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/broker/license_flows.py +0 -0
  15. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/broker/licenses.py +0 -0
  16. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/broker/playback.py +0 -0
  17. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/broker/record.py +0 -0
  18. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/broker/scripting.py +0 -0
  19. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/broker/signals.py +0 -0
  20. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/cloud/__init__.py +0 -0
  21. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/cloud/auth.py +0 -0
  22. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/cloud/auth_tokens.py +0 -0
  23. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/cloud/brokers.py +0 -0
  24. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/cloud/cloud_cli.py +0 -0
  25. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/cloud/configs.py +0 -0
  26. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/cloud/projects.py +0 -0
  27. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/cloud/recordings_playback.py +0 -0
  28. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/cloud/sample_recordings.py +0 -0
  29. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/cloud/service_account_tokens.py +0 -0
  30. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/cloud/service_accounts.py +0 -0
  31. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/connect/__init__.py +0 -0
  32. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/connect/connect.py +0 -0
  33. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/connect/protopie/protopie.py +0 -0
  34. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/errors.py +0 -0
  35. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/remotive.py +0 -0
  36. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/requirements.txt +0 -0
  37. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/settings.py +0 -0
  38. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/tools/__init__.py +0 -0
  39. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/tools/can/__init__.py +0 -0
  40. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/tools/can/can.py +0 -0
  41. {remotivelabs_cli-0.0.21 → remotivelabs_cli-0.0.22}/cli/tools/tools.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: remotivelabs-cli
3
- Version: 0.0.21
3
+ Version: 0.0.22
4
4
  Summary: CLI for operating RemotiveCloud and RemotiveBroker
5
5
  Author: Johan Rask
6
6
  Author-email: johan.rask@remotivelabs.com
@@ -6,7 +6,10 @@ import os
6
6
  import re
7
7
  import sys
8
8
  import tempfile
9
+ import time
10
+ import urllib.parse
9
11
  from pathlib import Path
12
+ from typing import Dict, List, Union
10
13
 
11
14
  import grpc
12
15
  import requests
@@ -193,7 +196,7 @@ def delete_recording_file(
193
196
 
194
197
 
195
198
  @app.command()
196
- def upload(
199
+ def upload( # noqa: C901
197
200
  path: Path = typer.Argument(
198
201
  ...,
199
202
  exists=True,
@@ -205,38 +208,86 @@ def upload(
205
208
  help="Path to recording file to upload",
206
209
  ),
207
210
  project: str = typer.Option(..., help="Project ID", envvar="REMOTIVE_CLOUD_PROJECT"),
208
- recording_type: str = typer.Option("remotive-broker", help="Type of recording"),
209
- signal_database: str = typer.Option(None, help="Signal database to use with candump"),
211
+ recording_session: str = typer.Option(default=None, help="Optional existing recording to upload file to"),
210
212
  ):
211
- # TODO - Test to do this with typer Enums instead
212
- # Validate this here to validate before we start any progress
213
- if recording_type == "candump" and (signal_database is None or signal_database == ""):
214
- ErrorPrinter.print_hint("Option --signal-database is required with --recording-type is 'candump'")
215
- exit(1)
213
+ """
214
+ Uploads a recording to RemotiveCloud.
215
+ Except for recordings from RemotiveBroker you can also upload Can ASC (.asc), Can BLF(.blf) and Can LOG (.log, .txt)
216
+ """
216
217
 
217
218
  filename = os.path.basename(path.name)
218
219
  rest.ensure_auth_token()
219
220
 
220
- if recording_type == "candump":
221
- rest.headers["x-recording-type"] = "candump"
222
- r = rest.handle_post(
223
- url=f"/api/project/{project}/files/recording/{filename}",
224
- return_response=True,
225
- progress_label="Requesting recording upload...",
226
- body=json.dumps({"dbcFile": signal_database}),
227
- )
228
- else:
221
+ if recording_session is None:
229
222
  r = rest.handle_post(f"/api/project/{project}/files/recording/{filename}", return_response=True)
223
+ else:
224
+ r = rest.handle_post(f"/api/project/{project}/files/recording/{recording_session}/recording-file/{filename}", return_response=True)
225
+
226
+ upload_url = r.text
227
+ url_path = urllib.parse.urlparse(upload_url).path
228
+ # Upload_id is the first part of the path
229
+ match = re.match(r"^/([^/]+)/organisation/(.*)$", url_path)
230
+ if match:
231
+ upload_id = match.group(1)
232
+ else:
233
+ ErrorPrinter.print_generic_error(
234
+ "Something went wrong, please try again. Please contact RemotiveLabs support if this problem remains"
235
+ )
236
+ ErrorPrinter.print_hint("Please make sure to use the latest version of RemotiveCLI")
237
+ exit(1)
230
238
 
231
- response = rest.upload_file_with_signed_url(path=path, url=r.text, upload_headers={"Content-Type": "application/x-www-form-urlencoded"})
239
+ upload_response = rest.upload_file_with_signed_url(
240
+ path=path, url=upload_url, upload_headers={"Content-Type": "application/x-www-form-urlencoded"}, return_response=True
241
+ )
242
+
243
+ # Exact same as in cloud console
244
+ def get_processing_message(step: str) -> str:
245
+ if step == "REQUESTED":
246
+ return "Preparing file..."
247
+ if step == "VALIDATING":
248
+ return "Validating file..."
249
+ if step == "CONVERT":
250
+ return "Converting file..."
251
+ if step == "SPLIT":
252
+ return "Splitting file..."
253
+ if step == "ZIP":
254
+ return "Compressing file..."
255
+ if step == "FINALIZE":
256
+ return "Finishing up..."
257
+ return "Processing..."
258
+
259
+ # print(response)
260
+ if 200 <= upload_response.status_code < 300:
261
+ # We need to print the error message outside the with Progress so the indicator is closed
262
+ error_message: Union[str, None] = None
263
+ with Progress(SpinnerColumn(), TextColumn("[progress.description]{task.description}"), transient=True) as p:
264
+ t = p.add_task("Processing...", total=1)
265
+ while True:
266
+ time.sleep(1)
267
+ r = rest.handle_get(
268
+ f"/api/project/{project}/files/recording/processing", return_response=True, use_progress_indicator=False
269
+ )
270
+ status_list: List[Dict[str, any]] = r.json()
271
+ res = list(filter(lambda s: s["uploadId"] == upload_id, status_list))
272
+ if len(res) == 1:
273
+ tracking_state = res[0]
274
+ if tracking_state["status"] != "FAILED" and tracking_state["status"] != "SUCCESS":
275
+ p.update(task_id=t, description=get_processing_message(tracking_state["step"]))
276
+ else:
277
+ if tracking_state["status"] == "FAILED":
278
+ error_message = f"Processing of uploaded file failed: {tracking_state['errors'][0]['message']}"
279
+ else:
280
+ print("File successfully uploaded")
281
+ break
282
+ else:
283
+ error_message = "Something went wrong, please try again. Please contact RemotiveLabs support if this problem remains"
284
+ break
285
+ if error_message is not None:
286
+ ErrorPrinter.print_generic_error(error_message)
287
+ exit(1)
232
288
 
233
- if 200 <= response.status_code < 300:
234
- print(
235
- "File successfully uploaded, please run 'remotive cloud recordings list' "
236
- "to verify that the recording was successfully processed"
237
- )
238
289
  else:
239
- rest.err_console.print(f":boom: [bold red]Got status code[/bold red]: {response.status_code} {response.text}")
290
+ rest.err_console.print(f":boom: [bold red]Got status code[/bold red]: {upload_response.status_code} {upload_response.text}")
240
291
 
241
292
 
242
293
  @app.command()
@@ -450,9 +501,9 @@ def _do_change_playback_mode(mode: str, recording_session: str, broker: str, pro
450
501
  # Here we try to verify that we are operating on a recording that is mounted on the
451
502
  # broker so we can verify this before we try playback and can also present some good
452
503
  # error messages
453
- tmp = tempfile.NamedTemporaryFile()
454
- broker.download(".cloud.context", tmp.name, True)
455
- with open(tmp.name, "r") as f:
504
+ tmp = os.path.join(tempfile.gettempdir(), os.urandom(24).hex())
505
+ broker.download(".cloud.context", tmp, True)
506
+ with open(tmp, "r") as f:
456
507
  json_context = json.loads(f.read())
457
508
  if json_context["recordingSessionId"] != recording_session:
458
509
  ErrorPrinter.print_generic_error(
@@ -496,3 +547,9 @@ def get_filename_from_cd(cd):
496
547
  if len(fname) == 0:
497
548
  return None
498
549
  return fname[0]
550
+
551
+
552
+ def use_progress(label: str):
553
+ p = Progress(SpinnerColumn(), TextColumn("[progress.description]{task.description}"), transient=True)
554
+ t = p.add_task(label, total=1)
555
+ return (p, t)
@@ -185,7 +185,7 @@ def upload_file_with_signed_url(
185
185
  path: Union[str, Path], url: str, upload_headers: dict[str, str], return_response: bool = False, progress_label="Uploading..."
186
186
  ):
187
187
  with open(path, "rb") as file:
188
- with wrap_file(file, os.stat(path).st_size, description=progress_label) as f:
188
+ with wrap_file(file, os.stat(path).st_size, description=progress_label, transient=True) as f:
189
189
  r = requests.put(url, data=f, headers=upload_headers)
190
190
  if return_response:
191
191
  check_api_result(r)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "remotivelabs-cli"
3
- version = "0.0.21"
3
+ version = "0.0.22"
4
4
  description = "CLI for operating RemotiveCloud and RemotiveBroker"
5
5
  authors = ["Johan Rask <johan.rask@remotivelabs.com>"]
6
6
  readme = "README.md"