Skip to content

Commit 1a73c67

Browse files
committed
test observable properties with synchronous ZMQ client, async already works in test with HTTP protocol binding
1 parent bc5c5cf commit 1a73c67

File tree

3 files changed

+97
-100
lines changed

3 files changed

+97
-100
lines changed

hololinked/client/factory.py

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -55,28 +55,28 @@ def zmq(self, server_id: str, thing_id: str, protocol: str, **kwargs):
5555
execution_timeout=object_proxy.execution_timeout,
5656
)
5757
self.add_property(object_proxy, consumed_property)
58-
# if hasattr(affordance, "observable") and affordance.observable:
59-
# sync_event_client = EventConsumer(
60-
# id=f"{TD['id']}|{affordance.name}|sync",
61-
# event_unique_identifier=affordance.zmq_unique_identifier,
62-
# socket_address=affordance.zmq_socket_address,
63-
# logger=object_proxy.logger
64-
# )
65-
# async_event_client = AsyncEventConsumer(
66-
# id=f"{TD['id']}|{affordance.name}|async",
67-
# event_unique_identifier=affordance.zmq_unique_identifier,
68-
# socket_address=affordance.zmq_socket_address,
69-
# logger=object_proxy.logger
70-
# )
71-
# consumed_observable = ZMQEvent(
72-
# resource=affordance,
73-
# sync_zmq_client=sync_event_client,
74-
# async_zmq_client=async_event_client,
75-
# owner_inst=object_proxy,
76-
# invokation_timeout=object_proxy.invokation_timeout,
77-
# execution_timeout=object_proxy.execution_timeout,
78-
# )
79-
# self.add_event(object_proxy, consumed_observable)
58+
if hasattr(affordance, "observable") and affordance.observable:
59+
sync_event_client = EventConsumer(
60+
id=f"{TD['id']}|{affordance.name}|sync",
61+
event_unique_identifier=affordance.zmq_unique_identifier,
62+
socket_address=affordance.zmq_socket_address,
63+
logger=object_proxy.logger
64+
)
65+
async_event_client = AsyncEventConsumer(
66+
id=f"{TD['id']}|{affordance.name}|async",
67+
event_unique_identifier=affordance.zmq_unique_identifier,
68+
socket_address=affordance.zmq_socket_address,
69+
logger=object_proxy.logger
70+
)
71+
consumed_observable = ZMQEvent(
72+
resource=affordance,
73+
sync_zmq_client=sync_event_client,
74+
async_zmq_client=async_event_client,
75+
owner_inst=object_proxy,
76+
invokation_timeout=object_proxy.invokation_timeout,
77+
execution_timeout=object_proxy.execution_timeout,
78+
)
79+
self.add_event(object_proxy, consumed_observable)
8080
for action in TD.get("actions", []):
8181
affordance = ActionAffordance.from_TD(action, TD)
8282
consumed_action = ZMQAction(

hololinked/td/interaction_affordance.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,8 @@ class PropertyAffordance(DataSchema, InteractionAffordance):
243243
"""
244244
# [Supported Fields]() <br>
245245
observable: Optional[bool] = None
246+
zmq_unique_identifier: Optional[str] = None
247+
zmq_socket_address: Optional[str] = None
246248

247249
def __init__(self):
248250
super().__init__()
@@ -256,7 +258,13 @@ def build(self) -> None:
256258
self.ds_build_from_property(property)
257259
if property.observable:
258260
self.observable = property.observable
259-
261+
observable_event_descriptor = property._observable_event_descriptor
262+
event_dispatcher = getattr(self.owner, observable_event_descriptor.name, None) # type: EventDispatcher
263+
if event_dispatcher:
264+
self.zmq_unique_identifier = event_dispatcher._unique_identifier
265+
self.zmq_socket_address = event_dispatcher.publisher.socket_address
266+
267+
260268
@classmethod
261269
def generate(cls, property, owner = None):
262270
assert isinstance(property, Property), f"property must be instance of Property, given type {type(property)}"

tests/test_12_protocols_zmq_object_proxy.py

Lines changed: 66 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -168,82 +168,73 @@ def cb(value):
168168
self.assertEqual(len(results), 100)
169169
thing.unsubscribe_event("test_event")
170170

171-
# def test_05_observe_properties(self):
172-
# thing = ClientFactory.zmq("test-thing", "test-thing", "IPC")
173-
# self.assertIsInstance(thing, ObjectProxy)
174-
175-
# # First check if an attribute is set on the object proxy
176-
# self.assertIsNotNone(thing, "observable_list_prop_change_event")
177-
# self.assertIsNotNone(thing, "observable_readonly_prop_change_event")
178-
179-
# event_count = 0
180-
# def callback(value):
181-
# nonlocal event_count
182-
# event_count += 1
183-
# self.assertIsInstance(value, list)
184-
185-
# thing.observe_property("observable_list_prop", callback)
186-
# thing.write_property("observable_list_prop", fake.pylist(25, value_types=[int, float, str, bool]))
187-
# thing.write_property("observable_list_prop", fake.pylist(25, value_types=[int, float, str, bool]))
188-
# self.assertEqual(event_count, 2)
189-
# self.assertEqual(thing.observable_list_prop, fake.last)
190-
191-
# # req 1 - observable events come due to writing a property
192-
# propective_values = [
193-
# [1, 2, 3, 4, 5],
194-
# ['a', 'b', 'c', 'd', 'e'],
195-
# [1, 'a', 2, 'b', 3]
196-
# ]
197-
# result = []
198-
# attempt = 0
199-
# def cb(value):
200-
# nonlocal attempt, result
201-
# self.assertEqual(value, propective_values[attempt])
202-
# result.append(value)
203-
# attempt += 1
204-
205-
# self.thing_client.subscribe_event('observable_list_prop_change_event', cb)
206-
# time.sleep(3)
207-
# # Calm down for event publisher to connect fully as there is no handshake for events
208-
# for value in propective_values:
209-
# self.thing_client.observable_list_prop = value
210-
211-
# for i in range(20):
212-
# if attempt == len(propective_values):
213-
# break
214-
# # wait for the callback to be called
215-
# time.sleep(0.1)
216-
# self.thing_client.unsubscribe_event('observable_list_prop_change_event')
217-
218-
# self.assertEqual(result, propective_values)
171+
172+
def test_06_observe_properties(self):
173+
thing = ClientFactory.zmq("test-thing", "test-thing", "IPC")
174+
self.assertIsInstance(thing, ObjectProxy)
175+
176+
# First check if an attribute is set on the object proxy
177+
self.assertIsNotNone(thing, "observable_list_prop_change_event")
178+
self.assertIsNotNone(thing, "observable_readonly_prop_change_event")
179+
180+
# req 1 - observable events come due to writing a property
181+
propective_values = [
182+
[1, 2, 3, 4, 5],
183+
['a', 'b', 'c', 'd', 'e'],
184+
[1, 'a', 2, 'b', 3]
185+
]
186+
result = []
187+
attempt = 0
188+
def cb(value):
189+
nonlocal attempt, result
190+
self.assertEqual(value, propective_values[attempt])
191+
result.append(value)
192+
attempt += 1
193+
194+
thing.observe_property('observable_list_prop', cb)
195+
time.sleep(3)
196+
# Calm down for event publisher to connect fully as there is no handshake for events
197+
for value in propective_values:
198+
thing.observable_list_prop = value
199+
200+
for i in range(20):
201+
if attempt == len(propective_values):
202+
break
203+
# wait for the callback to be called
204+
time.sleep(0.1)
205+
thing.unobserve_property('observable_list_prop')
206+
207+
for res in result:
208+
self.assertIn(res, propective_values)
219209

220210
# # req 2 - observable events come due to reading a property
221-
# propective_values = [1, 2, 3, 4, 5]
222-
# result = []
223-
# attempt = 0
224-
# def cb(value):
225-
# nonlocal attempt, result
226-
# self.assertEqual(value, propective_values[attempt])
227-
# result.append(value)
228-
# attempt += 1
229-
230-
# self.thing_client.subscribe_event('observable_readonly_prop_change_event', cb)
231-
# time.sleep(3)
232-
# # Calm down for event publisher to connect fully as there is no handshake for events
233-
# for _ in propective_values:
234-
# self.thing_client.observable_readonly_prop
235-
236-
# for i in range(20):
237-
# if attempt == len(propective_values):
238-
# break
239-
# # wait for the callback to be called
240-
# time.sleep(0.1)
241-
242-
# self.thing_client.unsubscribe_event('observable_readonly_prop_change_event')
243-
# self.assertEqual(result, propective_values)
244-
245-
246-
def test_06_stop(self):
211+
propective_values = [1, 2, 3, 4, 5]
212+
result = []
213+
attempt = 0
214+
def cb(value):
215+
nonlocal attempt, result
216+
self.assertEqual(value, propective_values[attempt])
217+
result.append(value)
218+
attempt += 1
219+
220+
thing.observe_property('observable_readonly_prop', cb)
221+
time.sleep(3)
222+
# Calm down for event publisher to connect fully as there is no handshake for events
223+
for _ in propective_values:
224+
thing.observable_readonly_prop # read property through do notation access
225+
226+
for i in range(20):
227+
if attempt == len(propective_values):
228+
break
229+
# wait for the callback to be called
230+
time.sleep(0.1)
231+
232+
thing.unobserve_property('observable_readonly_prop')
233+
for res in result:
234+
self.assertIn(res, propective_values)
235+
236+
237+
def test_07_stop(self):
247238
"""Test the stop of the zmq object proxy client"""
248239
self.thing.rpc_server.stop()
249240

@@ -304,12 +295,10 @@ async def test_04_stop(self):
304295

305296

306297

307-
308-
309298
def load_tests(loader, tests, pattern):
310299
suite = unittest.TestSuite()
311300
suite.addTest(unittest.TestLoader().loadTestsFromTestCase(TestZMQObjectProxyClient))
312-
# suite.addTest(unittest.TestLoader().loadTestsFromTestCase(TestZMQObjectProxyClientAsync))
301+
suite.addTest(unittest.TestLoader().loadTestsFromTestCase(TestZMQObjectProxyClientAsync))
313302
return suite
314303

315304
if __name__ == '__main__':

0 commit comments

Comments
 (0)