koi-net 1.0.0b12__py3-none-any.whl → 1.0.0b14__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 +22 -22
- koi_net/identity.py +9 -37
- koi_net/network/interface.py +16 -14
- koi_net/processor/interface.py +7 -3
- {koi_net-1.0.0b12.dist-info → koi_net-1.0.0b14.dist-info}/METADATA +4 -2
- {koi_net-1.0.0b12.dist-info → koi_net-1.0.0b14.dist-info}/RECORD +9 -8
- {koi_net-1.0.0b12.dist-info → koi_net-1.0.0b14.dist-info}/WHEEL +0 -0
- {koi_net-1.0.0b12.dist-info → koi_net-1.0.0b14.dist-info}/licenses/LICENSE +0 -0
koi_net/config.py
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from typing import TypeVar
|
|
3
|
+
from ruamel.yaml import YAML
|
|
4
|
+
from koi_net.protocol.node import NodeProfile
|
|
5
|
+
from rid_lib.types import KoiNetNode
|
|
6
|
+
from pydantic import BaseModel, Field, PrivateAttr
|
|
7
|
+
from dotenv import load_dotenv
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ServerConfig(BaseModel):
|
|
11
|
+
host: str | None = "127.0.0.1"
|
|
12
|
+
port: int | None = 8000
|
|
13
|
+
path: str | None = "/koi-net"
|
|
14
|
+
|
|
15
|
+
@property
|
|
16
|
+
def url(self):
|
|
17
|
+
return f"http://{self.host}:{self.port}{self.path or ''}"
|
|
18
|
+
|
|
19
|
+
class KoiNetConfig(BaseModel):
|
|
20
|
+
node_name: str
|
|
21
|
+
node_rid: KoiNetNode | None = None
|
|
22
|
+
node_profile: NodeProfile
|
|
23
|
+
|
|
24
|
+
cache_directory_path: str | None = ".rid_cache"
|
|
25
|
+
event_queues_path: str | None = "event_queues.json"
|
|
26
|
+
|
|
27
|
+
first_contact: str | None = None
|
|
28
|
+
|
|
29
|
+
class EnvConfig(BaseModel):
|
|
30
|
+
def __init__(self, **kwargs):
|
|
31
|
+
super().__init__(**kwargs)
|
|
32
|
+
load_dotenv()
|
|
33
|
+
|
|
34
|
+
def __getattribute__(self, name):
|
|
35
|
+
value = super().__getattribute__(name)
|
|
36
|
+
if name in type(self).model_fields:
|
|
37
|
+
env_val = os.getenv(value)
|
|
38
|
+
if env_val is None:
|
|
39
|
+
raise ValueError(f"Required environment variable {value} not set")
|
|
40
|
+
return env_val
|
|
41
|
+
return value
|
|
42
|
+
|
|
43
|
+
class Config(BaseModel):
|
|
44
|
+
server: ServerConfig | None = Field(default_factory=ServerConfig)
|
|
45
|
+
koi_net: KoiNetConfig
|
|
46
|
+
_file_path: str = PrivateAttr(default="config.yaml")
|
|
47
|
+
_file_content: str | None = PrivateAttr(default=None)
|
|
48
|
+
|
|
49
|
+
@classmethod
|
|
50
|
+
def load_from_yaml(
|
|
51
|
+
cls,
|
|
52
|
+
file_path: str | None = None,
|
|
53
|
+
generate_missing: bool = True
|
|
54
|
+
):
|
|
55
|
+
yaml = YAML()
|
|
56
|
+
|
|
57
|
+
try:
|
|
58
|
+
with open(file_path, "r") as f:
|
|
59
|
+
file_content = f.read()
|
|
60
|
+
config_data = yaml.load(file_content)
|
|
61
|
+
config = cls.model_validate(config_data)
|
|
62
|
+
config._file_content = file_content
|
|
63
|
+
|
|
64
|
+
except FileNotFoundError:
|
|
65
|
+
config = cls()
|
|
66
|
+
|
|
67
|
+
config._file_path = file_path
|
|
68
|
+
|
|
69
|
+
if generate_missing:
|
|
70
|
+
config.koi_net.node_rid = (
|
|
71
|
+
config.koi_net.node_rid or KoiNetNode.generate(config.koi_net.node_name)
|
|
72
|
+
)
|
|
73
|
+
config.koi_net.node_profile.base_url = (
|
|
74
|
+
config.koi_net.node_profile.base_url or config.server.url
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
config.save_to_yaml()
|
|
78
|
+
|
|
79
|
+
return config
|
|
80
|
+
|
|
81
|
+
def save_to_yaml(self):
|
|
82
|
+
yaml = YAML()
|
|
83
|
+
|
|
84
|
+
with open(self._file_path, "w") as f:
|
|
85
|
+
try:
|
|
86
|
+
config_data = self.model_dump(mode="json")
|
|
87
|
+
yaml.dump(config_data, f)
|
|
88
|
+
except Exception as e:
|
|
89
|
+
if self._file_content:
|
|
90
|
+
f.seek(0)
|
|
91
|
+
f.truncate()
|
|
92
|
+
f.write(self._file_content)
|
|
93
|
+
raise e
|
|
94
|
+
|
|
95
|
+
ConfigType = TypeVar("ConfigType", bound=Config)
|
koi_net/core.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
from typing import Generic
|
|
2
3
|
import httpx
|
|
3
4
|
from rid_lib.ext import Cache, Bundle
|
|
4
5
|
from .network import NetworkInterface
|
|
@@ -6,45 +7,43 @@ from .processor import ProcessorInterface
|
|
|
6
7
|
from .processor import default_handlers
|
|
7
8
|
from .processor.handler import KnowledgeHandler
|
|
8
9
|
from .identity import NodeIdentity
|
|
9
|
-
from .protocol.node import NodeProfile
|
|
10
10
|
from .protocol.event import Event, EventType
|
|
11
|
+
from .config import ConfigType
|
|
11
12
|
|
|
12
13
|
logger = logging.getLogger(__name__)
|
|
13
14
|
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
|
|
17
|
+
class NodeInterface(Generic[ConfigType]):
|
|
18
|
+
config: ConfigType
|
|
16
19
|
cache: Cache
|
|
17
20
|
identity: NodeIdentity
|
|
18
21
|
network: NetworkInterface
|
|
19
22
|
processor: ProcessorInterface
|
|
20
|
-
|
|
23
|
+
|
|
21
24
|
use_kobj_processor_thread: bool
|
|
22
25
|
|
|
23
26
|
def __init__(
|
|
24
27
|
self,
|
|
25
|
-
|
|
26
|
-
profile: NodeProfile,
|
|
27
|
-
identity_file_path: str = "identity.json",
|
|
28
|
-
event_queues_file_path: str = "event_queues.json",
|
|
29
|
-
cache_directory_path: str = "rid_cache",
|
|
28
|
+
config: ConfigType,
|
|
30
29
|
use_kobj_processor_thread: bool = False,
|
|
31
|
-
|
|
30
|
+
|
|
32
31
|
handlers: list[KnowledgeHandler] | None = None,
|
|
32
|
+
|
|
33
33
|
cache: Cache | None = None,
|
|
34
34
|
network: NetworkInterface | None = None,
|
|
35
35
|
processor: ProcessorInterface | None = None
|
|
36
36
|
):
|
|
37
|
-
self.
|
|
37
|
+
self.config: ConfigType = config
|
|
38
|
+
self.cache = cache or Cache(
|
|
39
|
+
self.config.koi_net.cache_directory_path)
|
|
40
|
+
|
|
38
41
|
self.identity = NodeIdentity(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
file_path=identity_file_path
|
|
43
|
-
)
|
|
44
|
-
self.first_contact = first_contact
|
|
42
|
+
config=self.config,
|
|
43
|
+
cache=self.cache)
|
|
44
|
+
|
|
45
45
|
self.network = network or NetworkInterface(
|
|
46
|
-
|
|
47
|
-
first_contact=self.first_contact,
|
|
46
|
+
config=self.config,
|
|
48
47
|
cache=self.cache,
|
|
49
48
|
identity=self.identity
|
|
50
49
|
)
|
|
@@ -58,13 +57,14 @@ class NodeInterface:
|
|
|
58
57
|
|
|
59
58
|
self.use_kobj_processor_thread = use_kobj_processor_thread
|
|
60
59
|
self.processor = processor or ProcessorInterface(
|
|
60
|
+
config=self.config,
|
|
61
61
|
cache=self.cache,
|
|
62
62
|
network=self.network,
|
|
63
63
|
identity=self.identity,
|
|
64
64
|
use_kobj_processor_thread=self.use_kobj_processor_thread,
|
|
65
65
|
default_handlers=handlers
|
|
66
66
|
)
|
|
67
|
-
|
|
67
|
+
|
|
68
68
|
def start(self) -> None:
|
|
69
69
|
"""Starts a node, call this method first.
|
|
70
70
|
|
|
@@ -91,8 +91,8 @@ class NodeInterface:
|
|
|
91
91
|
self.processor.flush_kobj_queue()
|
|
92
92
|
logger.debug("Done")
|
|
93
93
|
|
|
94
|
-
if not self.network.graph.get_neighbors() and self.first_contact:
|
|
95
|
-
logger.debug(f"I don't have any neighbors, reaching out to first contact {self.first_contact}")
|
|
94
|
+
if not self.network.graph.get_neighbors() and self.config.koi_net.first_contact:
|
|
95
|
+
logger.debug(f"I don't have any neighbors, reaching out to first contact {self.config.koi_net.first_contact}")
|
|
96
96
|
|
|
97
97
|
events = [
|
|
98
98
|
Event.from_rid(EventType.FORGET, self.identity.rid),
|
|
@@ -101,7 +101,7 @@ class NodeInterface:
|
|
|
101
101
|
|
|
102
102
|
try:
|
|
103
103
|
self.network.request_handler.broadcast_events(
|
|
104
|
-
url=self.first_contact,
|
|
104
|
+
url=self.config.koi_net.first_contact,
|
|
105
105
|
events=events
|
|
106
106
|
)
|
|
107
107
|
|
koi_net/identity.py
CHANGED
|
@@ -1,30 +1,24 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from pydantic import BaseModel
|
|
3
2
|
from rid_lib.ext.bundle import Bundle
|
|
4
3
|
from rid_lib.ext.cache import Cache
|
|
5
4
|
from rid_lib.types.koi_net_node import KoiNetNode
|
|
5
|
+
|
|
6
|
+
from .config import Config
|
|
6
7
|
from .protocol.node import NodeProfile
|
|
7
8
|
|
|
8
9
|
logger = logging.getLogger(__name__)
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
class NodeIdentityModel(BaseModel):
|
|
12
|
-
rid: KoiNetNode
|
|
13
|
-
profile: NodeProfile
|
|
14
11
|
|
|
15
12
|
class NodeIdentity:
|
|
16
13
|
"""Represents a node's identity (RID, profile, bundle)."""
|
|
17
14
|
|
|
18
|
-
|
|
19
|
-
file_path: str
|
|
15
|
+
config: Config
|
|
20
16
|
cache: Cache
|
|
21
17
|
|
|
22
18
|
def __init__(
|
|
23
|
-
self,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
cache: Cache,
|
|
27
|
-
file_path: str = "identity.json"
|
|
19
|
+
self,
|
|
20
|
+
config: Config,
|
|
21
|
+
cache: Cache
|
|
28
22
|
):
|
|
29
23
|
"""Initializes node identity from a name and profile.
|
|
30
24
|
|
|
@@ -32,38 +26,16 @@ class NodeIdentity:
|
|
|
32
26
|
|
|
33
27
|
WARNING: If the name is changed, the RID will be overwritten which will have consequences for the rest of the network.
|
|
34
28
|
"""
|
|
29
|
+
self.config = config
|
|
35
30
|
self.cache = cache
|
|
36
|
-
self.file_path = file_path
|
|
37
|
-
|
|
38
|
-
self._identity = None
|
|
39
|
-
try:
|
|
40
|
-
with open(file_path, "r") as f:
|
|
41
|
-
self._identity = NodeIdentityModel.model_validate_json(f.read())
|
|
42
|
-
|
|
43
|
-
except FileNotFoundError:
|
|
44
|
-
pass
|
|
45
|
-
|
|
46
|
-
if self._identity:
|
|
47
|
-
if self._identity.rid.name != name:
|
|
48
|
-
logger.warning("Node name changed which will change this node's RID, if you really want to do this manually delete the identity JSON file")
|
|
49
|
-
if self._identity.profile != profile:
|
|
50
|
-
self._identity.profile = profile
|
|
51
|
-
else:
|
|
52
|
-
self._identity = NodeIdentityModel(
|
|
53
|
-
rid=KoiNetNode.generate(name),
|
|
54
|
-
profile=profile,
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
with open(file_path, "w") as f:
|
|
58
|
-
f.write(self._identity.model_dump_json(indent=2))
|
|
59
31
|
|
|
60
32
|
@property
|
|
61
33
|
def rid(self) -> KoiNetNode:
|
|
62
|
-
return self.
|
|
34
|
+
return self.config.koi_net.node_rid
|
|
63
35
|
|
|
64
36
|
@property
|
|
65
37
|
def profile(self) -> NodeProfile:
|
|
66
|
-
return self.
|
|
38
|
+
return self.config.koi_net.node_profile
|
|
67
39
|
|
|
68
40
|
@property
|
|
69
41
|
def bundle(self) -> Bundle:
|
koi_net/network/interface.py
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from queue import Queue
|
|
3
|
+
from typing import Generic
|
|
3
4
|
import httpx
|
|
4
5
|
from pydantic import BaseModel
|
|
5
6
|
from rid_lib import RID
|
|
6
7
|
from rid_lib.core import RIDType
|
|
7
8
|
from rid_lib.ext import Cache
|
|
8
9
|
from rid_lib.types import KoiNetNode
|
|
10
|
+
|
|
9
11
|
from .graph import NetworkGraph
|
|
10
12
|
from .request_handler import RequestHandler
|
|
11
13
|
from .response_handler import ResponseHandler
|
|
@@ -13,6 +15,7 @@ from ..protocol.node import NodeType
|
|
|
13
15
|
from ..protocol.edge import EdgeType
|
|
14
16
|
from ..protocol.event import Event
|
|
15
17
|
from ..identity import NodeIdentity
|
|
18
|
+
from ..config import Config, ConfigType
|
|
16
19
|
|
|
17
20
|
logger = logging.getLogger(__name__)
|
|
18
21
|
|
|
@@ -23,33 +26,30 @@ class EventQueueModel(BaseModel):
|
|
|
23
26
|
|
|
24
27
|
type EventQueue = dict[RID, Queue[Event]]
|
|
25
28
|
|
|
26
|
-
class NetworkInterface:
|
|
29
|
+
class NetworkInterface(Generic[ConfigType]):
|
|
27
30
|
"""A collection of functions and classes to interact with the KOI network."""
|
|
28
31
|
|
|
32
|
+
config: ConfigType
|
|
29
33
|
identity: NodeIdentity
|
|
30
34
|
cache: Cache
|
|
31
|
-
first_contact: str | None
|
|
32
35
|
graph: NetworkGraph
|
|
33
36
|
request_handler: RequestHandler
|
|
34
37
|
response_handler: ResponseHandler
|
|
35
38
|
poll_event_queue: EventQueue
|
|
36
39
|
webhook_event_queue: EventQueue
|
|
37
|
-
event_queues_file_path: str
|
|
38
40
|
|
|
39
41
|
def __init__(
|
|
40
42
|
self,
|
|
41
|
-
|
|
42
|
-
first_contact: str | None,
|
|
43
|
+
config: ConfigType,
|
|
43
44
|
cache: Cache,
|
|
44
45
|
identity: NodeIdentity
|
|
45
46
|
):
|
|
47
|
+
self.config = config
|
|
46
48
|
self.identity = identity
|
|
47
49
|
self.cache = cache
|
|
48
|
-
self.first_contact = first_contact
|
|
49
50
|
self.graph = NetworkGraph(cache, identity)
|
|
50
51
|
self.request_handler = RequestHandler(cache, self.graph)
|
|
51
52
|
self.response_handler = ResponseHandler(cache)
|
|
52
|
-
self.event_queues_file_path = file_path
|
|
53
53
|
|
|
54
54
|
self.poll_event_queue = dict()
|
|
55
55
|
self.webhook_event_queue = dict()
|
|
@@ -58,7 +58,7 @@ class NetworkInterface:
|
|
|
58
58
|
def _load_event_queues(self):
|
|
59
59
|
"""Loads event queues from storage."""
|
|
60
60
|
try:
|
|
61
|
-
with open(self.
|
|
61
|
+
with open(self.config.koi_net.event_queues_path, "r") as f:
|
|
62
62
|
queues = EventQueueModel.model_validate_json(f.read())
|
|
63
63
|
|
|
64
64
|
for node in queues.poll.keys():
|
|
@@ -92,7 +92,7 @@ class NetworkInterface:
|
|
|
92
92
|
if len(events_model.poll) == 0 and len(events_model.webhook) == 0:
|
|
93
93
|
return
|
|
94
94
|
|
|
95
|
-
with open(self.
|
|
95
|
+
with open(self.config.koi_net.event_queues_path, "w") as f:
|
|
96
96
|
f.write(events_model.model_dump_json(indent=2))
|
|
97
97
|
|
|
98
98
|
def push_event_to(self, event: Event, node: KoiNetNode, flush=False):
|
|
@@ -171,10 +171,12 @@ class NetworkInterface:
|
|
|
171
171
|
|
|
172
172
|
try:
|
|
173
173
|
self.request_handler.broadcast_events(node, events=events)
|
|
174
|
+
return True
|
|
174
175
|
except httpx.ConnectError:
|
|
175
|
-
logger.warning("Broadcast failed,
|
|
176
|
+
logger.warning("Broadcast failed, dropping node")
|
|
176
177
|
for event in events:
|
|
177
178
|
self.push_event_to(event, node)
|
|
179
|
+
return False
|
|
178
180
|
|
|
179
181
|
def get_state_providers(self, rid_type: RIDType) -> list[KoiNetNode]:
|
|
180
182
|
"""Returns list of node RIDs which provide state for the specified RID type."""
|
|
@@ -238,18 +240,18 @@ class NetworkInterface:
|
|
|
238
240
|
|
|
239
241
|
neighbors = self.graph.get_neighbors()
|
|
240
242
|
|
|
241
|
-
if not neighbors and self.first_contact:
|
|
243
|
+
if not neighbors and self.config.koi_net.first_contact:
|
|
242
244
|
logger.debug("No neighbors found, polling first contact")
|
|
243
245
|
try:
|
|
244
246
|
payload = self.request_handler.poll_events(
|
|
245
|
-
url=self.first_contact,
|
|
247
|
+
url=self.config.koi_net.first_contact,
|
|
246
248
|
rid=self.identity.rid
|
|
247
249
|
)
|
|
248
250
|
if payload.events:
|
|
249
|
-
logger.debug(f"Received {len(payload.events)} events from '{self.first_contact}'")
|
|
251
|
+
logger.debug(f"Received {len(payload.events)} events from '{self.config.koi_net.first_contact}'")
|
|
250
252
|
return payload.events
|
|
251
253
|
except httpx.ConnectError:
|
|
252
|
-
logger.debug(f"Failed to reach first contact '{self.first_contact}'")
|
|
254
|
+
logger.debug(f"Failed to reach first contact '{self.config.koi_net.first_contact}'")
|
|
253
255
|
|
|
254
256
|
events = []
|
|
255
257
|
for node_rid in neighbors:
|
koi_net/processor/interface.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import queue
|
|
3
3
|
import threading
|
|
4
|
-
from typing import Callable
|
|
4
|
+
from typing import Callable, Generic
|
|
5
5
|
from rid_lib.core import RID, RIDType
|
|
6
6
|
from rid_lib.ext import Bundle, Cache, Manifest
|
|
7
7
|
from rid_lib.types.koi_net_edge import KoiNetEdge
|
|
@@ -9,6 +9,7 @@ from rid_lib.types.koi_net_node import KoiNetNode
|
|
|
9
9
|
from ..identity import NodeIdentity
|
|
10
10
|
from ..network import NetworkInterface
|
|
11
11
|
from ..protocol.event import Event, EventType
|
|
12
|
+
from ..config import Config
|
|
12
13
|
from .handler import (
|
|
13
14
|
KnowledgeHandler,
|
|
14
15
|
HandlerType,
|
|
@@ -24,9 +25,10 @@ from .knowledge_object import (
|
|
|
24
25
|
logger = logging.getLogger(__name__)
|
|
25
26
|
|
|
26
27
|
|
|
27
|
-
class ProcessorInterface:
|
|
28
|
+
class ProcessorInterface():
|
|
28
29
|
"""Provides access to this node's knowledge processing pipeline."""
|
|
29
30
|
|
|
31
|
+
config: Config
|
|
30
32
|
cache: Cache
|
|
31
33
|
network: NetworkInterface
|
|
32
34
|
identity: NodeIdentity
|
|
@@ -36,13 +38,15 @@ class ProcessorInterface:
|
|
|
36
38
|
worker_thread: threading.Thread | None = None
|
|
37
39
|
|
|
38
40
|
def __init__(
|
|
39
|
-
self,
|
|
41
|
+
self,
|
|
42
|
+
config: Config,
|
|
40
43
|
cache: Cache,
|
|
41
44
|
network: NetworkInterface,
|
|
42
45
|
identity: NodeIdentity,
|
|
43
46
|
use_kobj_processor_thread: bool,
|
|
44
47
|
default_handlers: list[KnowledgeHandler] = []
|
|
45
48
|
):
|
|
49
|
+
self.config = config
|
|
46
50
|
self.cache = cache
|
|
47
51
|
self.network = network
|
|
48
52
|
self.identity = identity
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: koi-net
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.0b14
|
|
4
4
|
Summary: Implementation of KOI-net protocol in Python
|
|
5
5
|
Project-URL: Homepage, https://github.com/BlockScience/koi-net/
|
|
6
6
|
Author-email: Luke Miller <luke@block.science>
|
|
@@ -30,7 +30,9 @@ Requires-Python: >=3.10
|
|
|
30
30
|
Requires-Dist: httpx>=0.28.1
|
|
31
31
|
Requires-Dist: networkx>=3.4.2
|
|
32
32
|
Requires-Dist: pydantic>=2.10.6
|
|
33
|
-
Requires-Dist:
|
|
33
|
+
Requires-Dist: python-dotenv>=1.1.0
|
|
34
|
+
Requires-Dist: rid-lib>=3.2.3
|
|
35
|
+
Requires-Dist: ruamel-yaml>=0.18.10
|
|
34
36
|
Provides-Extra: dev
|
|
35
37
|
Requires-Dist: build; extra == 'dev'
|
|
36
38
|
Requires-Dist: twine>=6.0; extra == 'dev'
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
koi_net/__init__.py,sha256=b0Ze0pZmJAuygpWUFHM6Kvqo3DkU_uzmkptv1EpAArw,31
|
|
2
|
-
koi_net/
|
|
3
|
-
koi_net/
|
|
2
|
+
koi_net/config.py,sha256=4Lglj9mz9i4ratUXypdrLTuI1RHUOYeal9n8RKdVP7A,2911
|
|
3
|
+
koi_net/core.py,sha256=IO8kqiNMYVeuNzilq7eHBA7IulsxRjrCbWnIAx6_abA,4406
|
|
4
|
+
koi_net/identity.py,sha256=Ro6iGw9DMc4KrLJyqejtdh9l872nCoCGc5ioF9OptJc,1276
|
|
4
5
|
koi_net/network/__init__.py,sha256=r_RN-q_mDYC-2RAkN-lJoMUX76TXyfEUc_MVKW87z0g,39
|
|
5
6
|
koi_net/network/graph.py,sha256=dsfPuHUTkCzlj0QeL0e7dgp7-FR5_AGP7eE8EpBPhC0,4710
|
|
6
|
-
koi_net/network/interface.py,sha256
|
|
7
|
+
koi_net/network/interface.py,sha256=DhMbVjKp9xdZReKldHWh72jkhd3RS_Q4XeNqg42mwyM,10474
|
|
7
8
|
koi_net/network/request_handler.py,sha256=66gjX2x4UnBWZYwKLjp_3WkhL-ekhR3VAyfGviHTcUs,4790
|
|
8
9
|
koi_net/network/response_handler.py,sha256=CAwici2Etj9ESndERXdtYkMlc4gWHz_xc7jHgY2Qjcg,1830
|
|
9
10
|
koi_net/processor/__init__.py,sha256=x4fAY0hvQEDcpfdTB3POIzxBQjYAtn0qQazPo1Xm0m4,41
|
|
10
11
|
koi_net/processor/default_handlers.py,sha256=vfQNvucQR5zANyYhdLnc3kOXGFrgNtq5swd-vH7n0Uo,6810
|
|
11
12
|
koi_net/processor/handler.py,sha256=7X6M6PP8m6-xdtsP1y4QO83g_MN5VSszNNikprITK80,2523
|
|
12
|
-
koi_net/processor/interface.py,sha256=
|
|
13
|
+
koi_net/processor/interface.py,sha256=Ecy0XWW7KfuDBFt7fXEmag4CzHP768mtO4uRZWNZN4E,13000
|
|
13
14
|
koi_net/processor/knowledge_object.py,sha256=RCgzkILsWm1Jw_NkSu4jTRYA9Ugga6mJ4jqKWwketQs,4090
|
|
14
15
|
koi_net/protocol/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
16
|
koi_net/protocol/api_models.py,sha256=DYDKCRD2Uja633bBAyTsaxyb1oF9pX9yQ9NpNAbkczo,1070
|
|
@@ -18,7 +19,7 @@ koi_net/protocol/edge.py,sha256=CcmvIY4P1HEBdKNJ4wFRDmwYMRMss24Besmbi7ZRFxQ,427
|
|
|
18
19
|
koi_net/protocol/event.py,sha256=HxzLN-iCXPyr2YzrswMIkgZYeUdFbBpa5v98dAB06lQ,1328
|
|
19
20
|
koi_net/protocol/helpers.py,sha256=8ZkQrjb_G0QEaMIKe9wkFOBonl1bkmemx_pwKMwIiLg,695
|
|
20
21
|
koi_net/protocol/node.py,sha256=2HhCh3LdBLlY2Z_kXNmKHzpVLKbP_ODob3HjHayFQtM,375
|
|
21
|
-
koi_net-1.0.
|
|
22
|
-
koi_net-1.0.
|
|
23
|
-
koi_net-1.0.
|
|
24
|
-
koi_net-1.0.
|
|
22
|
+
koi_net-1.0.0b14.dist-info/METADATA,sha256=98NmBhai3c88c5UJf459u3GnyAdDTJ0jlzUwO3iVZsc,34203
|
|
23
|
+
koi_net-1.0.0b14.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
24
|
+
koi_net-1.0.0b14.dist-info/licenses/LICENSE,sha256=03mgCL5qth2aD9C3F3qNVs4sFJSpK9kjtYCyOwdSp7s,1069
|
|
25
|
+
koi_net-1.0.0b14.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|