remotivelabs-cli 0.0.25__py3-none-any.whl → 0.0.27__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 (43) hide show
  1. cli/broker/brokers.py +2 -2
  2. cli/broker/export.py +5 -5
  3. cli/broker/files.py +5 -5
  4. cli/broker/lib/broker.py +82 -51
  5. cli/broker/license_flows.py +11 -9
  6. cli/broker/licenses.py +2 -2
  7. cli/broker/playback.py +14 -34
  8. cli/broker/record.py +3 -3
  9. cli/broker/scripting.py +4 -4
  10. cli/broker/signals.py +20 -12
  11. cli/cloud/__init__.py +0 -1
  12. cli/cloud/auth.py +40 -35
  13. cli/cloud/auth_tokens.py +73 -37
  14. cli/cloud/brokers.py +24 -33
  15. cli/cloud/cloud_cli.py +7 -18
  16. cli/cloud/configs.py +28 -11
  17. cli/cloud/filestorage.py +63 -51
  18. cli/cloud/organisations.py +30 -0
  19. cli/cloud/projects.py +11 -8
  20. cli/cloud/recordings.py +148 -117
  21. cli/cloud/recordings_playback.py +52 -39
  22. cli/cloud/rest_helper.py +247 -196
  23. cli/cloud/resumable_upload.py +9 -8
  24. cli/cloud/sample_recordings.py +5 -5
  25. cli/cloud/service_account_tokens.py +18 -16
  26. cli/cloud/service_accounts.py +9 -9
  27. cli/connect/__init__.py +0 -1
  28. cli/connect/connect.py +7 -6
  29. cli/connect/protopie/protopie.py +32 -16
  30. cli/errors.py +6 -5
  31. cli/remotive.py +13 -9
  32. cli/requirements.txt +4 -1
  33. cli/settings.py +9 -9
  34. cli/tools/__init__.py +0 -1
  35. cli/tools/can/__init__.py +0 -1
  36. cli/tools/can/can.py +8 -8
  37. cli/tools/tools.py +2 -2
  38. {remotivelabs_cli-0.0.25.dist-info → remotivelabs_cli-0.0.27.dist-info}/METADATA +5 -3
  39. remotivelabs_cli-0.0.27.dist-info/RECORD +45 -0
  40. remotivelabs_cli-0.0.25.dist-info/RECORD +0 -44
  41. {remotivelabs_cli-0.0.25.dist-info → remotivelabs_cli-0.0.27.dist-info}/LICENSE +0 -0
  42. {remotivelabs_cli-0.0.25.dist-info → remotivelabs_cli-0.0.27.dist-info}/WHEEL +0 -0
  43. {remotivelabs_cli-0.0.25.dist-info → remotivelabs_cli-0.0.27.dist-info}/entry_points.txt +0 -0
cli/broker/brokers.py CHANGED
@@ -19,7 +19,7 @@ app = typer.Typer(rich_markup_mode="rich")
19
19
  @app.callback()
20
20
  def main(
21
21
  url: str = typer.Option(None, is_eager=False, help="Broker URL", envvar="REMOTIVE_BROKER_URL"),
22
- ):
22
+ ) -> None:
23
23
  # This can be used to override the --url per command, lets see if this is a better approach
24
24
  if url is not None:
25
25
  os.environ["REMOTIVE_BROKER_URL"] = url
@@ -28,7 +28,7 @@ def main(
28
28
 
29
29
 
30
30
  @app.command(help="Discover brokers on this network")
31
- def discover():
31
+ def discover() -> None:
32
32
  # print("Not implemented")
33
33
 
34
34
  zeroconf = Zeroconf(ip_version=IPVersion.V4Only)
cli/broker/export.py CHANGED
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import os
4
4
  import signal as os_signal
5
- from typing import List
5
+ from typing import Any, List
6
6
 
7
7
  import grpc
8
8
  import typer
@@ -28,7 +28,7 @@ def influxdb(
28
28
  # namespace: str = typer.Option(..., help="Cloud Broker API-KEY or access token", envvar="REMOTIVE_BROKER_API_KEY"),
29
29
  on_change_only: bool = typer.Option(default=False, help="Only get signal if value is changed"),
30
30
  output: str = typer.Option(None, help="Write results to file, defaults to stdout"),
31
- ):
31
+ ) -> None:
32
32
  """
33
33
  Exports subscribed signals to InfluxDB line-protocol, really useful to dump some signals into
34
34
  influxdb for offline analysis and insights.
@@ -53,12 +53,12 @@ def influxdb(
53
53
  if output is not None:
54
54
  f = open(output, "w")
55
55
 
56
- def exit_on_ctrlc(sig, frame):
56
+ def exit_on_ctrlc(sig: Any, frame: Any) -> None:
57
57
  if output is not None:
58
58
  f.close()
59
59
  os._exit(0)
60
60
 
61
- def per_frame_influx_line_protocol(x):
61
+ def per_frame_influx_line_protocol(x: Any) -> None:
62
62
  signals = list(x)
63
63
  if len(signals) == 0:
64
64
  return
@@ -107,7 +107,7 @@ def influxdb(
107
107
  # signals2 = list(map( lambda s: s['signal'], broker.list_signal_names2(namespace)))
108
108
  try:
109
109
 
110
- def to_subscribable_signal(sig: str):
110
+ def to_subscribable_signal(sig: str) -> SubscribableSignal:
111
111
  arr = sig.split(":")
112
112
  if len(arr) != 2:
113
113
  ErrorPrinter.print_hint(f"--signal must have format namespace:signal ({sig})")
cli/broker/files.py CHANGED
@@ -11,14 +11,14 @@ from cli.errors import ErrorPrinter
11
11
 
12
12
  from .lib.broker import Broker
13
13
 
14
- app = typer.Typer(help=help)
14
+ app = typer.Typer(help=help) # type: ignore
15
15
 
16
16
 
17
17
  @app.command()
18
18
  def reload_configuration(
19
19
  url: str = typer.Option(..., help="Broker URL", envvar="REMOTIVE_BROKER_URL"),
20
20
  api_key: str = typer.Option("offline", help="Cloud Broker API-KEY or access token", envvar="REMOTIVE_BROKER_API_KEY"),
21
- ):
21
+ ) -> None:
22
22
  try:
23
23
  broker = Broker(url, api_key)
24
24
  broker.reload_config()
@@ -33,7 +33,7 @@ def delete(
33
33
  exit_on_failure: bool = typer.Option(False, help="Exits if there was a problem deleting a file"),
34
34
  url: str = typer.Option(..., help="Broker URL", envvar="REMOTIVE_BROKER_URL"),
35
35
  api_key: str = typer.Option("offline", help="Cloud Broker API-KEY or access token", envvar="REMOTIVE_BROKER_API_KEY"),
36
- ):
36
+ ) -> None:
37
37
  """
38
38
  Deletes the specified files from the broker
39
39
  """
@@ -55,7 +55,7 @@ def download(
55
55
  output: str = typer.Option("", help="Optional output file name"),
56
56
  url: str = typer.Option(..., help="Broker URL", envvar="REMOTIVE_BROKER_URL"),
57
57
  api_key: str = typer.Option("offline", help="Cloud Broker API-KEY or access token", envvar="REMOTIVE_BROKER_API_KEY"),
58
- ):
58
+ ) -> None:
59
59
  """
60
60
  Downloads a file from a broker
61
61
  """
@@ -85,7 +85,7 @@ def upload(
85
85
  output: str = typer.Option("", help="Optional output path on broker"),
86
86
  url: str = typer.Option(..., help="Broker URL", envvar="REMOTIVE_BROKER_URL"),
87
87
  api_key: str = typer.Option("offline", help="Cloud Broker API-KEY or access token", envvar="REMOTIVE_BROKER_API_KEY"),
88
- ):
88
+ ) -> None:
89
89
  """
90
90
  Uploads a file to a broker - physical or in cloud.
91
91
  """
cli/broker/lib/broker.py CHANGED
@@ -8,11 +8,10 @@ import queue
8
8
  import signal as os_signal
9
9
  import tempfile
10
10
  import time
11
- import typing
12
11
  import zipfile
13
12
  from dataclasses import dataclass
14
13
  from threading import Thread
15
- from typing import Callable, List, Sequence, Union
14
+ from typing import Any, Callable, Dict, Iterable, List, Sequence, Union
16
15
 
17
16
  import grpc
18
17
  import remotivelabs.broker.generated.sync.traffic_api_pb2 as traffic_api
@@ -42,10 +41,10 @@ class LicenseInfo:
42
41
 
43
42
 
44
43
  class Broker:
45
- def __init__(self, url: str, api_key: Union[str, None] = None):
44
+ def __init__(self, url: str, api_key: Union[str, None] = None) -> None:
46
45
  self.url = url
47
46
  self.api_key = api_key
48
- self.q = queue.Queue()
47
+ self.q: queue.Queue[Any] = queue.Queue()
49
48
  """Main function, checking arguments passed to script, setting up stubs, configuration and starting Threads."""
50
49
  # Setting up stubs and configuration
51
50
 
@@ -70,7 +69,7 @@ class Broker:
70
69
  self.signal_creator = br.SignalCreator(self.system_stub)
71
70
 
72
71
  @staticmethod
73
- def __check_playbackmode_result(status):
72
+ def __check_playbackmode_result(status: br.traffic_api_pb2.PlaybackInfos) -> None:
74
73
  err_cnt = 0
75
74
  for mode in status.playbackInfo:
76
75
  if mode.playbackMode.errorMessage:
@@ -79,8 +78,8 @@ class Broker:
79
78
  if err_cnt > 0:
80
79
  raise typer.Exit(1)
81
80
 
82
- def seek(self, recording_and_namespace: List, offset: int, silent: bool = True):
83
- def to_playback(rec):
81
+ def seek(self, recording_and_namespace: List[Any], offset: int, silent: bool = True) -> br.traffic_api_pb2.PlaybackInfos:
82
+ def to_playback(rec: Any) -> Dict[str, Any]:
84
83
  return {"namespace": rec["namespace"], "path": rec["recording"], "mode": br.traffic_api_pb2.Mode.SEEK, "offsettime": offset}
85
84
 
86
85
  playback_list = map(to_playback, recording_and_namespace)
@@ -91,8 +90,8 @@ class Broker:
91
90
  self.__check_playbackmode_result(status)
92
91
  return status
93
92
 
94
- def play(self, recording_and_namespace: List, silent: bool = False):
95
- def to_playback(rec):
93
+ def play(self, recording_and_namespace: List[Any], silent: bool = False) -> br.traffic_api_pb2.PlaybackInfos:
94
+ def to_playback(rec: Any) -> Dict[str, Any]:
96
95
  return {
97
96
  "namespace": rec["namespace"],
98
97
  "path": rec["recording"],
@@ -109,8 +108,8 @@ class Broker:
109
108
  self.__check_playbackmode_result(status)
110
109
  return status
111
110
 
112
- def stop_play(self, recording_and_namespace: List, silent: bool = False):
113
- def to_playback(rec):
111
+ def stop_play(self, recording_and_namespace: List[Any], silent: bool = False) -> br.traffic_api_pb2.PlaybackInfos:
112
+ def to_playback(rec: Any) -> Dict[str, Any]:
114
113
  return {
115
114
  "namespace": rec["namespace"],
116
115
  "path": rec["recording"],
@@ -126,8 +125,8 @@ class Broker:
126
125
  self.__check_playbackmode_result(status)
127
126
  return status
128
127
 
129
- def pause_play(self, recording_and_namespace: List, silent: bool = False):
130
- def to_playback(rec):
128
+ def pause_play(self, recording_and_namespace: List[Any], silent: bool = False) -> br.traffic_api_pb2.PlaybackInfos:
129
+ def to_playback(rec: Any) -> Dict[str, Any]:
131
130
  return {
132
131
  "namespace": rec["namespace"],
133
132
  "path": rec["recording"],
@@ -143,8 +142,8 @@ class Broker:
143
142
  self.__check_playbackmode_result(status)
144
143
  return status
145
144
 
146
- def record_multiple(self, namespaces: List[str], path: str):
147
- def to_playback(namespace):
145
+ def record_multiple(self, namespaces: List[str], path: str) -> br.traffic_api_pb2.PlaybackInfos:
146
+ def to_playback(namespace: str) -> Dict[str, Any]:
148
147
  return {
149
148
  "namespace": namespace,
150
149
  "path": path + "_" + namespace,
@@ -159,7 +158,7 @@ class Broker:
159
158
  self.__check_playbackmode_result(status)
160
159
  return status
161
160
 
162
- def record(self, namespace: str, path: str):
161
+ def record(self, namespace: str, path: str) -> br.traffic_api_pb2.PlaybackInfos:
163
162
  playback_list = [
164
163
  {
165
164
  "namespace": namespace,
@@ -174,7 +173,7 @@ class Broker:
174
173
  self.__check_playbackmode_result(status)
175
174
  return status
176
175
 
177
- def stop(self, namespace: str, path: str, silent: bool = False):
176
+ def stop(self, namespace: str, path: str, silent: bool = False) -> br.traffic_api_pb2.PlaybackInfos:
178
177
  playback_list = [
179
178
  {
180
179
  "namespace": namespace,
@@ -190,20 +189,22 @@ class Broker:
190
189
  self.__check_playbackmode_result(status)
191
190
  return status
192
191
 
193
- def listen_on_playback(self, repeat: bool, recording_and_namespace: List, callback: Callable[[int, int, str], None]):
192
+ def listen_on_playback(self, repeat: bool, recording_and_namespace: List[Any], callback: Callable[[int, int, str], None]) -> None:
194
193
  # include recording_and_namespace if we want to loop the recording
195
194
  # This can probably be improved
196
- def get_mode(mode: int):
195
+ def get_mode(mode: int) -> str:
197
196
  if mode == 0:
198
197
  return "playing"
199
198
  if mode == 1:
200
199
  return "paused"
201
200
  if mode == 2:
202
201
  return "stopped"
202
+ raise ValueError("Unknown Mode")
203
203
 
204
204
  sub = self.traffic_stub.PlayTrafficStatus(br.common_pb2.Empty())
205
205
  for playback_state in sub:
206
- p = typing.cast(br.traffic_api_pb2.PlaybackInfos, playback_state)
206
+ # p = typing.cast(br.traffic_api_pb2.PlaybackInfos, playback_state) # REDUNDANT CAST
207
+ p = playback_state
207
208
  offset_length = int(p.playbackInfo[0].playbackMode.offsetTime / 1000000)
208
209
  start_time = p.playbackInfo[0].playbackMode.startTime
209
210
  end_time = p.playbackInfo[0].playbackMode.endTime
@@ -218,7 +219,7 @@ class Broker:
218
219
  self.play(recording_and_namespace)
219
220
  callback(offset_length, total_length, get_mode(mode))
220
221
 
221
- def pause(self, namespace: str, path: str, silent: bool = False):
222
+ def pause(self, namespace: str, path: str, silent: bool = False) -> br.traffic_api_pb2.PlaybackInfos:
222
223
  playback_list = [
223
224
  {
224
225
  "namespace": namespace,
@@ -234,8 +235,8 @@ class Broker:
234
235
  self.__check_playbackmode_result(status)
235
236
  return status
236
237
 
237
- def stop_multiple(self, namespaces: List[str], path: str):
238
- def to_playback(namespace):
238
+ def stop_multiple(self, namespaces: List[str], path: str) -> br.traffic_api_pb2.PlaybackInfos:
239
+ def to_playback(namespace: str) -> Dict[str, Any]:
239
240
  return {
240
241
  "namespace": namespace,
241
242
  "path": path + "_" + namespace,
@@ -250,17 +251,17 @@ class Broker:
250
251
  self.__check_playbackmode_result(status)
251
252
  return status
252
253
 
253
- def diagnose_stop(self, namespace: List[str]):
254
+ def diagnose_stop(self, namespace: List[str]) -> None:
254
255
  recording_name = "diagnose__"
255
256
  self.stop_multiple(namespace, recording_name)
256
257
 
257
- def diagnose(self, namespace: List[str], wait_for_traffic: bool = False):
258
+ def diagnose(self, namespace: List[str], wait_for_traffic: bool = False) -> None:
258
259
  recording_name = "diagnose__"
259
260
 
260
261
  keep_running = True
261
262
  keep_running_during_recording = True
262
263
 
263
- def exit_on_ctrlc(sig, frame):
264
+ def exit_on_ctrlc(sig: Any, frame: Any) -> None:
264
265
  nonlocal keep_running
265
266
  keep_running = False
266
267
  nonlocal keep_running_during_recording
@@ -299,7 +300,7 @@ class Broker:
299
300
  if not wait_for_traffic or (not keep_running and not keep_running_during_recording):
300
301
  print(f'Namespace {r["namespace"]} did not receive any traffic')
301
302
 
302
- def upload(self, file: str, dest: str):
303
+ def upload(self, file: str, dest: str) -> None:
303
304
  try:
304
305
  br.helper.upload_file(system_stub=self.system_stub, path=file, dest_path=dest)
305
306
  except grpc.RpcError as rpc_error:
@@ -321,14 +322,14 @@ class Broker:
321
322
 
322
323
  # rpc BatchDeleteFiles (FileDescriptions) returns (Empty) {}
323
324
 
324
- def upload_folder(self, folder: str):
325
+ def upload_folder(self, folder: str) -> None:
325
326
  try:
326
327
  br.helper.upload_folder(system_stub=self.system_stub, folder=folder)
327
328
  except grpc.RpcError as rpc_error:
328
329
  print(f"Failed to upload file - {rpc_error.details()} ({rpc_error.code()})")
329
330
  raise typer.Exit(1)
330
331
 
331
- def download(self, file: str, dest: str, delegate_err: bool = False):
332
+ def download(self, file: str, dest: str, delegate_err: bool = False) -> None:
332
333
  try:
333
334
  br_helper.download_file(system_stub=self.system_stub, path=file, dest_path=dest)
334
335
  except grpc.RpcError as rpc_error:
@@ -339,7 +340,7 @@ class Broker:
339
340
  os.remove(dest)
340
341
  raise typer.Exit(1)
341
342
 
342
- def reload_config(self):
343
+ def reload_config(self) -> None:
343
344
  try:
344
345
  request = br.common_pb2.Empty()
345
346
  response = self.system_stub.ReloadConfiguration(request, timeout=60000)
@@ -351,7 +352,7 @@ class Broker:
351
352
  print(f"Failed to reload configuration - {rpc_error.details()} ({rpc_error.code()})")
352
353
  raise typer.Exit(1)
353
354
 
354
- def list_namespaces(self):
355
+ def list_namespaces(self) -> List[str]:
355
356
  # Lists available signals
356
357
  configuration = self.system_stub.GetConfiguration(br.common_pb2.Empty())
357
358
  namespaces = []
@@ -359,7 +360,7 @@ class Broker:
359
360
  namespaces.append(network_info.namespace.name)
360
361
  return namespaces
361
362
 
362
- def list_signal_names(self):
363
+ def list_signal_names(self) -> List[Dict[str, Any]]:
363
364
  # Lists available signals
364
365
  configuration = self.system_stub.GetConfiguration(br.common_pb2.Empty())
365
366
 
@@ -368,9 +369,30 @@ class Broker:
368
369
  res = self.system_stub.ListSignals(network_info.namespace)
369
370
  for finfo in res.frame:
370
371
  # f: br.common_pb2.FrameInfo = finfo
371
- signal_names.append({"signal": finfo.signalInfo.id.name, "namespace": network_info.namespace.name})
372
+ receivers = []
372
373
  for sinfo in finfo.childInfo:
373
- signal_names.append({"signal": sinfo.id.name, "namespace": network_info.namespace.name})
374
+ rec = list(map(lambda r: r, sinfo.metaData.receiver))
375
+ receivers.extend(rec)
376
+ signal_names.append(
377
+ {
378
+ "signal": sinfo.id.name,
379
+ "namespace": network_info.namespace.name,
380
+ "receivers": rec,
381
+ "min": sinfo.metaData.min,
382
+ "max": sinfo.metaData.max,
383
+ }
384
+ )
385
+
386
+ signal_names.append(
387
+ {
388
+ "signal": finfo.signalInfo.id.name,
389
+ "namespace": network_info.namespace.name,
390
+ "senders": list(map(lambda s: s, finfo.signalInfo.metaData.sender)),
391
+ "receivers": list(set(receivers)),
392
+ "cycletime": finfo.signalInfo.metaData.cycleTime,
393
+ }
394
+ )
395
+
374
396
  return signal_names
375
397
 
376
398
  def subscribe_on_script(
@@ -378,7 +400,7 @@ class Broker:
378
400
  script: bytes,
379
401
  on_frame: Callable[[Sequence[br.network_api_pb2.Signal]], None],
380
402
  changed_values_only: bool = False,
381
- ) -> grpc.RpcContext:
403
+ ) -> Any:
382
404
  client_id = br.common_pb2.ClientId(id="cli")
383
405
  # sync = queue.Queue()
384
406
  thread = Thread(
@@ -406,11 +428,11 @@ class Broker:
406
428
  # over namespaces
407
429
  # Begin
408
430
 
409
- def verify_namespace(available_signal):
410
- return list(filter(lambda namespace: available_signal["namespace"] == namespace, subscribed_namespaces))
431
+ def verify_namespace(available_signal: List[Dict[str, str]]) -> List[str]:
432
+ return list(filter(lambda namespace: available_signal["namespace"] == namespace, subscribed_namespaces)) # type: ignore
411
433
 
412
- def find_subscribed_signal(available_signal):
413
- return list(filter(lambda s: available_signal["signal"] == s, subscribed_signals))
434
+ def find_subscribed_signal(available_signal: List[Dict[str, str]]) -> List[str]:
435
+ return list(filter(lambda s: available_signal["signal"] == s, subscribed_signals)) # type: ignore
414
436
 
415
437
  existing_signals = self.list_signal_names()
416
438
  existing_ns = set(map(lambda s: s["namespace"], existing_signals))
@@ -424,8 +446,8 @@ class Broker:
424
446
  )
425
447
  exit(1)
426
448
 
427
- available_signals = list(filter(verify_namespace, existing_signals))
428
- signals_to_subscribe_to = list(filter(find_subscribed_signal, available_signals))
449
+ available_signals = list(filter(verify_namespace, existing_signals)) # type: ignore
450
+ signals_to_subscribe_to = list(filter(find_subscribed_signal, available_signals)) # type: ignore
429
451
 
430
452
  # Check if subscription is done on signal that is not in any of these namespaces
431
453
  signals_subscribed_to_but_does_not_exist = set(subscribed_signals) - set(map(lambda s: s["signal"], signals_to_subscribe_to))
@@ -436,7 +458,9 @@ class Broker:
436
458
 
437
459
  return list(map(lambda s: SubscribableSignal(s["signal"], s["namespace"]), signals_to_subscribe_to))
438
460
 
439
- def long_name_subscribe(self, signals_to_subscribe_to: List[SubscribableSignal], on_frame, changed_values_only: bool = True):
461
+ def long_name_subscribe(
462
+ self, signals_to_subscribe_to: List[SubscribableSignal], on_frame: Callable[..., Any], changed_values_only: bool = True
463
+ ) -> Any:
440
464
  client_id = br.common_pb2.ClientId(id="cli")
441
465
 
442
466
  # TODO - This can be improved moving forward and we also need to move the validation into api
@@ -444,7 +468,7 @@ class Broker:
444
468
  list(map(lambda s: s.namespace, signals_to_subscribe_to)), (list(map(lambda s: s.name, signals_to_subscribe_to)))
445
469
  )
446
470
 
447
- def to_protobuf_signal(s: SubscribableSignal):
471
+ def to_protobuf_signal(s: SubscribableSignal) -> br.common_pb2.SignalId:
448
472
  return self.signal_creator.signal(s.name, s.namespace)
449
473
 
450
474
  signals_to_subscribe_on = list(map(to_protobuf_signal, signals_to_subscribe_to))
@@ -464,14 +488,20 @@ class Broker:
464
488
  ecu, subscription = self.q.get()
465
489
  return subscription
466
490
 
467
- def subscribe(self, subscribed_signals: list[str], subscribed_namespaces: list[str], on_frame, changed_values_only: bool = True):
491
+ def subscribe(
492
+ self,
493
+ subscribed_signals: list[str],
494
+ subscribed_namespaces: list[str],
495
+ on_frame: Callable[..., Any],
496
+ changed_values_only: bool = True,
497
+ ) -> Any:
468
498
  client_id = br.common_pb2.ClientId(id="cli")
469
499
 
470
500
  signals_to_subscribe_to: List[SubscribableSignal] = self.validate_and_get_subscribed_signals(
471
501
  subscribed_namespaces, subscribed_signals
472
502
  )
473
503
 
474
- def to_protobuf_signal(s: SubscribableSignal):
504
+ def to_protobuf_signal(s: SubscribableSignal) -> br.common_pb2.SignalId:
475
505
  return self.signal_creator.signal(s.name, s.namespace)
476
506
 
477
507
  signals_to_subscribe_on = list(map(to_protobuf_signal, signals_to_subscribe_to))
@@ -491,7 +521,7 @@ class Broker:
491
521
  ecu, subscription = self.q.get()
492
522
  return subscription
493
523
 
494
- def __each_signal(self, signals, callback):
524
+ def __each_signal(self, signals: Iterable[br.network_api_pb2.Signal], callback: Callable[..., Any]) -> None:
495
525
  callback(
496
526
  map(
497
527
  lambda s: {"timestamp_us": s.timestamp, "namespace": s.id.namespace.name, "name": s.id.name, "value": self.__get_value(s)},
@@ -500,7 +530,7 @@ class Broker:
500
530
  )
501
531
 
502
532
  @staticmethod
503
- def __get_value(signal):
533
+ def __get_value(signal: br.network_api_pb2.Signal) -> Any:
504
534
  if signal.raw != b"":
505
535
  return "0x" + binascii.hexlify(signal.raw).decode("ascii")
506
536
  if signal.HasField("integer"):
@@ -512,7 +542,7 @@ class Broker:
512
542
  return "empty"
513
543
 
514
544
  @staticmethod
515
- def __create_playback_config(item):
545
+ def __create_playback_config(item: Dict[str, Any]) -> br.traffic_api_pb2.PlaybackInfo:
516
546
  """Creating configuration for playback
517
547
 
518
548
  Parameters
@@ -527,9 +557,10 @@ class Broker:
527
557
 
528
558
  """
529
559
 
530
- def get_offset_time():
560
+ def get_offset_time() -> int:
531
561
  if "offsettime" in item:
532
- return item["offsettime"]
562
+ return int(item["offsettime"])
563
+ return 0
533
564
 
534
565
  playback_config = br.traffic_api_pb2.PlaybackConfig(
535
566
  fileDescription=br.system_api_pb2.FileDescription(path=item["path"]),
@@ -549,7 +580,7 @@ class Broker:
549
580
  machine_id=license_info.requestMachineId.decode("utf-8"),
550
581
  )
551
582
 
552
- def apply_license(self, license_data_b64: bytes):
583
+ def apply_license(self, license_data_b64: bytes) -> LicenseInfo:
553
584
  license = br.system_api_pb2.License()
554
585
  license.data = license_data_b64
555
586
  license.termsAgreement = True
@@ -10,8 +10,8 @@ import typer
10
10
  from rich.console import Console
11
11
  from rich.progress import Progress, SpinnerColumn, TextColumn
12
12
 
13
- import cli.cloud.rest_helper as rest
14
13
  from cli.broker.lib.broker import Broker, LicenseInfo
14
+ from cli.cloud.rest_helper import RestHelper as Rest
15
15
 
16
16
  console = Console(stderr=True)
17
17
 
@@ -25,7 +25,7 @@ class LicenseFlow:
25
25
  )
26
26
  return b.get_license()
27
27
 
28
- def describe_with_hotspot(self, url: Union[str, None] = "http://192.168.4.1:50051"):
28
+ def describe_with_hotspot(self, url: Union[str, None] = "http://192.168.4.1:50051") -> LicenseInfo:
29
29
  if url is None:
30
30
  url = "http://192.168.4.1:50051"
31
31
 
@@ -34,7 +34,7 @@ class LicenseFlow:
34
34
  )
35
35
  return b.get_license()
36
36
 
37
- def request_with_url_with_internet(self, url: str):
37
+ def request_with_url_with_internet(self, url: str) -> None:
38
38
  console.print("This requires internet connection from your computer during the entire licensing process")
39
39
 
40
40
  email = LicenseFlow.__try_authenticate_and_get_email_from_cloud()
@@ -68,7 +68,7 @@ class LicenseFlow:
68
68
  if new_license.valid:
69
69
  console.print(f":thumbsup: Successfully applied license, it remains valid until {new_license.expires}")
70
70
 
71
- def request_with_hotspot(self, url: Union[str, None] = "http://192.168.4.1:50051"):
71
+ def request_with_hotspot(self, url: Union[str, None] = "http://192.168.4.1:50051") -> None:
72
72
  """
73
73
  This flow expects changes between networks and tries to guide the user accordingly
74
74
  :param url: If None it will use the default hotspot IP
@@ -137,12 +137,14 @@ class LicenseFlow:
137
137
  with use_progress("Fetching user info from cloud... Make sure you are connected to internet"):
138
138
  while True:
139
139
  try:
140
- r = rest.handle_get("/api/whoami", return_response=True, use_progress_indicator=False, timeout=5)
140
+ r = Rest.handle_get("/api/whoami", return_response=True, use_progress_indicator=False, timeout=5)
141
141
  break
142
142
  except (requests.exceptions.ConnectionError, requests.exceptions.Timeout):
143
143
  time.sleep(1)
144
144
  console.print(":white_check_mark: Fetching user info from cloud... Make sure you are connected to internet")
145
- return r.json()["email"]
145
+ if r is None:
146
+ return ""
147
+ return str(r.json()["email"])
146
148
 
147
149
  @staticmethod
148
150
  def __try_request_license(
@@ -153,15 +155,15 @@ class LicenseFlow:
153
155
  with use_progress(progress_label):
154
156
  while True:
155
157
  try:
156
- license_data_b64 = rest.request_license(email, json.loads(existing_license.machine_id)).encode()
158
+ license_data_b64 = Rest.request_license(email, json.loads(existing_license.machine_id)).encode()
157
159
  break
158
160
  except (requests.exceptions.ConnectionError, requests.exceptions.Timeout):
159
161
  time.sleep(1)
160
162
  console.print(f":white_check_mark: {progress_label}")
161
- return license_data_b64
163
+ return bytes(license_data_b64)
162
164
 
163
165
 
164
- def use_progress(label: str):
166
+ def use_progress(label: str) -> Progress:
165
167
  p = Progress(SpinnerColumn(), TextColumn("[progress.description]{task.description}"), transient=True, expand=False)
166
168
  p.add_task(label, total=1)
167
169
  return p
cli/broker/licenses.py CHANGED
@@ -35,7 +35,7 @@ class Connection(str, Enum):
35
35
  def describe(
36
36
  connect: Connection = typer.Option("url", case_sensitive=False, help="How to connect to broker"),
37
37
  url: str = typer.Option("http://localhost:50051", is_eager=False, help="Broker URL", envvar="REMOTIVE_BROKER_URL"),
38
- ):
38
+ ) -> None:
39
39
  """
40
40
  Show licence information
41
41
 
@@ -70,7 +70,7 @@ def request(
70
70
  help="Broker url, this is mandatory when connect type is 'url'",
71
71
  envvar="REMOTIVE_BROKER_URL",
72
72
  ),
73
- ):
73
+ ) -> None:
74
74
  """
75
75
  Requests and applies a new or existing License to a broker, Note that internet access is required on your
76
76
  computer