koi-net 1.0.0b19__py3-none-any.whl → 1.1.0b1__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 +43 -18
- koi_net/context.py +55 -0
- koi_net/core.py +115 -49
- koi_net/default_actions.py +15 -0
- koi_net/effector.py +139 -0
- koi_net/identity.py +4 -22
- koi_net/network/__init__.py +0 -1
- koi_net/network/behavior.py +42 -0
- koi_net/network/error_handler.py +50 -0
- koi_net/network/{interface.py → event_queue.py} +52 -131
- koi_net/network/graph.py +18 -33
- koi_net/network/request_handler.py +112 -66
- koi_net/network/resolver.py +150 -0
- koi_net/network/response_handler.py +11 -3
- koi_net/processor/__init__.py +0 -1
- koi_net/processor/default_handlers.py +57 -41
- koi_net/processor/handler.py +3 -7
- koi_net/processor/interface.py +15 -214
- koi_net/processor/knowledge_object.py +10 -17
- koi_net/processor/knowledge_pipeline.py +220 -0
- koi_net/protocol/api_models.py +7 -1
- koi_net/protocol/edge.py +23 -1
- koi_net/protocol/envelope.py +54 -0
- koi_net/protocol/errors.py +23 -0
- koi_net/protocol/node.py +2 -1
- koi_net/protocol/secure.py +106 -0
- koi_net/secure.py +117 -0
- {koi_net-1.0.0b19.dist-info → koi_net-1.1.0b1.dist-info}/METADATA +3 -2
- koi_net-1.1.0b1.dist-info/RECORD +35 -0
- koi_net/protocol/helpers.py +0 -25
- koi_net-1.0.0b19.dist-info/RECORD +0 -25
- {koi_net-1.0.0b19.dist-info → koi_net-1.1.0b1.dist-info}/WHEEL +0 -0
- {koi_net-1.0.0b19.dist-info → koi_net-1.1.0b1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from enum import StrEnum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class ErrorTypes(StrEnum):
|
|
5
|
+
UnknownNode = "unknown_node"
|
|
6
|
+
InvalidKey = "invalid_key"
|
|
7
|
+
InvalidSignature = "invalid_signature"
|
|
8
|
+
InvalidTarget = "invalid_target"
|
|
9
|
+
|
|
10
|
+
class ProtocolError(Exception):
|
|
11
|
+
error_type: ErrorTypes
|
|
12
|
+
|
|
13
|
+
class UnknownNodeError(ProtocolError):
|
|
14
|
+
error_type = ErrorTypes.UnknownNode
|
|
15
|
+
|
|
16
|
+
class InvalidKeyError(ProtocolError):
|
|
17
|
+
error_type = ErrorTypes.InvalidKey
|
|
18
|
+
|
|
19
|
+
class InvalidSignatureError(ProtocolError):
|
|
20
|
+
error_type = ErrorTypes.InvalidSignature
|
|
21
|
+
|
|
22
|
+
class InvalidTargetError(ProtocolError):
|
|
23
|
+
error_type = ErrorTypes.InvalidTarget
|
koi_net/protocol/node.py
CHANGED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from base64 import urlsafe_b64decode, urlsafe_b64encode
|
|
3
|
+
from cryptography.hazmat.primitives import hashes
|
|
4
|
+
from cryptography.hazmat.primitives.asymmetric import ec
|
|
5
|
+
from cryptography.hazmat.primitives import serialization
|
|
6
|
+
from rid_lib.ext.utils import sha256_hash
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class PrivateKey:
|
|
12
|
+
priv_key: ec.EllipticCurvePrivateKey
|
|
13
|
+
|
|
14
|
+
def __init__(self, priv_key):
|
|
15
|
+
self.priv_key = priv_key
|
|
16
|
+
|
|
17
|
+
@classmethod
|
|
18
|
+
def generate(cls):
|
|
19
|
+
return cls(priv_key=ec.generate_private_key(ec.SECP192R1()))
|
|
20
|
+
|
|
21
|
+
def public_key(self) -> "PublicKey":
|
|
22
|
+
return PublicKey(self.priv_key.public_key())
|
|
23
|
+
|
|
24
|
+
@classmethod
|
|
25
|
+
def from_pem(cls, priv_key_pem: str, password: str):
|
|
26
|
+
return cls(
|
|
27
|
+
priv_key=serialization.load_pem_private_key(
|
|
28
|
+
data=priv_key_pem.encode(),
|
|
29
|
+
password=password.encode()
|
|
30
|
+
)
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
def to_pem(self, password: str) -> str:
|
|
34
|
+
return self.priv_key.private_bytes(
|
|
35
|
+
encoding=serialization.Encoding.PEM,
|
|
36
|
+
format=serialization.PrivateFormat.PKCS8,
|
|
37
|
+
encryption_algorithm=serialization.BestAvailableEncryption(password.encode())
|
|
38
|
+
).decode()
|
|
39
|
+
|
|
40
|
+
def sign(self, message: bytes) -> str:
|
|
41
|
+
hashed_message = sha256_hash(message.decode())
|
|
42
|
+
|
|
43
|
+
signature = urlsafe_b64encode(
|
|
44
|
+
self.priv_key.sign(
|
|
45
|
+
data=message,
|
|
46
|
+
signature_algorithm=ec.ECDSA(hashes.SHA256())
|
|
47
|
+
)
|
|
48
|
+
).decode()
|
|
49
|
+
|
|
50
|
+
logger.debug(f"Signing message with [{self.public_key().to_der()}]")
|
|
51
|
+
logger.debug(f"hash: {hashed_message}")
|
|
52
|
+
logger.debug(f"signature: {signature}")
|
|
53
|
+
|
|
54
|
+
return signature
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class PublicKey:
|
|
58
|
+
pub_key: ec.EllipticCurvePublicKey
|
|
59
|
+
|
|
60
|
+
def __init__(self, pub_key):
|
|
61
|
+
self.pub_key = pub_key
|
|
62
|
+
|
|
63
|
+
@classmethod
|
|
64
|
+
def from_pem(cls, pub_key_pem: str):
|
|
65
|
+
return cls(
|
|
66
|
+
pub_key=serialization.load_pem_public_key(
|
|
67
|
+
data=pub_key_pem.encode()
|
|
68
|
+
)
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
def to_pem(self) -> str:
|
|
72
|
+
return self.pub_key.public_bytes(
|
|
73
|
+
encoding=serialization.Encoding.PEM,
|
|
74
|
+
format=serialization.PublicFormat.SubjectPublicKeyInfo
|
|
75
|
+
).decode()
|
|
76
|
+
|
|
77
|
+
@classmethod
|
|
78
|
+
def from_der(cls, pub_key_der: str):
|
|
79
|
+
return cls(
|
|
80
|
+
pub_key=serialization.load_der_public_key(
|
|
81
|
+
data=urlsafe_b64decode(pub_key_der)
|
|
82
|
+
)
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
def to_der(self) -> str:
|
|
86
|
+
return urlsafe_b64encode(
|
|
87
|
+
self.pub_key.public_bytes(
|
|
88
|
+
encoding=serialization.Encoding.DER,
|
|
89
|
+
format=serialization.PublicFormat.SubjectPublicKeyInfo
|
|
90
|
+
)
|
|
91
|
+
).decode()
|
|
92
|
+
|
|
93
|
+
def verify(self, signature: str, message: bytes) -> bool:
|
|
94
|
+
hashed_message = sha256_hash(message.decode())
|
|
95
|
+
|
|
96
|
+
logger.debug(f"Verifying message with [{self.to_der()}]")
|
|
97
|
+
logger.debug(f"hash: {hashed_message}")
|
|
98
|
+
logger.debug(f"signature: {signature}")
|
|
99
|
+
|
|
100
|
+
# NOTE: throws cryptography.exceptions.InvalidSignature on failure
|
|
101
|
+
|
|
102
|
+
self.pub_key.verify(
|
|
103
|
+
signature=urlsafe_b64decode(signature),
|
|
104
|
+
data=message,
|
|
105
|
+
signature_algorithm=ec.ECDSA(hashes.SHA256())
|
|
106
|
+
)
|
koi_net/secure.py
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from functools import wraps
|
|
3
|
+
|
|
4
|
+
import cryptography.exceptions
|
|
5
|
+
from rid_lib.ext import Bundle
|
|
6
|
+
from rid_lib.ext.utils import sha256_hash
|
|
7
|
+
from .identity import NodeIdentity
|
|
8
|
+
from .protocol.envelope import UnsignedEnvelope, SignedEnvelope
|
|
9
|
+
from .protocol.secure import PublicKey
|
|
10
|
+
from .protocol.api_models import EventsPayload
|
|
11
|
+
from .protocol.event import EventType
|
|
12
|
+
from .protocol.node import NodeProfile
|
|
13
|
+
from .protocol.secure import PrivateKey
|
|
14
|
+
from .protocol.errors import (
|
|
15
|
+
UnknownNodeError,
|
|
16
|
+
InvalidKeyError,
|
|
17
|
+
InvalidSignatureError,
|
|
18
|
+
InvalidTargetError
|
|
19
|
+
)
|
|
20
|
+
from .effector import Effector
|
|
21
|
+
from .config import NodeConfig
|
|
22
|
+
|
|
23
|
+
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Secure:
|
|
27
|
+
identity: NodeIdentity
|
|
28
|
+
effector: Effector
|
|
29
|
+
config: NodeConfig
|
|
30
|
+
priv_key: PrivateKey
|
|
31
|
+
|
|
32
|
+
def __init__(
|
|
33
|
+
self,
|
|
34
|
+
identity: NodeIdentity,
|
|
35
|
+
effector: Effector,
|
|
36
|
+
config: NodeConfig
|
|
37
|
+
):
|
|
38
|
+
self.identity = identity
|
|
39
|
+
self.effector = effector
|
|
40
|
+
self.config = config
|
|
41
|
+
|
|
42
|
+
self.priv_key = self._load_priv_key()
|
|
43
|
+
|
|
44
|
+
def _load_priv_key(self) -> PrivateKey:
|
|
45
|
+
with open(self.config.koi_net.private_key_pem_path, "r") as f:
|
|
46
|
+
priv_key_pem = f.read()
|
|
47
|
+
|
|
48
|
+
return PrivateKey.from_pem(
|
|
49
|
+
priv_key_pem=priv_key_pem,
|
|
50
|
+
password=self.config.env.priv_key_password
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
def _handle_unknown_node(self, envelope: SignedEnvelope) -> Bundle | None:
|
|
54
|
+
if type(envelope.payload) != EventsPayload:
|
|
55
|
+
return None
|
|
56
|
+
|
|
57
|
+
for event in envelope.payload.events:
|
|
58
|
+
# must be NEW event for bundle of source node's profile
|
|
59
|
+
if event.rid != envelope.source_node:
|
|
60
|
+
continue
|
|
61
|
+
if event.event_type != EventType.NEW:
|
|
62
|
+
continue
|
|
63
|
+
|
|
64
|
+
return event.bundle
|
|
65
|
+
return None
|
|
66
|
+
|
|
67
|
+
def create_envelope(self, payload, target) -> SignedEnvelope:
|
|
68
|
+
return UnsignedEnvelope(
|
|
69
|
+
payload=payload,
|
|
70
|
+
source_node=self.identity.rid,
|
|
71
|
+
target_node=target
|
|
72
|
+
).sign_with(self.priv_key)
|
|
73
|
+
|
|
74
|
+
def validate_envelope(self, envelope: SignedEnvelope):
|
|
75
|
+
node_bundle = (
|
|
76
|
+
self.effector.deref(envelope.source_node) or
|
|
77
|
+
self._handle_unknown_node(envelope)
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
if not node_bundle:
|
|
81
|
+
raise UnknownNodeError(f"Couldn't resolve {envelope.source_node}")
|
|
82
|
+
|
|
83
|
+
node_profile = node_bundle.validate_contents(NodeProfile)
|
|
84
|
+
|
|
85
|
+
# check that public key matches source node RID
|
|
86
|
+
if envelope.source_node.hash != sha256_hash(node_profile.public_key):
|
|
87
|
+
raise InvalidKeyError("Invalid public key on new node!")
|
|
88
|
+
|
|
89
|
+
# check envelope signed by validated public key
|
|
90
|
+
pub_key = PublicKey.from_der(node_profile.public_key)
|
|
91
|
+
try:
|
|
92
|
+
envelope.verify_with(pub_key)
|
|
93
|
+
except cryptography.exceptions.InvalidSignature as err:
|
|
94
|
+
raise InvalidSignatureError(f"Signature {envelope.signature} is invalid.")
|
|
95
|
+
|
|
96
|
+
# check that this node is the target of the envelope
|
|
97
|
+
if envelope.target_node != self.identity.rid:
|
|
98
|
+
raise InvalidTargetError(f"Envelope target {envelope.target_node!r} is not me")
|
|
99
|
+
|
|
100
|
+
def envelope_handler(self, func):
|
|
101
|
+
@wraps(func)
|
|
102
|
+
async def wrapper(req: SignedEnvelope, *args, **kwargs) -> SignedEnvelope | None:
|
|
103
|
+
logger.info("Validating envelope")
|
|
104
|
+
|
|
105
|
+
self.validate_envelope(req)
|
|
106
|
+
logger.info("Calling endpoint handler")
|
|
107
|
+
|
|
108
|
+
result = await func(req, *args, **kwargs)
|
|
109
|
+
|
|
110
|
+
if result is not None:
|
|
111
|
+
logger.info("Creating response envelope")
|
|
112
|
+
return self.create_envelope(
|
|
113
|
+
payload=result,
|
|
114
|
+
target=req.source_node
|
|
115
|
+
)
|
|
116
|
+
return wrapper
|
|
117
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: koi-net
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.0b1
|
|
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>
|
|
@@ -27,11 +27,12 @@ License: MIT License
|
|
|
27
27
|
SOFTWARE.
|
|
28
28
|
License-File: LICENSE
|
|
29
29
|
Requires-Python: >=3.10
|
|
30
|
+
Requires-Dist: cryptography>=45.0.3
|
|
30
31
|
Requires-Dist: httpx>=0.28.1
|
|
31
32
|
Requires-Dist: networkx>=3.4.2
|
|
32
33
|
Requires-Dist: pydantic>=2.10.6
|
|
33
34
|
Requires-Dist: python-dotenv>=1.1.0
|
|
34
|
-
Requires-Dist: rid-lib>=3.2.
|
|
35
|
+
Requires-Dist: rid-lib>=3.2.7
|
|
35
36
|
Requires-Dist: ruamel-yaml>=0.18.10
|
|
36
37
|
Provides-Extra: dev
|
|
37
38
|
Requires-Dist: build; extra == 'dev'
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
koi_net/__init__.py,sha256=b0Ze0pZmJAuygpWUFHM6Kvqo3DkU_uzmkptv1EpAArw,31
|
|
2
|
+
koi_net/config.py,sha256=Zu6iVPQ1yar9OMZQp-Ez0eYRIoCeDq69eTQyYplQqQc,4057
|
|
3
|
+
koi_net/context.py,sha256=JmbpCzusXFq_NCXiUp5Z56N6vpBdYMUK8eOs7ogO68A,1428
|
|
4
|
+
koi_net/core.py,sha256=QIYRlvi5BFxaQKYrbI8CGs2yZxf-U6PeJlYBaG6HsLQ,6474
|
|
5
|
+
koi_net/default_actions.py,sha256=TkQR9oj9CpO37Gb5bZLmFNl-Q8n3OxGiX4dvxQR7SaA,421
|
|
6
|
+
koi_net/effector.py,sha256=gSyZgRxQ91X04UL261e2pXWUfBHnQTGtjSHpc2JufxA,4097
|
|
7
|
+
koi_net/identity.py,sha256=FvIWksGTqwM7HCevIwmo_6l-t-2tnYkaaR4CanZatL4,569
|
|
8
|
+
koi_net/secure.py,sha256=cGNF2assqCaYq0i0fhQBm7aREoAdpY-XVypDsE1ALaU,3970
|
|
9
|
+
koi_net/network/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
koi_net/network/behavior.py,sha256=NZLvWlrxR0uWriE3ZzCXmocUVccQthy7Xx8E_8KBwsg,1208
|
|
11
|
+
koi_net/network/error_handler.py,sha256=CrmCpBY2oj4nl7uXrIYusUHDKxPZ1HDuQAtiBSZarRI,1623
|
|
12
|
+
koi_net/network/event_queue.py,sha256=QV1dLOe-H85fNJVkc-e0ZRsUpHTkFcMLMbp3WU5gRNg,7225
|
|
13
|
+
koi_net/network/graph.py,sha256=NLstBsPa9By0luxcTjThnqVd3hxfQdFwn8tWgJ6u4l4,4144
|
|
14
|
+
koi_net/network/request_handler.py,sha256=77SHLO92gVHTusUXWo89KgjRnxU9vLG_Qi8HxTFtFBg,6376
|
|
15
|
+
koi_net/network/resolver.py,sha256=coIp4M6k0-8sUfAy4h2NMx_7zCNroWlCHKOj3AXZVhc,5412
|
|
16
|
+
koi_net/network/response_handler.py,sha256=tEfzSZWXKCRwUlXhM8Qp3Y6BKTQ4abfi-MrSaatlITI,1980
|
|
17
|
+
koi_net/processor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
|
+
koi_net/processor/default_handlers.py,sha256=SX1eP740W9LeG-IEoBOmsNrKJfOEDDuEQUSwnJEG_8w,8954
|
|
19
|
+
koi_net/processor/handler.py,sha256=_loaHjgVGVUxtCQdvAY9dQ0iqiq5co7wB2tK-usuv3Y,2355
|
|
20
|
+
koi_net/processor/interface.py,sha256=ebDwqggznFRfp2PT8-UJPUAvCwX8nZaaQ68FUeWQvmw,3682
|
|
21
|
+
koi_net/processor/knowledge_object.py,sha256=avQnsaeqqiJxy40P1VGljuQMtAGmJB-TBa4pmBXTaIs,3863
|
|
22
|
+
koi_net/processor/knowledge_pipeline.py,sha256=i7FpCFl0UIOwCI5zhP1i8M4PX4A48VN28iV9jruvN5k,9486
|
|
23
|
+
koi_net/protocol/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
|
+
koi_net/protocol/api_models.py,sha256=bHhbLeq8I7nVBuW-AXgKfb1O58_mLogHRG8A_LZt2IE,1188
|
|
25
|
+
koi_net/protocol/consts.py,sha256=bisbVEojPIHlLhkLafBzfIhH25TjNfvTORF1g6YXzIM,243
|
|
26
|
+
koi_net/protocol/edge.py,sha256=dQKtI0_eX2E6tD7kMExv6DeJMkqNo2cY-LxJMJbiK0E,963
|
|
27
|
+
koi_net/protocol/envelope.py,sha256=W-K3rjwqwAL9wCXb2_gpAUwnc2xOVdZ1UWMoDlLrqJY,1690
|
|
28
|
+
koi_net/protocol/errors.py,sha256=A83QiYe_fJdxW2lsNsLCujWxDr5sk1UmYYd3TGbSNJA,601
|
|
29
|
+
koi_net/protocol/event.py,sha256=eGgihEj1gliLoQRk8pVB2q_was0AGo-PbT3Hqnpn3oU,1379
|
|
30
|
+
koi_net/protocol/node.py,sha256=7GQzHORFr9cP4BqJgir6EGSWCskL-yqmvJksIiLfcWU,409
|
|
31
|
+
koi_net/protocol/secure.py,sha256=Reem9Z4le4uWXM9uczNOdmgVBg8p4YQav-7_c3pZ1CQ,3366
|
|
32
|
+
koi_net-1.1.0b1.dist-info/METADATA,sha256=pHwaqM6wXoQpOUINUBlLlmCnSv3nEHF-EbL5x42jf3s,37142
|
|
33
|
+
koi_net-1.1.0b1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
34
|
+
koi_net-1.1.0b1.dist-info/licenses/LICENSE,sha256=03mgCL5qth2aD9C3F3qNVs4sFJSpK9kjtYCyOwdSp7s,1069
|
|
35
|
+
koi_net-1.1.0b1.dist-info/RECORD,,
|
koi_net/protocol/helpers.py
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
from rid_lib.core import RIDType
|
|
2
|
-
from rid_lib.ext.bundle import Bundle
|
|
3
|
-
from rid_lib.types import KoiNetEdge
|
|
4
|
-
from rid_lib.types.koi_net_node import KoiNetNode
|
|
5
|
-
from .edge import EdgeProfile, EdgeStatus, EdgeType
|
|
6
|
-
|
|
7
|
-
def generate_edge_bundle(
|
|
8
|
-
source: KoiNetNode,
|
|
9
|
-
target: KoiNetNode,
|
|
10
|
-
rid_types: list[RIDType],
|
|
11
|
-
edge_type: EdgeType
|
|
12
|
-
) -> Bundle:
|
|
13
|
-
edge_rid = KoiNetEdge.generate(source, target)
|
|
14
|
-
edge_profile = EdgeProfile(
|
|
15
|
-
source=source,
|
|
16
|
-
target=target,
|
|
17
|
-
rid_types=rid_types,
|
|
18
|
-
edge_type=edge_type,
|
|
19
|
-
status=EdgeStatus.PROPOSED
|
|
20
|
-
)
|
|
21
|
-
edge_bundle = Bundle.generate(
|
|
22
|
-
edge_rid,
|
|
23
|
-
edge_profile.model_dump()
|
|
24
|
-
)
|
|
25
|
-
return edge_bundle
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
koi_net/__init__.py,sha256=b0Ze0pZmJAuygpWUFHM6Kvqo3DkU_uzmkptv1EpAArw,31
|
|
2
|
-
koi_net/config.py,sha256=TIKb1kFTcEysqwdHp6yCNpcXeS84dlprcb-f0z2jF0Y,3160
|
|
3
|
-
koi_net/core.py,sha256=IO8kqiNMYVeuNzilq7eHBA7IulsxRjrCbWnIAx6_abA,4406
|
|
4
|
-
koi_net/identity.py,sha256=muc5vuQ8zUOebhwAB3-ql6W2pgQETiYXXQAFBv8bLyg,1288
|
|
5
|
-
koi_net/network/__init__.py,sha256=r_RN-q_mDYC-2RAkN-lJoMUX76TXyfEUc_MVKW87z0g,39
|
|
6
|
-
koi_net/network/graph.py,sha256=dsfPuHUTkCzlj0QeL0e7dgp7-FR5_AGP7eE8EpBPhC0,4710
|
|
7
|
-
koi_net/network/interface.py,sha256=icpl0rzpC5yV86BQBAbjAjK7AWhgCFoyFLm_Fjf1mCI,10451
|
|
8
|
-
koi_net/network/request_handler.py,sha256=66gjX2x4UnBWZYwKLjp_3WkhL-ekhR3VAyfGviHTcUs,4790
|
|
9
|
-
koi_net/network/response_handler.py,sha256=CAwici2Etj9ESndERXdtYkMlc4gWHz_xc7jHgY2Qjcg,1830
|
|
10
|
-
koi_net/processor/__init__.py,sha256=x4fAY0hvQEDcpfdTB3POIzxBQjYAtn0qQazPo1Xm0m4,41
|
|
11
|
-
koi_net/processor/default_handlers.py,sha256=dP64lEJ64BJ7H8PhFK-GZI1pv51tVVINV4jAgcOtOhc,8669
|
|
12
|
-
koi_net/processor/handler.py,sha256=7X6M6PP8m6-xdtsP1y4QO83g_MN5VSszNNikprITK80,2523
|
|
13
|
-
koi_net/processor/interface.py,sha256=Kyw4SQos_1WdcPJJe-j2w4xDIfwtmpF4mfGlkRVRqUI,12876
|
|
14
|
-
koi_net/processor/knowledge_object.py,sha256=RCgzkILsWm1Jw_NkSu4jTRYA9Ugga6mJ4jqKWwketQs,4090
|
|
15
|
-
koi_net/protocol/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
-
koi_net/protocol/api_models.py,sha256=DYDKCRD2Uja633bBAyTsaxyb1oF9pX9yQ9NpNAbkczo,1070
|
|
17
|
-
koi_net/protocol/consts.py,sha256=bisbVEojPIHlLhkLafBzfIhH25TjNfvTORF1g6YXzIM,243
|
|
18
|
-
koi_net/protocol/edge.py,sha256=CcmvIY4P1HEBdKNJ4wFRDmwYMRMss24Besmbi7ZRFxQ,427
|
|
19
|
-
koi_net/protocol/event.py,sha256=eGgihEj1gliLoQRk8pVB2q_was0AGo-PbT3Hqnpn3oU,1379
|
|
20
|
-
koi_net/protocol/helpers.py,sha256=8ZkQrjb_G0QEaMIKe9wkFOBonl1bkmemx_pwKMwIiLg,695
|
|
21
|
-
koi_net/protocol/node.py,sha256=2HhCh3LdBLlY2Z_kXNmKHzpVLKbP_ODob3HjHayFQtM,375
|
|
22
|
-
koi_net-1.0.0b19.dist-info/METADATA,sha256=uVzxDiRiHRncwfjotk7j_frmm_ka6PEpI-kcA278HoE,37107
|
|
23
|
-
koi_net-1.0.0b19.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
24
|
-
koi_net-1.0.0b19.dist-info/licenses/LICENSE,sha256=03mgCL5qth2aD9C3F3qNVs4sFJSpK9kjtYCyOwdSp7s,1069
|
|
25
|
-
koi_net-1.0.0b19.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|