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.
- foxglove/__init__.py +245 -124
- foxglove/_foxglove_py/__init__.pyi +233 -167
- foxglove/_foxglove_py/channels.pyi +2792 -2580
- foxglove/_foxglove_py/cloud.pyi +9 -0
- foxglove/_foxglove_py/mcap.pyi +125 -84
- foxglove/_foxglove_py/schemas.pyi +1009 -839
- foxglove/_foxglove_py/schemas_wkt.pyi +85 -77
- foxglove/_foxglove_py/websocket.pyi +394 -343
- foxglove/_foxglove_py.cp312-win32.pyd +0 -0
- foxglove/benchmarks/test_mcap_serialization.py +160 -160
- foxglove/channel.py +241 -234
- foxglove/channels/__init__.py +94 -90
- foxglove/cloud.py +61 -0
- foxglove/mcap.py +12 -12
- foxglove/notebook/__init__.py +0 -0
- foxglove/notebook/foxglove_widget.py +100 -0
- foxglove/notebook/notebook_buffer.py +114 -0
- foxglove/schemas/__init__.py +163 -155
- foxglove/tests/test_channel.py +243 -215
- foxglove/tests/test_context.py +10 -0
- foxglove/tests/test_logging.py +62 -16
- foxglove/tests/test_mcap.py +477 -116
- foxglove/tests/test_parameters.py +178 -154
- foxglove/tests/test_schemas.py +17 -0
- foxglove/tests/test_server.py +141 -110
- foxglove/tests/test_time.py +137 -137
- foxglove/websocket.py +220 -195
- foxglove_sdk-0.16.3.dist-info/METADATA +53 -0
- foxglove_sdk-0.16.3.dist-info/RECORD +32 -0
- {foxglove_sdk-0.8.1.dist-info → foxglove_sdk-0.16.3.dist-info}/WHEEL +1 -1
- foxglove_sdk-0.8.1.dist-info/METADATA +0 -51
- foxglove_sdk-0.8.1.dist-info/RECORD +0 -25
|
@@ -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.
|
|
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
|
|
30
|
-
assert p.value == ParameterValue.
|
|
31
|
-
assert type(p.get_value()) is
|
|
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.
|
|
43
|
-
ParameterValue.
|
|
44
|
-
ParameterValue.
|
|
45
|
-
]
|
|
46
|
-
)
|
|
47
|
-
assert p.get_value() == v
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def
|
|
51
|
-
v: AnyNativeParameterValue = [
|
|
52
|
-
p = Parameter("
|
|
53
|
-
assert p.name == "
|
|
54
|
-
assert p.type is None
|
|
55
|
-
assert p.value == ParameterValue.Array(
|
|
56
|
-
[
|
|
57
|
-
ParameterValue.
|
|
58
|
-
ParameterValue.
|
|
59
|
-
ParameterValue.
|
|
60
|
-
]
|
|
61
|
-
)
|
|
62
|
-
assert p.get_value() == v
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def
|
|
66
|
-
p = Parameter("
|
|
67
|
-
assert p.name == "
|
|
68
|
-
assert p.type is None
|
|
69
|
-
assert p.value == ParameterValue.
|
|
70
|
-
assert p.get_value()
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
assert p.
|
|
78
|
-
assert p.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
assert p.
|
|
93
|
-
assert p.
|
|
94
|
-
assert p.
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
p
|
|
118
|
-
assert p.
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
)
|
|
136
|
-
assert p.
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
assert p.
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
p = Parameter(
|
|
147
|
-
"bad
|
|
148
|
-
value=ParameterValue.
|
|
149
|
-
type=ParameterType.
|
|
150
|
-
)
|
|
151
|
-
assert p.type == ParameterType.
|
|
152
|
-
assert p.
|
|
153
|
-
|
|
154
|
-
|
|
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
|
foxglove/tests/test_server.py
CHANGED
|
@@ -1,110 +1,141 @@
|
|
|
1
|
-
import time
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
assert
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
assert
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
assert
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
server.
|
|
50
|
-
server.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
server.
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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))
|