koi-net 1.0.0b11__py3-none-any.whl → 1.0.0b13__py3-none-any.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 koi-net might be problematic. Click here for more details.
- koi_net/config.py +95 -0
- koi_net/core.py +125 -125
- koi_net/identity.py +41 -69
- koi_net/network/graph.py +127 -127
- koi_net/network/interface.py +275 -275
- koi_net/network/request_handler.py +148 -148
- koi_net/network/response_handler.py +58 -58
- koi_net/processor/default_handlers.py +162 -162
- koi_net/processor/handler.py +59 -59
- koi_net/processor/interface.py +302 -298
- koi_net/processor/knowledge_object.py +122 -122
- koi_net/protocol/api_models.py +46 -46
- koi_net/protocol/consts.py +6 -6
- koi_net/protocol/edge.py +20 -20
- koi_net/protocol/event.py +50 -50
- koi_net/protocol/helpers.py +24 -24
- koi_net/protocol/node.py +16 -16
- {koi_net-1.0.0b11.dist-info → koi_net-1.0.0b13.dist-info}/METADATA +1 -1
- koi_net-1.0.0b13.dist-info/RECORD +25 -0
- {koi_net-1.0.0b11.dist-info → koi_net-1.0.0b13.dist-info}/licenses/LICENSE +21 -21
- koi_net-1.0.0b11.dist-info/RECORD +0 -24
- {koi_net-1.0.0b11.dist-info → koi_net-1.0.0b13.dist-info}/WHEEL +0 -0
koi_net/network/graph.py
CHANGED
|
@@ -1,127 +1,127 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
from typing import Literal
|
|
3
|
-
import networkx as nx
|
|
4
|
-
from rid_lib import RIDType
|
|
5
|
-
from rid_lib.ext import Cache
|
|
6
|
-
from rid_lib.types import KoiNetEdge, KoiNetNode
|
|
7
|
-
from ..identity import NodeIdentity
|
|
8
|
-
from ..protocol.edge import EdgeProfile, EdgeStatus
|
|
9
|
-
from ..protocol.node import NodeProfile
|
|
10
|
-
|
|
11
|
-
logger = logging.getLogger(__name__)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class NetworkGraph:
|
|
15
|
-
"""Graph functions for this node's view of its network."""
|
|
16
|
-
|
|
17
|
-
cache: Cache
|
|
18
|
-
identity: NodeIdentity
|
|
19
|
-
dg: nx.DiGraph
|
|
20
|
-
|
|
21
|
-
def __init__(self, cache: Cache, identity: NodeIdentity):
|
|
22
|
-
self.cache = cache
|
|
23
|
-
self.dg = nx.DiGraph()
|
|
24
|
-
self.identity = identity
|
|
25
|
-
|
|
26
|
-
def generate(self):
|
|
27
|
-
"""Generates directed graph from cached KOI nodes and edges."""
|
|
28
|
-
logger.debug("Generating network graph")
|
|
29
|
-
self.dg.clear()
|
|
30
|
-
for rid in self.cache.list_rids():
|
|
31
|
-
if type(rid) == KoiNetNode:
|
|
32
|
-
self.dg.add_node(rid)
|
|
33
|
-
logger.debug(f"Added node {rid}")
|
|
34
|
-
|
|
35
|
-
elif type(rid) == KoiNetEdge:
|
|
36
|
-
edge_profile = self.get_edge_profile(rid)
|
|
37
|
-
if not edge_profile:
|
|
38
|
-
logger.warning(f"Failed to load {rid!r}")
|
|
39
|
-
continue
|
|
40
|
-
self.dg.add_edge(edge_profile.source, edge_profile.target, rid=rid)
|
|
41
|
-
logger.debug(f"Added edge {rid} ({edge_profile.source} -> {edge_profile.target})")
|
|
42
|
-
logger.debug("Done")
|
|
43
|
-
|
|
44
|
-
def get_node_profile(self, rid: KoiNetNode) -> NodeProfile | None:
|
|
45
|
-
"""Returns node profile given its RID."""
|
|
46
|
-
bundle = self.cache.read(rid)
|
|
47
|
-
if bundle:
|
|
48
|
-
return bundle.validate_contents(NodeProfile)
|
|
49
|
-
|
|
50
|
-
def get_edge_profile(
|
|
51
|
-
self,
|
|
52
|
-
rid: KoiNetEdge | None = None,
|
|
53
|
-
source: KoiNetNode | None = None,
|
|
54
|
-
target: KoiNetNode | None = None,
|
|
55
|
-
) -> EdgeProfile | None:
|
|
56
|
-
"""Returns edge profile given its RID, or source and target node RIDs."""
|
|
57
|
-
if source and target:
|
|
58
|
-
if (source, target) not in self.dg.edges: return
|
|
59
|
-
edge_data = self.dg.get_edge_data(source, target)
|
|
60
|
-
if not edge_data: return
|
|
61
|
-
rid = edge_data.get("rid")
|
|
62
|
-
if not rid: return
|
|
63
|
-
elif not rid:
|
|
64
|
-
raise ValueError("Either 'rid' or 'source' and 'target' must be provided")
|
|
65
|
-
|
|
66
|
-
bundle = self.cache.read(rid)
|
|
67
|
-
if bundle:
|
|
68
|
-
return bundle.validate_contents(EdgeProfile)
|
|
69
|
-
|
|
70
|
-
def get_edges(
|
|
71
|
-
self,
|
|
72
|
-
direction: Literal["in", "out"] | None = None,
|
|
73
|
-
) -> list[KoiNetEdge]:
|
|
74
|
-
"""Returns edges this node belongs to.
|
|
75
|
-
|
|
76
|
-
All edges returned by default, specify `direction` to restrict to incoming or outgoing edges only."""
|
|
77
|
-
|
|
78
|
-
edges = []
|
|
79
|
-
if direction != "in" and self.dg.out_edges:
|
|
80
|
-
out_edges = self.dg.out_edges(self.identity.rid)
|
|
81
|
-
edges.extend([e for e in out_edges])
|
|
82
|
-
|
|
83
|
-
if direction != "out" and self.dg.in_edges:
|
|
84
|
-
in_edges = self.dg.in_edges(self.identity.rid)
|
|
85
|
-
edges.extend([e for e in in_edges])
|
|
86
|
-
|
|
87
|
-
edge_rids = []
|
|
88
|
-
for edge in edges:
|
|
89
|
-
edge_data = self.dg.get_edge_data(*edge)
|
|
90
|
-
if not edge_data: continue
|
|
91
|
-
edge_rid = edge_data.get("rid")
|
|
92
|
-
if not edge_rid: continue
|
|
93
|
-
edge_rids.append(edge_rid)
|
|
94
|
-
|
|
95
|
-
return edge_rids
|
|
96
|
-
|
|
97
|
-
def get_neighbors(
|
|
98
|
-
self,
|
|
99
|
-
direction: Literal["in", "out"] | None = None,
|
|
100
|
-
status: EdgeStatus | None = None,
|
|
101
|
-
allowed_type: RIDType | None = None
|
|
102
|
-
) -> list[KoiNetNode]:
|
|
103
|
-
"""Returns neighboring nodes this node shares an edge with.
|
|
104
|
-
|
|
105
|
-
All neighboring nodes returned by default, specify `direction` to restrict to neighbors connected by incoming or outgoing edges only."""
|
|
106
|
-
|
|
107
|
-
neighbors = []
|
|
108
|
-
for edge_rid in self.get_edges(direction):
|
|
109
|
-
edge_profile = self.get_edge_profile(edge_rid)
|
|
110
|
-
|
|
111
|
-
if not edge_profile:
|
|
112
|
-
logger.warning(f"Failed to find edge {edge_rid!r} in cache")
|
|
113
|
-
continue
|
|
114
|
-
|
|
115
|
-
if status and edge_profile.status != status:
|
|
116
|
-
continue
|
|
117
|
-
|
|
118
|
-
if allowed_type and allowed_type not in edge_profile.rid_types:
|
|
119
|
-
continue
|
|
120
|
-
|
|
121
|
-
if edge_profile.target == self.identity.rid:
|
|
122
|
-
neighbors.append(edge_profile.source)
|
|
123
|
-
elif edge_profile.source == self.identity.rid:
|
|
124
|
-
neighbors.append(edge_profile.target)
|
|
125
|
-
|
|
126
|
-
return list(neighbors)
|
|
127
|
-
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Literal
|
|
3
|
+
import networkx as nx
|
|
4
|
+
from rid_lib import RIDType
|
|
5
|
+
from rid_lib.ext import Cache
|
|
6
|
+
from rid_lib.types import KoiNetEdge, KoiNetNode
|
|
7
|
+
from ..identity import NodeIdentity
|
|
8
|
+
from ..protocol.edge import EdgeProfile, EdgeStatus
|
|
9
|
+
from ..protocol.node import NodeProfile
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class NetworkGraph:
|
|
15
|
+
"""Graph functions for this node's view of its network."""
|
|
16
|
+
|
|
17
|
+
cache: Cache
|
|
18
|
+
identity: NodeIdentity
|
|
19
|
+
dg: nx.DiGraph
|
|
20
|
+
|
|
21
|
+
def __init__(self, cache: Cache, identity: NodeIdentity):
|
|
22
|
+
self.cache = cache
|
|
23
|
+
self.dg = nx.DiGraph()
|
|
24
|
+
self.identity = identity
|
|
25
|
+
|
|
26
|
+
def generate(self):
|
|
27
|
+
"""Generates directed graph from cached KOI nodes and edges."""
|
|
28
|
+
logger.debug("Generating network graph")
|
|
29
|
+
self.dg.clear()
|
|
30
|
+
for rid in self.cache.list_rids():
|
|
31
|
+
if type(rid) == KoiNetNode:
|
|
32
|
+
self.dg.add_node(rid)
|
|
33
|
+
logger.debug(f"Added node {rid}")
|
|
34
|
+
|
|
35
|
+
elif type(rid) == KoiNetEdge:
|
|
36
|
+
edge_profile = self.get_edge_profile(rid)
|
|
37
|
+
if not edge_profile:
|
|
38
|
+
logger.warning(f"Failed to load {rid!r}")
|
|
39
|
+
continue
|
|
40
|
+
self.dg.add_edge(edge_profile.source, edge_profile.target, rid=rid)
|
|
41
|
+
logger.debug(f"Added edge {rid} ({edge_profile.source} -> {edge_profile.target})")
|
|
42
|
+
logger.debug("Done")
|
|
43
|
+
|
|
44
|
+
def get_node_profile(self, rid: KoiNetNode) -> NodeProfile | None:
|
|
45
|
+
"""Returns node profile given its RID."""
|
|
46
|
+
bundle = self.cache.read(rid)
|
|
47
|
+
if bundle:
|
|
48
|
+
return bundle.validate_contents(NodeProfile)
|
|
49
|
+
|
|
50
|
+
def get_edge_profile(
|
|
51
|
+
self,
|
|
52
|
+
rid: KoiNetEdge | None = None,
|
|
53
|
+
source: KoiNetNode | None = None,
|
|
54
|
+
target: KoiNetNode | None = None,
|
|
55
|
+
) -> EdgeProfile | None:
|
|
56
|
+
"""Returns edge profile given its RID, or source and target node RIDs."""
|
|
57
|
+
if source and target:
|
|
58
|
+
if (source, target) not in self.dg.edges: return
|
|
59
|
+
edge_data = self.dg.get_edge_data(source, target)
|
|
60
|
+
if not edge_data: return
|
|
61
|
+
rid = edge_data.get("rid")
|
|
62
|
+
if not rid: return
|
|
63
|
+
elif not rid:
|
|
64
|
+
raise ValueError("Either 'rid' or 'source' and 'target' must be provided")
|
|
65
|
+
|
|
66
|
+
bundle = self.cache.read(rid)
|
|
67
|
+
if bundle:
|
|
68
|
+
return bundle.validate_contents(EdgeProfile)
|
|
69
|
+
|
|
70
|
+
def get_edges(
|
|
71
|
+
self,
|
|
72
|
+
direction: Literal["in", "out"] | None = None,
|
|
73
|
+
) -> list[KoiNetEdge]:
|
|
74
|
+
"""Returns edges this node belongs to.
|
|
75
|
+
|
|
76
|
+
All edges returned by default, specify `direction` to restrict to incoming or outgoing edges only."""
|
|
77
|
+
|
|
78
|
+
edges = []
|
|
79
|
+
if direction != "in" and self.dg.out_edges:
|
|
80
|
+
out_edges = self.dg.out_edges(self.identity.rid)
|
|
81
|
+
edges.extend([e for e in out_edges])
|
|
82
|
+
|
|
83
|
+
if direction != "out" and self.dg.in_edges:
|
|
84
|
+
in_edges = self.dg.in_edges(self.identity.rid)
|
|
85
|
+
edges.extend([e for e in in_edges])
|
|
86
|
+
|
|
87
|
+
edge_rids = []
|
|
88
|
+
for edge in edges:
|
|
89
|
+
edge_data = self.dg.get_edge_data(*edge)
|
|
90
|
+
if not edge_data: continue
|
|
91
|
+
edge_rid = edge_data.get("rid")
|
|
92
|
+
if not edge_rid: continue
|
|
93
|
+
edge_rids.append(edge_rid)
|
|
94
|
+
|
|
95
|
+
return edge_rids
|
|
96
|
+
|
|
97
|
+
def get_neighbors(
|
|
98
|
+
self,
|
|
99
|
+
direction: Literal["in", "out"] | None = None,
|
|
100
|
+
status: EdgeStatus | None = None,
|
|
101
|
+
allowed_type: RIDType | None = None
|
|
102
|
+
) -> list[KoiNetNode]:
|
|
103
|
+
"""Returns neighboring nodes this node shares an edge with.
|
|
104
|
+
|
|
105
|
+
All neighboring nodes returned by default, specify `direction` to restrict to neighbors connected by incoming or outgoing edges only."""
|
|
106
|
+
|
|
107
|
+
neighbors = []
|
|
108
|
+
for edge_rid in self.get_edges(direction):
|
|
109
|
+
edge_profile = self.get_edge_profile(edge_rid)
|
|
110
|
+
|
|
111
|
+
if not edge_profile:
|
|
112
|
+
logger.warning(f"Failed to find edge {edge_rid!r} in cache")
|
|
113
|
+
continue
|
|
114
|
+
|
|
115
|
+
if status and edge_profile.status != status:
|
|
116
|
+
continue
|
|
117
|
+
|
|
118
|
+
if allowed_type and allowed_type not in edge_profile.rid_types:
|
|
119
|
+
continue
|
|
120
|
+
|
|
121
|
+
if edge_profile.target == self.identity.rid:
|
|
122
|
+
neighbors.append(edge_profile.source)
|
|
123
|
+
elif edge_profile.source == self.identity.rid:
|
|
124
|
+
neighbors.append(edge_profile.target)
|
|
125
|
+
|
|
126
|
+
return list(neighbors)
|
|
127
|
+
|