foxglove-sdk 0.8.1__cp312-cp312-win32.whl → 0.16.3__cp312-cp312-win32.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.

Potentially problematic release.


This version of foxglove-sdk might be problematic. Click here for more details.

@@ -1,154 +1,178 @@
1
- import pytest
2
- from foxglove.websocket import (
3
- AnyNativeParameterValue,
4
- Parameter,
5
- ParameterType,
6
- ParameterValue,
7
- )
8
-
9
-
10
- def test_empty() -> None:
11
- p = Parameter("empty")
12
- assert p.name == "empty"
13
- assert p.type is None
14
- assert p.value is None
15
- assert p.get_value() is None
16
-
17
-
18
- def test_float() -> None:
19
- p = Parameter("float", value=1.234)
20
- assert p.name == "float"
21
- assert p.type == ParameterType.Float64
22
- assert p.value == ParameterValue.Number(1.234)
23
- assert p.get_value() == 1.234
24
-
25
-
26
- def test_int() -> None:
27
- p = Parameter("int", value=1)
28
- assert p.name == "int"
29
- assert p.type == ParameterType.Float64
30
- assert p.value == ParameterValue.Number(1)
31
- assert type(p.get_value()) is float
32
- assert p.get_value() == 1
33
-
34
-
35
- def test_float_array() -> None:
36
- v: AnyNativeParameterValue = [1, 2, 3]
37
- p = Parameter("float_array", value=v)
38
- assert p.name == "float_array"
39
- assert p.type == ParameterType.Float64Array
40
- assert p.value == ParameterValue.Array(
41
- [
42
- ParameterValue.Number(1),
43
- ParameterValue.Number(2),
44
- ParameterValue.Number(3),
45
- ]
46
- )
47
- assert p.get_value() == v
48
-
49
-
50
- def test_heterogeneous_array() -> None:
51
- v: AnyNativeParameterValue = ["a", 2, False]
52
- p = Parameter("heterogeneous_array", value=v)
53
- assert p.name == "heterogeneous_array"
54
- assert p.type is None
55
- assert p.value == ParameterValue.Array(
56
- [
57
- ParameterValue.String("a"),
58
- ParameterValue.Number(2),
59
- ParameterValue.Bool(False),
60
- ]
61
- )
62
- assert p.get_value() == v
63
-
64
-
65
- def test_string() -> None:
66
- p = Parameter("string", value="hello")
67
- assert p.name == "string"
68
- assert p.type is None
69
- assert p.value == ParameterValue.String("hello")
70
- assert p.get_value() == "hello"
71
-
72
-
73
- def test_bytes() -> None:
74
- p = Parameter("bytes", value=b"hello")
75
- assert p.name == "bytes"
76
- assert p.type == ParameterType.ByteArray
77
- assert p.value == ParameterValue.String("aGVsbG8=")
78
- assert p.get_value() == b"hello"
79
-
80
-
81
- def test_dict() -> None:
82
- v: AnyNativeParameterValue = {
83
- "a": True,
84
- "b": 2,
85
- "c": "C",
86
- "d": {"inner": [1, 2, 3]},
87
- }
88
- p = Parameter(
89
- "dict",
90
- value=v,
91
- )
92
- assert p.name == "dict"
93
- assert p.type is None
94
- assert p.value == ParameterValue.Dict(
95
- {
96
- "a": ParameterValue.Bool(True),
97
- "b": ParameterValue.Number(2),
98
- "c": ParameterValue.String("C"),
99
- "d": ParameterValue.Dict(
100
- {
101
- "inner": ParameterValue.Array(
102
- [
103
- ParameterValue.Number(1),
104
- ParameterValue.Number(2),
105
- ParameterValue.Number(3),
106
- ]
107
- )
108
- }
109
- ),
110
- }
111
- )
112
- assert p.get_value() == v
113
-
114
-
115
- def test_explicit() -> None:
116
- # Derive type from value
117
- p = Parameter("float", value=ParameterValue.Number(1))
118
- assert p.type == ParameterType.Float64
119
- assert p.get_value() == 1
120
-
121
- # Override derived type.
122
- p = Parameter(
123
- "bad float array",
124
- value=ParameterValue.Number(1),
125
- type=ParameterType.Float64Array,
126
- )
127
- assert p.type == ParameterType.Float64Array
128
- assert p.get_value() == 1
129
-
130
- # Override derived type in a different way.
131
- p = Parameter(
132
- "bad float",
133
- value=ParameterValue.String("1"),
134
- type=ParameterType.Float64,
135
- )
136
- assert p.type == ParameterType.Float64
137
- assert p.get_value() == "1"
138
-
139
- # Override derived type with None.
140
- p = Parameter("underspecified float", value=ParameterValue.Number(1), type=None)
141
- assert p.type is None
142
- assert p.get_value() == 1
143
-
144
-
145
- def test_base64_decode_error() -> None:
146
- p = Parameter(
147
- "bad bytes",
148
- value=ParameterValue.String("!!!"),
149
- type=ParameterType.ByteArray,
150
- )
151
- assert p.type == ParameterType.ByteArray
152
- assert p.value == ParameterValue.String("!!!")
153
- with pytest.raises(ValueError, match=r"Failed to decode base64"):
154
- p.get_value()
1
+ import pytest
2
+ from foxglove.websocket import (
3
+ AnyNativeParameterValue,
4
+ Parameter,
5
+ ParameterType,
6
+ ParameterValue,
7
+ )
8
+
9
+
10
+ def test_empty() -> None:
11
+ p = Parameter("empty")
12
+ assert p.name == "empty"
13
+ assert p.type is None
14
+ assert p.value is None
15
+ assert p.get_value() is None
16
+
17
+
18
+ def test_float() -> None:
19
+ p = Parameter("float", value=1.234)
20
+ assert p.name == "float"
21
+ assert p.type == ParameterType.Float64
22
+ assert p.value == ParameterValue.Float64(1.234)
23
+ assert p.get_value() == 1.234
24
+
25
+
26
+ def test_int() -> None:
27
+ p = Parameter("int", value=1)
28
+ assert p.name == "int"
29
+ assert p.type is None
30
+ assert p.value == ParameterValue.Integer(1)
31
+ assert type(p.get_value()) is int
32
+ assert p.get_value() == 1
33
+
34
+
35
+ def test_float_array() -> None:
36
+ v: AnyNativeParameterValue = [1.0, 2.0, 3.0]
37
+ p = Parameter("float_array", value=v)
38
+ assert p.name == "float_array"
39
+ assert p.type == ParameterType.Float64Array
40
+ assert p.value == ParameterValue.Array(
41
+ [
42
+ ParameterValue.Float64(1.0),
43
+ ParameterValue.Float64(2.0),
44
+ ParameterValue.Float64(3.0),
45
+ ]
46
+ )
47
+ assert p.get_value() == v
48
+
49
+
50
+ def test_int_array() -> None:
51
+ v: AnyNativeParameterValue = [1, 2, 3]
52
+ p = Parameter("int_array", value=v)
53
+ assert p.name == "int_array"
54
+ assert p.type is None
55
+ assert p.value == ParameterValue.Array(
56
+ [
57
+ ParameterValue.Integer(1),
58
+ ParameterValue.Integer(2),
59
+ ParameterValue.Integer(3),
60
+ ]
61
+ )
62
+ assert p.get_value() == v
63
+
64
+
65
+ def test_parameter_value_integer() -> None:
66
+ p = Parameter("integer_param", value=ParameterValue.Integer(42))
67
+ assert p.name == "integer_param"
68
+ assert p.type is None
69
+ assert p.value == ParameterValue.Integer(42)
70
+ assert type(p.get_value()) is int
71
+ assert p.get_value() == 42
72
+
73
+
74
+ def test_heterogeneous_array() -> None:
75
+ v: AnyNativeParameterValue = ["a", 2, False]
76
+ p = Parameter("heterogeneous_array", value=v)
77
+ assert p.name == "heterogeneous_array"
78
+ assert p.type is None
79
+ assert p.value == ParameterValue.Array(
80
+ [
81
+ ParameterValue.String("a"),
82
+ ParameterValue.Integer(2),
83
+ ParameterValue.Bool(False),
84
+ ]
85
+ )
86
+ assert p.get_value() == v
87
+
88
+
89
+ def test_string() -> None:
90
+ p = Parameter("string", value="hello")
91
+ assert p.name == "string"
92
+ assert p.type is None
93
+ assert p.value == ParameterValue.String("hello")
94
+ assert p.get_value() == "hello"
95
+
96
+
97
+ def test_bytes() -> None:
98
+ p = Parameter("bytes", value=b"hello")
99
+ assert p.name == "bytes"
100
+ assert p.type == ParameterType.ByteArray
101
+ assert p.value == ParameterValue.String("aGVsbG8=")
102
+ assert p.get_value() == b"hello"
103
+
104
+
105
+ def test_dict() -> None:
106
+ v: AnyNativeParameterValue = {
107
+ "a": True,
108
+ "b": 2,
109
+ "c": "C",
110
+ "d": {"inner": [1, 2, 3]},
111
+ }
112
+ p = Parameter(
113
+ "dict",
114
+ value=v,
115
+ )
116
+ assert p.name == "dict"
117
+ assert p.type is None
118
+ assert p.value == ParameterValue.Dict(
119
+ {
120
+ "a": ParameterValue.Bool(True),
121
+ "b": ParameterValue.Integer(2),
122
+ "c": ParameterValue.String("C"),
123
+ "d": ParameterValue.Dict(
124
+ {
125
+ "inner": ParameterValue.Array(
126
+ [
127
+ ParameterValue.Integer(1),
128
+ ParameterValue.Integer(2),
129
+ ParameterValue.Integer(3),
130
+ ]
131
+ )
132
+ }
133
+ ),
134
+ }
135
+ )
136
+ assert p.get_value() == v
137
+
138
+
139
+ def test_explicit() -> None:
140
+ # Derive type from value
141
+ p = Parameter("float", value=ParameterValue.Float64(1))
142
+ assert p.type == ParameterType.Float64
143
+ assert p.get_value() == 1
144
+
145
+ # Override derived type.
146
+ p = Parameter(
147
+ "bad float array",
148
+ value=ParameterValue.Float64(1),
149
+ type=ParameterType.Float64Array,
150
+ )
151
+ assert p.type == ParameterType.Float64Array
152
+ assert p.get_value() == 1
153
+
154
+ # Override derived type in a different way.
155
+ p = Parameter(
156
+ "bad float",
157
+ value=ParameterValue.String("1"),
158
+ type=ParameterType.Float64,
159
+ )
160
+ assert p.type == ParameterType.Float64
161
+ assert p.get_value() == "1"
162
+
163
+ # Override derived type with None.
164
+ p = Parameter("underspecified float", value=ParameterValue.Float64(1), type=None)
165
+ assert p.type is None
166
+ assert p.get_value() == 1
167
+
168
+
169
+ def test_base64_decode_error() -> None:
170
+ p = Parameter(
171
+ "bad bytes",
172
+ value=ParameterValue.String("!!!"),
173
+ type=ParameterType.ByteArray,
174
+ )
175
+ assert p.type == ParameterType.ByteArray
176
+ assert p.value == ParameterValue.String("!!!")
177
+ with pytest.raises(ValueError, match=r"Failed to decode base64"):
178
+ p.get_value()
@@ -0,0 +1,17 @@
1
+ from foxglove.schemas import Log, LogLevel, Timestamp
2
+
3
+ """ Asserts that foxglove schemas can be encoded as protobuf. """
4
+
5
+
6
+ def test_can_encode() -> None:
7
+ msg = Log(
8
+ timestamp=Timestamp(5, 10),
9
+ level=LogLevel.Error,
10
+ message="hello",
11
+ name="logger",
12
+ file="file",
13
+ line=123,
14
+ )
15
+ encoded = msg.encode()
16
+ assert isinstance(encoded, bytes)
17
+ assert len(encoded) == 34
@@ -1,110 +1,141 @@
1
- import time
2
- from urllib.parse import parse_qs, urlparse
3
-
4
- import pytest
5
- from foxglove import (
6
- Capability,
7
- Channel,
8
- Context,
9
- ServerListener,
10
- Service,
11
- start_server,
12
- )
13
- from foxglove.websocket import ServiceSchema, StatusLevel
14
-
15
-
16
- def test_server_interface() -> None:
17
- """
18
- Exercise the server interface; will also be checked with mypy.
19
- """
20
- server = start_server(port=0)
21
- assert isinstance(server.port, int)
22
- assert server.port != 0
23
-
24
- raw_url = server.app_url()
25
- assert raw_url is not None
26
- url = urlparse(raw_url)
27
- assert url.scheme == "https"
28
- assert url.netloc == "app.foxglove.dev"
29
- assert parse_qs(url.query) == {
30
- "ds": ["foxglove-websocket"],
31
- "ds.url": [f"ws://127.0.0.1:{server.port}"],
32
- }
33
-
34
- raw_url = server.app_url(layout_id="lay_123", open_in_desktop=True)
35
- assert raw_url is not None
36
- url = urlparse(raw_url)
37
- assert url.scheme == "https"
38
- assert url.netloc == "app.foxglove.dev"
39
- assert parse_qs(url.query) == {
40
- "ds": ["foxglove-websocket"],
41
- "ds.url": [f"ws://127.0.0.1:{server.port}"],
42
- "layoutId": ["lay_123"],
43
- "openIn": ["desktop"],
44
- }
45
-
46
- server.publish_status("test message", StatusLevel.Info, "some-id")
47
- server.broadcast_time(time.time_ns())
48
- server.remove_status(["some-id"])
49
- server.clear_session()
50
- server.stop()
51
-
52
-
53
- def test_server_listener_provides_default_implementation() -> None:
54
- class DefaultServerListener(ServerListener):
55
- pass
56
-
57
- listener = DefaultServerListener()
58
-
59
- listener.on_parameters_subscribe(["test"])
60
- listener.on_parameters_unsubscribe(["test"])
61
-
62
-
63
- def test_services_interface() -> None:
64
- test_svc = Service(
65
- name="test",
66
- schema=ServiceSchema(name="test-schema"),
67
- handler=lambda *_: b"{}",
68
- )
69
- test2_svc = Service(
70
- name="test2",
71
- schema=ServiceSchema(name="test-schema"),
72
- handler=lambda *_: b"{}",
73
- )
74
- server = start_server(
75
- port=0,
76
- capabilities=[Capability.Services],
77
- supported_encodings=["json"],
78
- services=[test_svc],
79
- )
80
-
81
- # Add a new service.
82
- server.add_services([test2_svc])
83
-
84
- # Can't add a service with the same name.
85
- with pytest.raises(RuntimeError):
86
- server.add_services([test_svc])
87
-
88
- # Remove services.
89
- server.remove_services(["test", "test2"])
90
-
91
- # Re-add a service.
92
- server.add_services([test_svc])
93
-
94
- server.stop()
95
-
96
-
97
- def test_context_can_be_attached_to_server() -> None:
98
- ctx1 = Context()
99
- ctx2 = Context()
100
-
101
- server1 = start_server(port=0, context=ctx1)
102
- server2 = start_server(port=0, context=ctx2)
103
-
104
- ch1 = Channel("/1", context=ctx1)
105
- ch2 = Channel("/2", context=ctx2)
106
- ch1.log("test")
107
- ch2.log("test")
108
-
109
- server1.stop()
110
- server2.stop()
1
+ import time
2
+ import typing
3
+ from urllib.parse import parse_qs, urlparse
4
+
5
+ import pytest
6
+ from foxglove import (
7
+ Capability,
8
+ Channel,
9
+ Context,
10
+ ServerListener,
11
+ Service,
12
+ start_server,
13
+ )
14
+ from foxglove.websocket import PlaybackState, PlaybackStatus, ServiceSchema, StatusLevel
15
+
16
+
17
+ def test_server_interface() -> None:
18
+ """
19
+ Exercise the server interface; will also be checked with mypy.
20
+ """
21
+ server = start_server(
22
+ port=0, session_id="test-session", channel_filter=lambda _: True
23
+ )
24
+ assert isinstance(server.port, int)
25
+ assert server.port != 0
26
+
27
+ raw_url = server.app_url()
28
+ assert raw_url is not None
29
+ url = urlparse(raw_url)
30
+ assert url.scheme == "https"
31
+ assert url.netloc == "app.foxglove.dev"
32
+ assert parse_qs(url.query) == {
33
+ "ds": ["foxglove-websocket"],
34
+ "ds.url": [f"ws://127.0.0.1:{server.port}"],
35
+ }
36
+
37
+ raw_url = server.app_url(layout_id="lay_123", open_in_desktop=True)
38
+ assert raw_url is not None
39
+ url = urlparse(raw_url)
40
+ assert url.scheme == "https"
41
+ assert url.netloc == "app.foxglove.dev"
42
+ assert parse_qs(url.query) == {
43
+ "ds": ["foxglove-websocket"],
44
+ "ds.url": [f"ws://127.0.0.1:{server.port}"],
45
+ "layoutId": ["lay_123"],
46
+ "openIn": ["desktop"],
47
+ }
48
+
49
+ server.publish_status("test message", StatusLevel.Info, "some-id")
50
+ server.broadcast_time(time.time_ns())
51
+ server.broadcast_playback_state(
52
+ PlaybackState(
53
+ status=PlaybackStatus.Paused,
54
+ playback_speed=1.0,
55
+ current_time=time.time_ns(),
56
+ did_seek=False,
57
+ request_id=None,
58
+ )
59
+ )
60
+ server.remove_status(["some-id"])
61
+ server.clear_session("new-session")
62
+ server.stop()
63
+
64
+
65
+ def test_server_listener_provides_default_implementation() -> None:
66
+ class DefaultServerListener(ServerListener):
67
+ pass
68
+
69
+ listener = DefaultServerListener()
70
+
71
+ listener.on_parameters_subscribe(["test"])
72
+ listener.on_parameters_unsubscribe(["test"])
73
+
74
+
75
+ def test_services_interface() -> None:
76
+ test_svc = Service(
77
+ name="test",
78
+ schema=ServiceSchema(name="test-schema"),
79
+ handler=lambda *_: b"{}",
80
+ )
81
+ test2_svc = Service(
82
+ name="test2",
83
+ schema=ServiceSchema(name="test-schema"),
84
+ handler=lambda *_: b"{}",
85
+ )
86
+ server = start_server(
87
+ port=0,
88
+ capabilities=[Capability.Services],
89
+ supported_encodings=["json"],
90
+ services=[test_svc],
91
+ )
92
+
93
+ # Add a new service.
94
+ server.add_services([test2_svc])
95
+
96
+ # Can't add a service with the same name.
97
+ with pytest.raises(RuntimeError):
98
+ server.add_services([test_svc])
99
+
100
+ # Remove services.
101
+ server.remove_services(["test", "test2"])
102
+
103
+ # Re-add a service.
104
+ server.add_services([test_svc])
105
+
106
+ server.stop()
107
+
108
+
109
+ def test_context_can_be_attached_to_server() -> None:
110
+ ctx1 = Context()
111
+ ctx2 = Context()
112
+
113
+ server1 = start_server(port=0, context=ctx1)
114
+ server2 = start_server(port=0, context=ctx2)
115
+
116
+ ch1 = Channel("/1", context=ctx1)
117
+ ch2 = Channel("/2", context=ctx2)
118
+ ch1.log("test")
119
+ ch2.log("test")
120
+
121
+ server1.stop()
122
+ server2.stop()
123
+
124
+
125
+ @typing.no_type_check
126
+ def test_server_with_invalid_playback_time_range() -> None:
127
+ with pytest.raises(TypeError):
128
+ # Tuple of a single element
129
+ start_server(port=0, playback_time_range=(123,))
130
+
131
+ with pytest.raises(TypeError):
132
+ # Tuple with invalid types
133
+ start_server(port=0, playback_time_range=("not-a-time", None))
134
+
135
+ with pytest.raises(TypeError):
136
+ # Not a tuple
137
+ start_server(port=0, playback_time_range=23443)
138
+
139
+ with pytest.raises(TypeError):
140
+ # Tuple with too many elements
141
+ start_server(port=0, playback_time_range=(123, 456, 789))