Skip to content

Commit c72b046

Browse files
committed
tests are running
1 parent 2cac9e6 commit c72b046

File tree

12 files changed

+210
-112
lines changed

12 files changed

+210
-112
lines changed

.vscode/settings.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"python.testing.pytestEnabled": true,
3+
"python.testing.cwd": ".",
4+
"python.analysis.logLevel": "Information",
5+
"python.testing.nosetestsEnabled": false,
6+
"python.testing.unittestEnabled": false,
7+
}

olink/clientnode.py

Lines changed: 16 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from olink.core.protocol import Protocol
66

77

8-
class InvokeReplyArg(ProtocolType):
8+
class InvokeReplyArg:
99
def __init__(self, name: str, value: Any):
1010
self.name = name
1111
self.value = value
@@ -33,6 +33,9 @@ def olink_on_release(self) -> None:
3333
class SinkToClientEntry:
3434
sink: IObjectSink = None
3535
node: "ClientNode" = None
36+
def __init__(self, sink=None):
37+
self.sink = sink
38+
self.node = None
3639

3740

3841
class ClientRegistry(Base):
@@ -46,12 +49,7 @@ def detach_client_node(self, node: "ClientNode"):
4649
entry.node = None
4750

4851
def link_client_node(self, name: str, node: "ClientNode"):
49-
resource = Name.resource_from_name(name)
50-
self.init_entry(resource)
51-
if not self.entries[resource].node:
52-
self.entries[resource].node = node
53-
else:
54-
self.emit_log(LogLevel.DEBUG, f"link node failed, sink has already a node: {resource}")
52+
self.entry(name).node = node
5553

5654
def unlink_client_node(self, name: str, node: "ClientNode"):
5755
resource = Name.resource_from_name(name)
@@ -62,55 +60,30 @@ def unlink_client_node(self, name: str, node: "ClientNode"):
6260
self.emit_log(LogLevel.DEBUG, f"unlink node failed, not the same node: {resource}")
6361

6462
def add_object_sink(self, sink: IObjectSink) -> "ClientNode":
65-
resource = Name.resource_from_name(sink.olink_object_name())
66-
self.init_entry(resource)
67-
if not self.entries[resource].sink:
68-
self.entries[resource].sink = sink
69-
else:
70-
self.emit_log(LogLevel.DEBUG, f"add object sink failed: sink already added: {resource}")
71-
return self.entries[resource].node
63+
name = sink.olink_object_name()
64+
self.entry(name).sink = sink
7265

7366
def remove_object_sink(self, sink: IObjectSink):
74-
resource = Name.resource_from_name(sink.olink_object_name())
75-
if self.entries[resource].sink:
76-
del self.entries[resource]
77-
else:
78-
self.emit_log(LogLevel.DEBUG, f"remove object sink failed: no sink to remove {resource}")
67+
name = sink.olink_object_name()
68+
self.remove_entry(name)
7969

8070
def get_object_sink(self, name: str) -> Optional[IObjectSink]:
81-
resource = Name.resource_from_name(name)
82-
if resource in self.entries:
83-
sink = self.entries[resource].sink
84-
if not sink:
85-
self.emit_log(LogLevel.DEBUG, f"no sink attached {resource}")
86-
return sink
87-
else:
88-
self.emit_log(LogLevel.DEBUG, f"no resource: {resource}")
89-
return None
71+
return self.entry(name).sink
9072

9173
def get_client_node(self, name: str) -> Optional["ClientNode"]:
92-
resource = Name.resource_from_name(name)
93-
if resource in self.entries:
94-
node = self.entries[resource].node
95-
if not node:
96-
self.emit_log(LogLevel.DEBUG, f"no node attached {resource}")
97-
return node
98-
else:
99-
self.emit_log(LogLevel.DEBUG, f"no resource: {resource}")
100-
return None
74+
return self.entry(name).node
10175

10276
def entry(self, name: str) -> SinkToClientEntry:
10377
resource = Name.resource_from_name(name)
78+
if not resource in self.entries:
79+
self.emit_log(LogLevel.DEBUG, f"add new resource: {resource}")
80+
self.entries[resource] = SinkToClientEntry()
10481
return self.entries[resource]
10582

106-
def has_entry(self, name: str) -> bool:
83+
def remove_entry(self, name: str) -> None:
10784
resource = Name.resource_from_name(name)
108-
return resource in self.entries
85+
del self.entries[resource]
10986

110-
def init_entry(self, name: str):
111-
resource = Name.resource_from_name(name)
112-
if resource not in self.entries:
113-
self.entries[resource] = SinkToClientEntry()
11487

11588

11689

olink/core/protocol.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,31 @@
33
from .types import Base, LogLevel, MsgType
44

55
class IProtocolListener(ProptocolType):
6-
def handle_link(name: str) -> None:
6+
def handle_link(self, name: str) -> None:
77
raise NotImplementedError()
88

9-
def handle_unlink(name: str) -> None:
9+
def handle_unlink(self, name: str) -> None:
1010
raise NotImplementedError()
1111

12-
def handle_init(name: str, props: object) -> None:
12+
def handle_init(self, name: str, props: object) -> None:
1313
raise NotImplementedError()
1414

15-
def handle_set_property(name: str, value: Any) -> None:
15+
def handle_set_property(self, name: str, value: Any) -> None:
1616
raise NotImplementedError()
1717

18-
def handle_property_change(name: str, value: Any) -> None:
18+
def handle_property_change(self, name: str, value: Any) -> None:
1919
raise NotImplementedError()
2020

21-
def handle_invoke(id: int, name: str, args: list[Any]) -> None:
21+
def handle_invoke(self, id: int, name: str, args: list[Any]) -> None:
2222
raise NotImplementedError()
2323

24-
def handle_invoke_reply(id: int, name: str, value: Any) -> None:
24+
def handle_invoke_reply(self, id: int, name: str, value: Any) -> None:
2525
raise NotImplementedError()
2626

27-
def handle_signal(name: str, args: Any) -> None:
27+
def handle_signal(self, name: str, args: Any) -> None:
2828
raise NotImplementedError()
2929

30-
def handle_error(msgType: int, id: int, error: str) -> None:
30+
def handle_error(self, msgType: int, id: int, error: str) -> None:
3131
raise NotImplementedError()
3232

3333
class Protocol(Base):

olink/core/types.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
from enum import Enum
1+
from enum import IntEnum
22
from typing import Any, Callable
33
from typing import Protocol as ProptocolType
44
import json
55

6-
class MsgType(Enum):
6+
class MsgType(IntEnum):
77
LINK = 10,
88
INIT = 11,
99
UNLINK = 12,
@@ -14,7 +14,7 @@ class MsgType(Enum):
1414
SIGNAL = 40,
1515
ERROR = 90,
1616

17-
class MessageFormat(Enum):
17+
class MessageFormat(IntEnum):
1818
JSON = 1,
1919
BSON = 2,
2020
MSGPACK = 3,
@@ -26,7 +26,7 @@ def resource_from_name(name: str) -> str:
2626
return name.split('/')[0]
2727
@staticmethod
2828
def path_from_name(name: str) -> str:
29-
return name.split('/')[:-1]
29+
return name.split('/')[-1]
3030
@staticmethod
3131
def has_path(name: str) -> bool:
3232
return '/' in name
@@ -39,9 +39,9 @@ class MessageConverter:
3939
format: MessageFormat = MessageFormat.JSON
4040
def __init__(self, format: MessageFormat):
4141
self.format = format
42-
def from_string(message: str) -> list[Any]:
42+
def from_string(self, message: str) -> list[Any]:
4343
return json.loads(message)
44-
def to_string(data: list[Any]) -> str:
44+
def to_string(self, data: list[Any]) -> str:
4545
return json.dumps(data)
4646

4747
WriteMessageFunc = Callable[[str], None]
@@ -64,7 +64,7 @@ def log(level: LogLevel, msg: str) -> None:
6464
class Base:
6565
log_func: WriteLogFunc = None
6666

67-
def onLog(self, func: WriteLogFunc):
67+
def on_log(self, func: WriteLogFunc):
6868
self.log_func = func
6969

7070
def emit_log(self, level: LogLevel, msg: str):

olink/mocks/mocksink.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def __init__(self, name: str):
1414
def invoke(self, name: str, args: list[Any]):
1515
if self.node:
1616
def func(arg: InvokeReplyArg):
17-
self.events.append({'type': 'invoke', 'name': arg.name, 'value': arg.value})
17+
self.events.append({'type': 'invoke-reply', 'name': arg.name, 'value': arg.value})
1818
self.node.invoke_remote(name, args, func)
1919

2020
def olink_object_name(self) -> str:
@@ -23,8 +23,8 @@ def olink_object_name(self) -> str:
2323
def olink_on_signal(self, name: str, args: list[Any]) -> None:
2424
self.events.append({'type': 'signal', 'name': name, 'args': args})
2525

26-
def olink_property_change(self, name: str, value: Any) -> None:
27-
path = Name.pathFromName(name)
26+
def olink_on_property_changed(self, name: str, value: Any) -> None:
27+
path = Name.path_from_name(name)
2828
self.events.append({ 'type': 'property_change', 'name': name, 'value': value})
2929
self.properties[path] = value
3030

olink/mocks/mocksource.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ class MockSource(IObjectSource):
99
node: RemoteNode = None
1010

1111
def __init__(self, name: str):
12-
super().__init__(self)
1312
self.name = name
13+
RemoteNode.add_object_source(self)
1414

1515
def set_property(self, name: str, value: Any):
1616
if self.node:
@@ -30,10 +30,17 @@ def olink_invoke(self, name: str, args: list[Any]):
3030
def olink_set_property(self, name: str, value: Any):
3131
path = Name.path_from_name(name)
3232
self.events.append({'type': 'set_property', 'name': name, 'value': value})
33-
if self.properties[path] != value:
33+
if not path in self.properties:
34+
# assign new value
3435
self.properties[path] = value
3536
if self.node:
3637
self.node.notify_property_change(name, value)
38+
else:
39+
# update existing value
40+
if not self.properties[path] == value:
41+
self.properties[path] = value
42+
if self.node:
43+
self.node.notify_property_change(name, value)
3744

3845
def olink_linked(self, name: str, node: RemoteNode):
3946
self.events.append({'type': 'linked', 'name': name})

olink/remotenode.py

Lines changed: 43 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from olink.core.types import Base, LogLevel, Name
33
from olink.core.node import BaseNode
44

5-
from typing import Any, Callable, Optional, Protocol as ProtocolType
5+
from typing import Any, Protocol as ProtocolType
66

77
class IObjectSource(ProtocolType):
88
def olink_object_name() -> str:
@@ -25,80 +25,79 @@ class SourceToNodeEntry:
2525
source: IObjectSource = None
2626
nodes: set["RemoteNode"] = set()
2727

28-
def __init__(self, source):
28+
def __init__(self, source=None):
2929
self.source = source
30+
self.nodes = set()
3031

3132

3233

3334
class RemoteRegistry(Base):
3435
entries: dict[str, SourceToNodeEntry] = {}
3536

3637
def add_object_source(self, source: IObjectSource):
37-
resource = Name.resourceFromName(source.olink_object_name())
38-
self.emit_log(LogLevel.DEBUG, f"RemoteRegistry.add_object_source: {resource}")
39-
if not resource in self.entries:
40-
self.entries[resource] = SourceToNodeEntry(source)
41-
else:
42-
self.emit_log(LogLevel.DEBUG, f"source already added: {resource}")
43-
38+
name = source.olink_object_name()
39+
self.emit_log(LogLevel.DEBUG, f"RemoteRegistry.add_object_source: {name}")
40+
self.entry(name).source = source
41+
4442
def remove_object_source(self, source: IObjectSource):
45-
resource = Name.resourceFromName(source.olink_object_name())
46-
self.emit_log(LogLevel.DEBUG, f"RemoteRegistry.remove_object_source: {resource}")
47-
if resource in self.entries:
48-
del self.entries[resource]
49-
else:
50-
self.emit_log(LogLevel.DEBUG, f'remove object source failed, no source exists: {resource}')
43+
name = source.olink_object_name()
44+
self.remove_entry(name)
5145

5246
def get_object_source(self, name: str):
53-
resource = Name.resourceFromName(name)
54-
if resource in self.entries:
55-
source = self.entries[resource].source
56-
if not source:
57-
self.emit_log(LogLevel.DEBUG, f"no source at: {resource}")
58-
return source
59-
else:
60-
self.emit_log(LogLevel.DEBUG, f"no source registered at: {name}")
47+
return self.entry(name).source
6148

6249
def get_remote_nodes(self, name: str):
63-
resource = Name.resourceFromName(name)
64-
if resource in self.entries:
65-
nodes = self.entries[resource].nodes
66-
if not nodes:
67-
self.emit_log(LogLevel.DEBUG, f"no nodes at: {resource}")
68-
return nodes
69-
else:
70-
self.emit_log(LogLevel.DEBUG, f"no source registered at: {name}")
50+
return self.entry(name).nodes
7151

7252
def attach_remote_node(self, node: "RemoteNode"):
7353
self.emit_log(LogLevel.DEBUG, "RemoteRegistry.attach_remote_node")
7454

7555
def detach_remote_node(self, node: "RemoteNode"):
7656
self.emit_log(LogLevel.DEBUG, "RemoteRegistry.detach_remote_node")
77-
for entry in self.entries.items():
57+
for entry in self.entries.values():
7858
if node in entry.nodes:
7959
entry.nodes.remove(node)
8060

8161
def link_remote_node(self, name: str, node: "RemoteNode"):
82-
resource = Name.resourceFromName(name)
83-
self.emit_log(LogLevel.DEBUG, f'RemoteRegistry.link_remote_node: {resource}')
84-
if resource in self.entries:
85-
self.entries[resource].nodes.add(node)
86-
else:
87-
self.emit_log(LogLevel.DEBUG, f"no source registered at: {name}")
62+
self.entry(name).nodes.add(node)
8863

8964
def unlink_remote_node(self, name: str, node: "RemoteNode"):
90-
resource = Name.resourceFromName(name)
91-
self.emit_log(LogLevel.DEBUG, f'RemoteRegistry.unlink_remote_node: {resource}')
65+
self.entry(name).nodes.remove(node)
66+
67+
def entry(self, name: str) -> SourceToNodeEntry:
68+
resource = Name.resource_from_name(name)
69+
if not resource in self.entries:
70+
self.emit_log(LogLevel.DEBUG, f"add new resource: {resource}")
71+
self.entries[resource] = SourceToNodeEntry()
72+
return self.entries[resource]
73+
74+
def remove_entry(self, name: str) -> None:
75+
resource = Name.resource_from_name(name)
9276
if resource in self.entries:
93-
self.entries[resource].nodes.remove(node)
77+
del self.entries[resource]
9478
else:
95-
self.emit_log(LogLevel.DEBUG, f"no source registered at: {name}")
79+
self.emit_log(LogLevel.DEBUG, f'remove resource failed, resource not exists: {resource}')
80+
81+
82+
def has_entry(self, name: str) -> SourceToNodeEntry:
83+
resource = Name.resource_from_name(name)
84+
return resource in self.entries
85+
86+
def init_entry(self, name: str):
87+
resource = Name.resource_from_name(name)
88+
if resource in self.entries:
89+
self.entries[resource] = SourceToNodeEntry()
90+
91+
92+
93+
def clear(self):
94+
self.entries = {}
9695

9796
_registry = RemoteRegistry()
9897

9998
class RemoteNode(BaseNode):
10099
def __init__(self):
101-
super().__init__(self)
100+
super().__init__()
102101
_registry.attach_remote_node(self)
103102

104103
def detach(self):
@@ -131,7 +130,7 @@ def handle_unlink(self, name: str):
131130
if source:
132131
self.registry().unlink_remote_node(name, self)
133132

134-
def handle_set_properties(self, name: str, value: Any):
133+
def handle_set_property(self, name: str, value: Any):
135134
source = self.get_object_source(name)
136135
if source:
137136
source.olink_set_property(name, value)

tests/__init__.py

Whitespace-only changes.
File renamed without changes.

0 commit comments

Comments
 (0)