Skip to content

Commit 3e8dbc0

Browse files
committed
many: pass data directly to event handler & add more tests for subscribe object
1 parent 6cf469e commit 3e8dbc0

File tree

2 files changed

+79
-19
lines changed

2 files changed

+79
-19
lines changed

tests/codec_test.py

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
from typing import Type, TypeVar, Any
55

66
import capnp
7+
import pytest
78
from google.protobuf.message import Message
89

910
from xconn.client import connect_anonymous
1011
from xconn import codec
11-
from xconn.types import Event
1212
from tests.schemas.profile_pb2 import ProfileCreate, ProfileGet
1313

1414

@@ -82,12 +82,63 @@ def test_pubsub_object():
8282
session = connect_anonymous("ws://localhost:8080/ws", "realm1")
8383
session.set_payload_codec(Base64Codec())
8484

85-
def event_handler(event: Event):
86-
assert event.args[0] == "hello"
85+
def event_handler(data: String):
86+
assert data == "hello"
8787

88-
session.subscribe_object("io.xconn.object", event_handler, String)
88+
session.subscribe_object("io.xconn.object", event_handler)
8989

90-
session.publish_object("io.xconn.object", String("hello"))
90+
session.publish_object("io.xconn.object", String("hello"), {"acknowledge": True})
91+
92+
session.leave()
93+
94+
95+
def test_subscribe_object_without_codec():
96+
session = connect_anonymous("ws://localhost:8080/ws", "realm1")
97+
98+
def event_handler(user: ProfileCreate):
99+
pass
100+
101+
with pytest.raises(ValueError, match="no payload codec set"):
102+
session.subscribe_object("io.xconn.object", event_handler)
103+
104+
session.leave()
105+
106+
107+
def test_subscribe_object_without_args():
108+
session = connect_anonymous("ws://localhost:8080/ws", "realm1")
109+
session.set_payload_codec(Base64Codec())
110+
111+
def event_handler():
112+
pass
113+
114+
with pytest.raises(ValueError, match="event handler must accept 1 argument"):
115+
session.subscribe_object("io.xconn.object", event_handler)
116+
117+
session.leave()
118+
119+
120+
def test_subscribe_object_with_multiple_args():
121+
session = connect_anonymous("ws://localhost:8080/ws", "realm1")
122+
session.set_payload_codec(ProtobufCodec())
123+
124+
def event_handler(user: ProfileCreate, a):
125+
pass
126+
127+
with pytest.raises(ValueError, match="event handler must accept 1 argument"):
128+
session.subscribe_object("io.xconn.object", event_handler)
129+
130+
session.leave()
131+
132+
133+
def test_subscribe_object_without_annotation():
134+
session = connect_anonymous("ws://localhost:8080/ws", "realm1")
135+
session.set_payload_codec(ProtobufCodec())
136+
137+
def event_handler(user):
138+
pass
139+
140+
with pytest.raises(TypeError, match="event handler parameter must have a type annotation"):
141+
session.subscribe_object("io.xconn.object", event_handler)
91142

92143
session.leave()
93144

@@ -96,16 +147,15 @@ def test_pubsub_protobuf():
96147
session = connect_anonymous("ws://localhost:8080/ws", "realm1")
97148
session.set_payload_codec(ProtobufCodec())
98149

99-
def event_handler(event: Event):
100-
user: ProfileCreate = event.args[0]
150+
def event_handler(user: ProfileCreate):
101151
assert user.username == "john"
102152
assert user.email == "[email protected]"
103153
assert user.age == 25
104154

105-
session.subscribe_object("io.xconn.object", event_handler, ProfileCreate)
155+
session.subscribe_object("io.xconn.object", event_handler)
106156

107157
create_msg = ProfileCreate(username="john", email="[email protected]", age=25)
108-
session.publish_object("io.xconn.object", create_msg)
158+
session.publish_object("io.xconn.object", create_msg, {"acknowledge": True})
109159

110160
session.leave()
111161

@@ -239,19 +289,18 @@ def test_pubsub_capnproto():
239289
session = connect_anonymous("ws://localhost:8080/ws", "realm1")
240290
session.set_payload_codec(CapnpProtoCodec())
241291

242-
def event_handler(event: Event):
243-
user: UserCreate = event.args[0]
292+
def event_handler(user: UserCreate):
244293
assert user.name == "alice"
245294
assert user.email == "[email protected]"
246295
assert user.age == 21
247296

248-
session.subscribe_object("io.xconn.object", event_handler, UserCreate)
297+
session.subscribe_object("io.xconn.object", event_handler)
249298

250299
new_user = UserCreate.new_message()
251300
new_user.name = "alice"
252301
new_user.email = "[email protected]"
253302
new_user.age = 21
254303

255-
session.publish_object("io.xconn.object", new_user)
304+
session.publish_object("io.xconn.object", new_user, {"acknowledge": True})
256305

257306
session.leave()

xconn/session.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -195,26 +195,37 @@ def call_object(self, procedure: str, request: TReq = None, return_type: Type[TR
195195

196196
return None
197197

198-
def subscribe_object(self, topic: str, event_handler: Callable[[types.Event], None], return_type: Type[TRes]):
198+
def subscribe_object(self, topic: str, event_handler: Callable[[TReq], None]):
199199
if self._payload_codec is None:
200200
raise ValueError("no payload codec set")
201201

202+
sig = inspect.signature(event_handler)
203+
204+
params = list(sig.parameters.values())
205+
if len(params) != 1:
206+
raise ValueError("event handler must accept 1 argument")
207+
208+
param_type = params[0].annotation
209+
if param_type is inspect._empty:
210+
raise TypeError("event handler parameter must have a type annotation")
211+
202212
def _event_handler(event: types.Event):
203-
if len(event.args) != 1:
213+
if len(event.args) != 1 or len(event.kwargs) != 0:
204214
raise ValueError("only one argument expected in event")
205215

206216
data = event.args[0]
207-
d = self._payload_codec.decode(data, return_type)
208-
event_handler(types.Event(args=[d], kwargs={}, details={}))
217+
request_obj = self._payload_codec.decode(data, param_type)
218+
event_handler(request_obj)
209219

210220
return self.subscribe(topic, _event_handler)
211221

212-
def publish_object(self, topic: str, request: TReq):
222+
def publish_object(self, topic: str, request: TReq, options: dict[str, Any] | None = None):
213223
if self._payload_codec is None:
214224
raise ValueError("no payload codec set")
215225

216226
encoded = self._payload_codec.encode(request)
217-
return self.publish(topic, [encoded])
227+
228+
return self.publish(topic, [encoded], options=options)
218229

219230
def register_object(
220231
self,

0 commit comments

Comments
 (0)