remotivelabs-cli 0.0.25__tar.gz → 0.0.26__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 (49) hide show
  1. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/PKG-INFO +5 -3
  2. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/broker/brokers.py +2 -2
  3. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/broker/export.py +5 -5
  4. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/broker/files.py +5 -5
  5. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/broker/lib/broker.py +59 -49
  6. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/broker/license_flows.py +11 -9
  7. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/broker/licenses.py +2 -2
  8. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/broker/playback.py +14 -34
  9. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/broker/record.py +3 -3
  10. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/broker/scripting.py +4 -4
  11. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/broker/signals.py +11 -11
  12. remotivelabs_cli-0.0.26/cli/cloud/__init__.py +0 -0
  13. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/cloud/auth.py +40 -35
  14. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/cloud/auth_tokens.py +39 -36
  15. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/cloud/brokers.py +24 -33
  16. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/cloud/cloud_cli.py +9 -6
  17. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/cloud/configs.py +19 -11
  18. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/cloud/filestorage.py +63 -51
  19. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/cloud/projects.py +10 -7
  20. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/cloud/recordings.py +127 -108
  21. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/cloud/recordings_playback.py +52 -39
  22. remotivelabs_cli-0.0.26/cli/cloud/rest_helper.py +284 -0
  23. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/cloud/resumable_upload.py +9 -8
  24. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/cloud/sample_recordings.py +5 -5
  25. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/cloud/service_account_tokens.py +18 -16
  26. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/cloud/service_accounts.py +9 -9
  27. remotivelabs_cli-0.0.26/cli/connect/__init__.py +0 -0
  28. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/connect/connect.py +7 -6
  29. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/connect/protopie/protopie.py +32 -16
  30. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/errors.py +6 -5
  31. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/remotive.py +13 -9
  32. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/requirements.txt +4 -1
  33. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/settings.py +9 -9
  34. remotivelabs_cli-0.0.26/cli/tools/__init__.py +0 -0
  35. remotivelabs_cli-0.0.26/cli/tools/can/__init__.py +0 -0
  36. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/tools/can/can.py +8 -8
  37. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/tools/tools.py +2 -2
  38. remotivelabs_cli-0.0.26/pyproject.toml +155 -0
  39. remotivelabs_cli-0.0.25/cli/cloud/__init__.py +0 -1
  40. remotivelabs_cli-0.0.25/cli/cloud/rest_helper.py +0 -233
  41. remotivelabs_cli-0.0.25/cli/connect/__init__.py +0 -1
  42. remotivelabs_cli-0.0.25/cli/tools/__init__.py +0 -1
  43. remotivelabs_cli-0.0.25/cli/tools/can/__init__.py +0 -1
  44. remotivelabs_cli-0.0.25/pyproject.toml +0 -38
  45. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/LICENSE +0 -0
  46. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/README.md +0 -0
  47. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/__about__.py +0 -0
  48. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/__init__.py +0 -0
  49. {remotivelabs_cli-0.0.25 → remotivelabs_cli-0.0.26}/cli/broker/lib/__about__.py +0 -0
@@ -1,16 +1,17 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: remotivelabs-cli
3
- Version: 0.0.25
3
+ Version: 0.0.26
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.0
7
+ Requires-Python: >=3.8,<3.12
8
8
  Classifier: Programming Language :: Python :: 3
9
9
  Classifier: Programming Language :: Python :: 3.8
10
10
  Classifier: Programming Language :: Python :: 3.9
11
11
  Classifier: Programming Language :: Python :: 3.10
12
12
  Classifier: Programming Language :: Python :: 3.11
13
- Classifier: Programming Language :: Python :: 3.12
13
+ Requires-Dist: grpc-stubs (>=1.53.0.5)
14
+ Requires-Dist: mypy-protobuf (>=3.0.0)
14
15
  Requires-Dist: plotext (>=5.2,<6.0)
15
16
  Requires-Dist: pyjwt (>=2.6,<3.0)
16
17
  Requires-Dist: python-can (>=4.3.1)
@@ -19,6 +20,7 @@ Requires-Dist: remotivelabs-broker (>=0.1.17,<0.2.0)
19
20
  Requires-Dist: rich (>=13.7.0,<13.8.0)
20
21
  Requires-Dist: trogon (>=0.5.0)
21
22
  Requires-Dist: typer (>=0.9.0,<0.10.0)
23
+ Requires-Dist: types-requests (>=2.32.0.20240622,<3.0.0.0)
22
24
  Requires-Dist: websocket-client (>=1.6,<2.0)
23
25
  Requires-Dist: zeroconf (>=0.127.0,<0.128.0)
24
26
  Description-Content-Type: text/markdown
@@ -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)
@@ -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})")
@@ -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
  """
@@ -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, str]]:
363
364
  # Lists available signals
364
365
  configuration = self.system_stub.GetConfiguration(br.common_pb2.Empty())
365
366
 
@@ -378,7 +379,7 @@ class Broker:
378
379
  script: bytes,
379
380
  on_frame: Callable[[Sequence[br.network_api_pb2.Signal]], None],
380
381
  changed_values_only: bool = False,
381
- ) -> grpc.RpcContext:
382
+ ) -> Any:
382
383
  client_id = br.common_pb2.ClientId(id="cli")
383
384
  # sync = queue.Queue()
384
385
  thread = Thread(
@@ -406,11 +407,11 @@ class Broker:
406
407
  # over namespaces
407
408
  # Begin
408
409
 
409
- def verify_namespace(available_signal):
410
- return list(filter(lambda namespace: available_signal["namespace"] == namespace, subscribed_namespaces))
410
+ def verify_namespace(available_signal: List[Dict[str, str]]) -> List[str]:
411
+ return list(filter(lambda namespace: available_signal["namespace"] == namespace, subscribed_namespaces)) # type: ignore
411
412
 
412
- def find_subscribed_signal(available_signal):
413
- return list(filter(lambda s: available_signal["signal"] == s, subscribed_signals))
413
+ def find_subscribed_signal(available_signal: List[Dict[str, str]]) -> List[str]:
414
+ return list(filter(lambda s: available_signal["signal"] == s, subscribed_signals)) # type: ignore
414
415
 
415
416
  existing_signals = self.list_signal_names()
416
417
  existing_ns = set(map(lambda s: s["namespace"], existing_signals))
@@ -424,8 +425,8 @@ class Broker:
424
425
  )
425
426
  exit(1)
426
427
 
427
- available_signals = list(filter(verify_namespace, existing_signals))
428
- signals_to_subscribe_to = list(filter(find_subscribed_signal, available_signals))
428
+ available_signals = list(filter(verify_namespace, existing_signals)) # type: ignore
429
+ signals_to_subscribe_to = list(filter(find_subscribed_signal, available_signals)) # type: ignore
429
430
 
430
431
  # Check if subscription is done on signal that is not in any of these namespaces
431
432
  signals_subscribed_to_but_does_not_exist = set(subscribed_signals) - set(map(lambda s: s["signal"], signals_to_subscribe_to))
@@ -436,7 +437,9 @@ class Broker:
436
437
 
437
438
  return list(map(lambda s: SubscribableSignal(s["signal"], s["namespace"]), signals_to_subscribe_to))
438
439
 
439
- def long_name_subscribe(self, signals_to_subscribe_to: List[SubscribableSignal], on_frame, changed_values_only: bool = True):
440
+ def long_name_subscribe(
441
+ self, signals_to_subscribe_to: List[SubscribableSignal], on_frame: Callable[..., Any], changed_values_only: bool = True
442
+ ) -> Any:
440
443
  client_id = br.common_pb2.ClientId(id="cli")
441
444
 
442
445
  # TODO - This can be improved moving forward and we also need to move the validation into api
@@ -444,7 +447,7 @@ class Broker:
444
447
  list(map(lambda s: s.namespace, signals_to_subscribe_to)), (list(map(lambda s: s.name, signals_to_subscribe_to)))
445
448
  )
446
449
 
447
- def to_protobuf_signal(s: SubscribableSignal):
450
+ def to_protobuf_signal(s: SubscribableSignal) -> br.common_pb2.SignalId:
448
451
  return self.signal_creator.signal(s.name, s.namespace)
449
452
 
450
453
  signals_to_subscribe_on = list(map(to_protobuf_signal, signals_to_subscribe_to))
@@ -464,14 +467,20 @@ class Broker:
464
467
  ecu, subscription = self.q.get()
465
468
  return subscription
466
469
 
467
- def subscribe(self, subscribed_signals: list[str], subscribed_namespaces: list[str], on_frame, changed_values_only: bool = True):
470
+ def subscribe(
471
+ self,
472
+ subscribed_signals: list[str],
473
+ subscribed_namespaces: list[str],
474
+ on_frame: Callable[..., Any],
475
+ changed_values_only: bool = True,
476
+ ) -> Any:
468
477
  client_id = br.common_pb2.ClientId(id="cli")
469
478
 
470
479
  signals_to_subscribe_to: List[SubscribableSignal] = self.validate_and_get_subscribed_signals(
471
480
  subscribed_namespaces, subscribed_signals
472
481
  )
473
482
 
474
- def to_protobuf_signal(s: SubscribableSignal):
483
+ def to_protobuf_signal(s: SubscribableSignal) -> br.common_pb2.SignalId:
475
484
  return self.signal_creator.signal(s.name, s.namespace)
476
485
 
477
486
  signals_to_subscribe_on = list(map(to_protobuf_signal, signals_to_subscribe_to))
@@ -491,7 +500,7 @@ class Broker:
491
500
  ecu, subscription = self.q.get()
492
501
  return subscription
493
502
 
494
- def __each_signal(self, signals, callback):
503
+ def __each_signal(self, signals: Iterable[br.network_api_pb2.Signal], callback: Callable[..., Any]) -> None:
495
504
  callback(
496
505
  map(
497
506
  lambda s: {"timestamp_us": s.timestamp, "namespace": s.id.namespace.name, "name": s.id.name, "value": self.__get_value(s)},
@@ -500,7 +509,7 @@ class Broker:
500
509
  )
501
510
 
502
511
  @staticmethod
503
- def __get_value(signal):
512
+ def __get_value(signal: br.network_api_pb2.Signal) -> Any:
504
513
  if signal.raw != b"":
505
514
  return "0x" + binascii.hexlify(signal.raw).decode("ascii")
506
515
  if signal.HasField("integer"):
@@ -512,7 +521,7 @@ class Broker:
512
521
  return "empty"
513
522
 
514
523
  @staticmethod
515
- def __create_playback_config(item):
524
+ def __create_playback_config(item: Dict[str, Any]) -> br.traffic_api_pb2.PlaybackInfo:
516
525
  """Creating configuration for playback
517
526
 
518
527
  Parameters
@@ -527,9 +536,10 @@ class Broker:
527
536
 
528
537
  """
529
538
 
530
- def get_offset_time():
539
+ def get_offset_time() -> int:
531
540
  if "offsettime" in item:
532
- return item["offsettime"]
541
+ return int(item["offsettime"])
542
+ return 0
533
543
 
534
544
  playback_config = br.traffic_api_pb2.PlaybackConfig(
535
545
  fileDescription=br.system_api_pb2.FileDescription(path=item["path"]),
@@ -549,7 +559,7 @@ class Broker:
549
559
  machine_id=license_info.requestMachineId.decode("utf-8"),
550
560
  )
551
561
 
552
- def apply_license(self, license_data_b64: bytes):
562
+ def apply_license(self, license_data_b64: bytes) -> LicenseInfo:
553
563
  license = br.system_api_pb2.License()
554
564
  license.data = license_data_b64
555
565
  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
@@ -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