koi-net 1.2.0b2__py3-none-any.whl → 1.2.0b3__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.

Files changed (44) hide show
  1. koi_net/__init__.py +0 -1
  2. koi_net/assembler.py +20 -7
  3. koi_net/cli/models.py +2 -2
  4. koi_net/config/core.py +71 -0
  5. koi_net/config/full_node.py +31 -0
  6. koi_net/config/loader.py +46 -0
  7. koi_net/config/partial_node.py +18 -0
  8. koi_net/core.py +15 -23
  9. koi_net/default_actions.py +1 -2
  10. koi_net/effector.py +1 -1
  11. koi_net/entrypoints/__init__.py +2 -0
  12. koi_net/entrypoints/base.py +5 -0
  13. koi_net/{poller.py → entrypoints/poller.py} +9 -9
  14. koi_net/{server.py → entrypoints/server.py} +9 -10
  15. koi_net/handshaker.py +2 -2
  16. koi_net/identity.py +1 -1
  17. koi_net/lifecycle.py +6 -6
  18. koi_net/network/error_handler.py +1 -1
  19. koi_net/network/event_queue.py +1 -1
  20. koi_net/network/poll_event_buffer.py +1 -1
  21. koi_net/network/resolver.py +1 -1
  22. koi_net/network/response_handler.py +1 -1
  23. koi_net/{context.py → processor/context.py} +6 -6
  24. koi_net/processor/handler.py +4 -1
  25. koi_net/processor/{handlers.py → knowledge_handlers.py} +6 -6
  26. koi_net/processor/knowledge_object.py +2 -3
  27. koi_net/processor/kobj_queue.py +1 -1
  28. koi_net/processor/pipeline.py +2 -2
  29. koi_net/protocol/node.py +3 -3
  30. koi_net/protocol/secure.py +6 -0
  31. koi_net/secure.py +1 -2
  32. koi_net/workers/__init__.py +2 -0
  33. koi_net/{processor → workers}/event_worker.py +8 -8
  34. koi_net/{processor → workers}/kobj_worker.py +3 -3
  35. {koi_net-1.2.0b2.dist-info → koi_net-1.2.0b3.dist-info}/METADATA +1 -1
  36. koi_net-1.2.0b3.dist-info/RECORD +56 -0
  37. koi_net/config.py +0 -161
  38. koi_net/interfaces/entrypoint.py +0 -5
  39. koi_net/sentry.py +0 -13
  40. koi_net-1.2.0b2.dist-info/RECORD +0 -52
  41. /koi_net/{interfaces/worker.py → workers/base.py} +0 -0
  42. {koi_net-1.2.0b2.dist-info → koi_net-1.2.0b3.dist-info}/WHEEL +0 -0
  43. {koi_net-1.2.0b2.dist-info → koi_net-1.2.0b3.dist-info}/entry_points.txt +0 -0
  44. {koi_net-1.2.0b2.dist-info → koi_net-1.2.0b3.dist-info}/licenses/LICENSE +0 -0
koi_net/__init__.py CHANGED
@@ -1,2 +1 @@
1
1
  from . import logger
2
- from . import sentry
koi_net/assembler.py CHANGED
@@ -2,9 +2,10 @@ import inspect
2
2
  from typing import Protocol
3
3
  from dataclasses import make_dataclass
4
4
 
5
+ from pydantic import BaseModel
5
6
  import structlog
6
7
 
7
- from .interfaces.entrypoint import EntryPoint
8
+ from .entrypoints.base import EntryPoint
8
9
 
9
10
  log = structlog.stdlib.get_logger()
10
11
 
@@ -41,13 +42,25 @@ class NodeAssembler(metaclass=BuildOrderer):
41
42
  @classmethod
42
43
  def _build(cls) -> NodeContainer:
43
44
  components = {}
44
- for comp_name in cls._build_order:
45
- comp_factory = getattr(cls, comp_name, None)
45
+ for comp_name in cls._build_order:
46
+ comp = getattr(cls, comp_name, None)
46
47
 
47
- if comp_factory is None:
48
+ if comp is None:
48
49
  raise Exception(f"Couldn't find factory for component '{comp_name}'")
49
50
 
50
- sig = inspect.signature(comp_factory)
51
+ print(comp_name)
52
+
53
+ if not callable(comp):
54
+ print(f"Treating {comp_name} as a literal")
55
+ components[comp_name] = comp
56
+ continue
57
+
58
+ if issubclass(comp, BaseModel):
59
+ print(f"Treating {comp_name} as a pydantic model")
60
+ components[comp_name] = comp
61
+ continue
62
+
63
+ sig = inspect.signature(comp)
51
64
 
52
65
  required_comps = []
53
66
  for name, param in sig.parameters.items():
@@ -58,7 +71,7 @@ class NodeAssembler(metaclass=BuildOrderer):
58
71
  else:
59
72
  s = f"{comp_name} -> {', '.join([name for name, _type in required_comps])}"
60
73
 
61
- print(s.replace("graph", "_graph"), end=";\n")
74
+ # print(s.replace("graph", "_graph"), end=";\n")
62
75
 
63
76
  dependencies = {}
64
77
  for req_comp_name, req_comp_type in required_comps:
@@ -67,7 +80,7 @@ class NodeAssembler(metaclass=BuildOrderer):
67
80
 
68
81
  dependencies[req_comp_name] = components[req_comp_name]
69
82
 
70
- components[comp_name] = comp_factory(**dependencies)
83
+ components[comp_name] = comp(**dependencies)
71
84
 
72
85
  NodeContainer = make_dataclass(
73
86
  cls_name="NodeContainer",
koi_net/cli/models.py CHANGED
@@ -1,9 +1,9 @@
1
- from pydantic import BaseModel, Field, PrivateAttr
1
+ from pydantic import BaseModel, PrivateAttr
2
2
  from ruamel.yaml import YAML
3
3
 
4
4
 
5
5
  class KoiNetworkConfig(BaseModel):
6
- nodes: dict[str, str] = Field(default_factory=dict)
6
+ nodes: dict[str, str] = {}
7
7
  _file_path: str = PrivateAttr(default="koi-net-config.yaml")
8
8
 
9
9
  @classmethod
koi_net/config/core.py ADDED
@@ -0,0 +1,71 @@
1
+ import os
2
+ from pydantic import BaseModel, model_validator
3
+ from dotenv import load_dotenv
4
+ from rid_lib import RIDType
5
+ from rid_lib.types import KoiNetNode
6
+
7
+ from koi_net.protocol.secure import PrivateKey
8
+ from ..protocol.node import NodeProfile
9
+
10
+
11
+ class NodeContact(BaseModel):
12
+ rid: KoiNetNode | None = None
13
+ url: str | None = None
14
+
15
+ class KoiNetConfig(BaseModel):
16
+ """Config for KOI-net."""
17
+
18
+ node_name: str
19
+ node_rid: KoiNetNode | None = None
20
+ node_profile: NodeProfile
21
+
22
+ rid_types_of_interest: list[RIDType] = [KoiNetNode]
23
+
24
+ cache_directory_path: str = ".rid_cache"
25
+ event_queues_path: str = "event_queues.json"
26
+ private_key_pem_path: str = "priv_key.pem"
27
+
28
+ first_contact: NodeContact = NodeContact()
29
+
30
+ class EnvConfig(BaseModel):
31
+ """Config for environment variables.
32
+
33
+ Values set in the config are the variables names, and are loaded
34
+ from the environment at runtime. For example, if the config YAML
35
+ sets `priv_key_password: PRIV_KEY_PASSWORD` accessing
36
+ `priv_key_password` would retrieve the value of `PRIV_KEY_PASSWORD`
37
+ from the environment.
38
+ """
39
+
40
+ priv_key_password: str = "PRIV_KEY_PASSWORD"
41
+
42
+ def __init__(self, **kwargs):
43
+ super().__init__(**kwargs)
44
+ load_dotenv()
45
+
46
+ def __getattribute__(self, name):
47
+ value = super().__getattribute__(name)
48
+ if name in type(self).model_fields:
49
+ env_val = os.getenv(value)
50
+ if env_val is None:
51
+ raise ValueError(f"Required environment variable {value} not set")
52
+ return env_val
53
+ return value
54
+
55
+ class NodeConfig(BaseModel):
56
+ koi_net: KoiNetConfig
57
+ env: EnvConfig = EnvConfig()
58
+
59
+ @model_validator(mode="after")
60
+ def generate_rid_cascade(self):
61
+ if not self.koi_net.node_rid:
62
+ priv_key = PrivateKey.generate()
63
+ pub_key = priv_key.public_key()
64
+
65
+ self.koi_net.node_rid = pub_key.to_node_rid(self.koi_net.node_name)
66
+
67
+ with open(self.koi_net.private_key_pem_path, "w") as f:
68
+ f.write(priv_key.to_pem(self.env.priv_key_password))
69
+
70
+ self.koi_net.node_profile.public_key = pub_key.to_der()
71
+ return self
@@ -0,0 +1,31 @@
1
+ from pydantic import BaseModel, model_validator
2
+ from koi_net.config.core import NodeConfig, KoiNetConfig as BaseKoiNetConfig
3
+ from ..protocol.node import NodeProfile as BaseNodeProfile, NodeType, NodeProvides
4
+
5
+
6
+ class NodeProfile(BaseNodeProfile):
7
+ node_type: NodeType = NodeType.FULL
8
+
9
+ class KoiNetConfig(BaseKoiNetConfig):
10
+ node_profile: NodeProfile
11
+
12
+ class ServerConfig(BaseModel):
13
+ """Config for the node server (full node only)."""
14
+
15
+ host: str = "127.0.0.1"
16
+ port: int = 8000
17
+ path: str | None = "/koi-net"
18
+
19
+ @property
20
+ def url(self) -> str:
21
+ return f"http://{self.host}:{self.port}{self.path or ''}"
22
+
23
+ class FullNodeConfig(NodeConfig):
24
+ koi_net: KoiNetConfig
25
+ server: ServerConfig = ServerConfig()
26
+
27
+ @model_validator(mode="after")
28
+ def check_url(self):
29
+ if not self.koi_net.node_profile.base_url:
30
+ self.koi_net.node_profile.base_url = self.server.url
31
+ return self
@@ -0,0 +1,46 @@
1
+ from ruamel.yaml import YAML
2
+ from .core import NodeConfig
3
+
4
+
5
+ class ConfigLoader:
6
+ _config: NodeConfig
7
+
8
+ _file_path: str = "config.yaml"
9
+ _file_content: str
10
+
11
+ def __init__(self, config_cls: type[NodeConfig]):
12
+ self._config_cls = config_cls
13
+ self.load_from_yaml()
14
+
15
+ def __getattr__(self, name):
16
+ return getattr(self._config, name)
17
+
18
+ def load_from_yaml(self):
19
+ """Loads config state from YAML file."""
20
+ yaml = YAML()
21
+
22
+ try:
23
+ with open(self._file_path, "r") as f:
24
+ self._file_content = f.read()
25
+ config_data = yaml.load(self._file_content)
26
+ self._config = self._config_cls.model_validate(config_data)
27
+
28
+ except FileNotFoundError:
29
+ self._config = self._config_cls()
30
+
31
+ self.save_to_yaml()
32
+
33
+
34
+ def save_to_yaml(self):
35
+ yaml = YAML()
36
+
37
+ with open(self._file_path, "w") as f:
38
+ try:
39
+ config_data = self._config.model_dump(mode="json")
40
+ yaml.dump(config_data, f)
41
+ except Exception as e:
42
+ if self._file_content:
43
+ f.seek(0)
44
+ f.truncate()
45
+ f.write(self._file_content)
46
+ raise e
@@ -0,0 +1,18 @@
1
+ from pydantic import BaseModel
2
+ from koi_net.config.core import NodeConfig, KoiNetConfig
3
+ from ..protocol.node import NodeProfile, NodeType, NodeProvides
4
+
5
+
6
+ class NodeProfile(NodeProfile):
7
+ base_url: str | None = None
8
+ node_type: NodeType = NodeType.PARTIAL
9
+
10
+ class KoiNetConfig(KoiNetConfig):
11
+ node_profile: NodeProfile
12
+
13
+ class PollerConfig(BaseModel):
14
+ polling_interval: int = 5
15
+
16
+ class PartialNodeConfig(NodeConfig):
17
+ koi_net: KoiNetConfig
18
+ poller: PollerConfig = PollerConfig()
koi_net/core.py CHANGED
@@ -1,11 +1,13 @@
1
1
  from rid_lib.ext import Cache
2
+
3
+ from .config.loader import ConfigLoader
2
4
  from .assembler import NodeAssembler
3
- from .config.base import BaseConfig
4
- from .context import HandlerContext
5
+ from .config.core import NodeConfig
6
+ from .processor.context import HandlerContext
5
7
  from .effector import Effector
6
8
  from .handshaker import Handshaker
7
9
  from .identity import NodeIdentity
8
- from .processor.kobj_worker import KnowledgeProcessingWorker
10
+ from .workers import KnowledgeProcessingWorker, EventProcessingWorker
9
11
  from .lifecycle import NodeLifecycle
10
12
  from .network.error_handler import ErrorHandler
11
13
  from .network.event_queue import EventQueue
@@ -14,8 +16,11 @@ from .network.request_handler import RequestHandler
14
16
  from .network.resolver import NetworkResolver
15
17
  from .network.response_handler import ResponseHandler
16
18
  from .network.poll_event_buffer import PollEventBuffer
17
- from .poller import NodePoller
18
- from .processor.handlers import (
19
+ from .processor.pipeline import KnowledgePipeline
20
+ from .processor.kobj_queue import KobjQueue
21
+ from .secure import Secure
22
+ from .entrypoints import NodeServer, NodePoller
23
+ from .processor.knowledge_handlers import (
19
24
  basic_manifest_handler,
20
25
  basic_network_output_filter,
21
26
  basic_rid_handler,
@@ -24,28 +29,15 @@ from .processor.handlers import (
24
29
  forget_edge_on_node_deletion,
25
30
  secure_profile_handler
26
31
  )
27
- from .processor.event_worker import EventProcessingWorker
28
- from .processor.pipeline import KnowledgePipeline
29
- from .processor.kobj_queue import KobjQueue
30
- from .secure import Secure
31
- from .server import NodeServer
32
-
33
-
34
- # factory functions for components with non standard initializiation
35
-
36
- def make_config() -> BaseConfig:
37
- return BaseConfig.load_from_yaml()
38
-
39
- def make_cache(config: BaseConfig) -> Cache:
40
- return Cache(directory_path=config.koi_net.cache_directory_path)
41
32
 
42
33
 
43
34
  class BaseNode(NodeAssembler):
44
- config = lambda: None
35
+ config_cls = NodeConfig
45
36
  kobj_queue = KobjQueue
46
37
  event_queue = EventQueue
47
38
  poll_event_buf = PollEventBuffer
48
- knowledge_handlers = lambda: [
39
+ config = ConfigLoader
40
+ knowledge_handlers = [
49
41
  basic_rid_handler,
50
42
  basic_manifest_handler,
51
43
  secure_profile_handler,
@@ -54,7 +46,8 @@ class BaseNode(NodeAssembler):
54
46
  basic_network_output_filter,
55
47
  forget_edge_on_node_deletion
56
48
  ]
57
- cache = make_cache
49
+ cache = lambda config: Cache(
50
+ directory_path=config.koi_net.cache_directory_path)
58
51
  identity = NodeIdentity
59
52
  graph = NetworkGraph
60
53
  secure = Secure
@@ -70,7 +63,6 @@ class BaseNode(NodeAssembler):
70
63
  event_worker = EventProcessingWorker
71
64
  lifecycle = NodeLifecycle
72
65
 
73
-
74
66
  class FullNode(BaseNode):
75
67
  entrypoint = NodeServer
76
68
 
@@ -1,9 +1,8 @@
1
1
  """Implementations of default dereference actions."""
2
2
 
3
- from .context import ActionContext
4
3
  from rid_lib.types import KoiNetNode
5
4
  from rid_lib.ext import Bundle
6
- from .effector import Effector
5
+ from .effector import Effector, ActionContext
7
6
 
8
7
 
9
8
  @Effector.register_default_action(KoiNetNode)
koi_net/effector.py CHANGED
@@ -155,7 +155,7 @@ class Effector:
155
155
  and bundle is not None
156
156
  and source != BundleSource.CACHE
157
157
  ):
158
- self.kobj_queue.put_kobj(
158
+ self.kobj_queue.push(
159
159
  bundle=bundle,
160
160
  source=source if type(source) is KoiNetNode else None
161
161
  )
@@ -0,0 +1,2 @@
1
+ from .poller import NodePoller
2
+ from .server import NodeServer
@@ -0,0 +1,5 @@
1
+ from koi_net.config.core import NodeConfig
2
+
3
+
4
+ class EntryPoint:
5
+ def run(self): ...
@@ -2,11 +2,11 @@
2
2
  import time
3
3
  import structlog
4
4
 
5
- from koi_net.interfaces.entrypoint import EntryPoint
6
- from .processor.kobj_queue import KobjQueue
7
- from .lifecycle import NodeLifecycle
8
- from .network.resolver import NetworkResolver
9
- from .config import NodeConfig
5
+ from .base import EntryPoint
6
+ from ..processor.kobj_queue import KobjQueue
7
+ from ..lifecycle import NodeLifecycle
8
+ from ..network.resolver import NetworkResolver
9
+ from ..config.partial_node import PartialNodeConfig
10
10
 
11
11
  log = structlog.stdlib.get_logger()
12
12
 
@@ -16,11 +16,11 @@ class NodePoller(EntryPoint):
16
16
  kobj_queue: KobjQueue
17
17
  lifecycle: NodeLifecycle
18
18
  resolver: NetworkResolver
19
- config: NodeConfig
19
+ config: PartialNodeConfig
20
20
 
21
21
  def __init__(
22
22
  self,
23
- config: NodeConfig,
23
+ config: PartialNodeConfig,
24
24
  lifecycle: NodeLifecycle,
25
25
  kobj_queue: KobjQueue,
26
26
  resolver: NetworkResolver,
@@ -35,7 +35,7 @@ class NodePoller(EntryPoint):
35
35
  neighbors = self.resolver.poll_neighbors()
36
36
  for node_rid in neighbors:
37
37
  for event in neighbors[node_rid]:
38
- self.kobj_queue.put_kobj(event=event, source=node_rid)
38
+ self.kobj_queue.push(event=event, source=node_rid)
39
39
 
40
40
  def run(self):
41
41
  """Runs polling event loop."""
@@ -44,6 +44,6 @@ class NodePoller(EntryPoint):
44
44
  start_time = time.time()
45
45
  self.poll()
46
46
  elapsed = time.time() - start_time
47
- sleep_time = self.config.koi_net.polling_interval - elapsed
47
+ sleep_time = self.config.poller.polling_interval - elapsed
48
48
  if sleep_time > 0:
49
49
  time.sleep(sleep_time)
@@ -4,21 +4,20 @@ from contextlib import asynccontextmanager
4
4
  from fastapi import FastAPI, APIRouter
5
5
  from fastapi.responses import JSONResponse
6
6
 
7
- from koi_net.interfaces.entrypoint import EntryPoint
8
-
9
- from .network.response_handler import ResponseHandler
10
- from .protocol.model_map import API_MODEL_MAP
11
- from .protocol.api_models import ErrorResponse
12
- from .protocol.errors import ProtocolError
13
- from .lifecycle import NodeLifecycle
14
- from .config import NodeConfig
7
+ from .base import EntryPoint
8
+ from ..network.response_handler import ResponseHandler
9
+ from ..protocol.model_map import API_MODEL_MAP
10
+ from ..protocol.api_models import ErrorResponse
11
+ from ..protocol.errors import ProtocolError
12
+ from ..lifecycle import NodeLifecycle
13
+ from ..config.full_node import FullNodeConfig
15
14
 
16
15
  log = structlog.stdlib.get_logger()
17
16
 
18
17
 
19
18
  class NodeServer(EntryPoint):
20
19
  """Manages FastAPI server and event handling for full nodes."""
21
- config: NodeConfig
20
+ config: FullNodeConfig
22
21
  lifecycle: NodeLifecycle
23
22
  response_handler: ResponseHandler
24
23
  app: FastAPI
@@ -26,7 +25,7 @@ class NodeServer(EntryPoint):
26
25
 
27
26
  def __init__(
28
27
  self,
29
- config: NodeConfig,
28
+ config: FullNodeConfig,
30
29
  lifecycle: NodeLifecycle,
31
30
  response_handler: ResponseHandler,
32
31
  ):
koi_net/handshaker.py CHANGED
@@ -25,13 +25,13 @@ class Handshaker:
25
25
  reset the target's cache in case it already knew this node.
26
26
  """
27
27
  log.debug(f"Initiating handshake with {target}")
28
- self.event_queue.push_event_to(
28
+ self.event_queue.push(
29
29
  Event.from_rid(
30
30
  event_type=EventType.FORGET,
31
31
  rid=self.identity.rid),
32
32
  target=target
33
33
  )
34
- self.event_queue.push_event_to(
34
+ self.event_queue.push(
35
35
  event=Event.from_bundle(
36
36
  event_type=EventType.NEW,
37
37
  bundle=self.cache.read(self.identity.rid)),
koi_net/identity.py CHANGED
@@ -1,6 +1,6 @@
1
1
  import structlog
2
2
  from rid_lib.types.koi_net_node import KoiNetNode
3
- from .config import NodeConfig
3
+ from .config.core import NodeConfig
4
4
  from .protocol.node import NodeProfile
5
5
 
6
6
  log = structlog.stdlib.get_logger()
koi_net/lifecycle.py CHANGED
@@ -6,12 +6,12 @@ from rid_lib.types import KoiNetNode
6
6
 
7
7
  from .handshaker import Handshaker
8
8
  from .network.request_handler import RequestHandler
9
- from .processor.kobj_worker import KnowledgeProcessingWorker
9
+ from .workers.kobj_worker import KnowledgeProcessingWorker
10
10
  from .network.event_queue import EventQueue
11
- from .processor.event_worker import EventProcessingWorker
11
+ from .workers import EventProcessingWorker
12
12
  from .protocol.api_models import ErrorResponse
13
- from .interfaces.worker import STOP_WORKER
14
- from .config import NodeConfig
13
+ from .workers.base import STOP_WORKER
14
+ from .config.core import NodeConfig
15
15
  from .processor.kobj_queue import KobjQueue
16
16
  from .network.graph import NetworkGraph
17
17
  from .identity import NodeIdentity
@@ -99,7 +99,7 @@ class NodeLifecycle:
99
99
 
100
100
  # refresh to reflect changes (if any) in config.yaml
101
101
 
102
- self.kobj_queue.put_kobj(bundle=Bundle.generate(
102
+ self.kobj_queue.push(bundle=Bundle.generate(
103
103
  rid=self.identity.rid,
104
104
  contents=self.identity.profile.model_dump()
105
105
  ))
@@ -119,7 +119,7 @@ class NodeLifecycle:
119
119
  continue
120
120
 
121
121
  for manifest in payload.manifests:
122
- self.kobj_queue.put_kobj(
122
+ self.kobj_queue.push(
123
123
  manifest=manifest,
124
124
  source=coordinator
125
125
  )
@@ -31,7 +31,7 @@ class ErrorHandler:
31
31
 
32
32
  if self.timeout_counter[node] > 3:
33
33
  log.debug(f"Exceeded time out limit, forgetting node")
34
- self.kobj_queue.put_kobj(rid=node, event_type=EventType.FORGET)
34
+ self.kobj_queue.push(rid=node, event_type=EventType.FORGET)
35
35
  # do something
36
36
 
37
37
 
@@ -20,7 +20,7 @@ class EventQueue:
20
20
  def __init__(self):
21
21
  self.q = Queue()
22
22
 
23
- def push_event_to(self, event: Event, target: KoiNetNode):
23
+ def push(self, event: Event, target: KoiNetNode):
24
24
  """Pushes event to queue of specified node.
25
25
 
26
26
  Event will be sent to webhook or poll queue depending on the
@@ -9,7 +9,7 @@ class PollEventBuffer:
9
9
  def __init__(self):
10
10
  self.buffers = dict()
11
11
 
12
- def put(self, node: KoiNetNode, event: Event):
12
+ def push(self, node: KoiNetNode, event: Event):
13
13
  event_buf = self.buffers.setdefault(node, [])
14
14
  event_buf.append(event)
15
15
 
@@ -11,7 +11,7 @@ from ..protocol.node import NodeProfile, NodeType
11
11
  from ..protocol.event import Event
12
12
  from ..protocol.api_models import ErrorResponse
13
13
  from ..identity import NodeIdentity
14
- from ..config import NodeConfig
14
+ from ..config.core import NodeConfig
15
15
 
16
16
  log = structlog.stdlib.get_logger()
17
17
 
@@ -70,7 +70,7 @@ class ResponseHandler:
70
70
  log.info(f"Request to broadcast events, received {len(req.events)} event(s)")
71
71
 
72
72
  for event in req.events:
73
- self.kobj_queue.put_kobj(event=event, source=source)
73
+ self.kobj_queue.push(event=event, source=source)
74
74
 
75
75
  def poll_events_handler(
76
76
  self,
@@ -2,12 +2,12 @@ from rid_lib.ext import Cache
2
2
 
3
3
  from koi_net.effector import Effector
4
4
  from koi_net.network.resolver import NetworkResolver
5
- from .config import NodeConfig
6
- from .network.graph import NetworkGraph
7
- from .network.event_queue import EventQueue
8
- from .network.request_handler import RequestHandler
9
- from .identity import NodeIdentity
10
- from .processor.kobj_queue import KobjQueue
5
+ from ..config.core import NodeConfig
6
+ from ..network.graph import NetworkGraph
7
+ from ..network.event_queue import EventQueue
8
+ from ..network.request_handler import RequestHandler
9
+ from ..identity import NodeIdentity
10
+ from .kobj_queue import KobjQueue
11
11
 
12
12
 
13
13
  class HandlerContext:
@@ -2,7 +2,10 @@ from dataclasses import dataclass
2
2
  from enum import StrEnum
3
3
  from typing import Callable
4
4
  from rid_lib import RIDType
5
+
5
6
  from ..protocol.event import EventType
7
+ from .knowledge_object import KnowledgeObject
8
+ from .context import HandlerContext
6
9
 
7
10
 
8
11
  class StopChain:
@@ -32,7 +35,7 @@ class HandlerType(StrEnum):
32
35
  class KnowledgeHandler:
33
36
  """Handles knowledge processing events of the provided types."""
34
37
 
35
- func: Callable
38
+ func: Callable[[HandlerContext, KnowledgeObject], None | KnowledgeObject | StopChain]
36
39
  handler_type: HandlerType
37
40
  rid_types: list[RIDType] | None
38
41
  event_types: list[EventType | None] | None = None
@@ -7,7 +7,7 @@ from rid_lib.types import KoiNetNode, KoiNetEdge
7
7
  from koi_net.protocol.node import NodeType
8
8
  from .handler import KnowledgeHandler, HandlerType, STOP_CHAIN
9
9
  from .knowledge_object import KnowledgeObject
10
- from ..context import HandlerContext
10
+ from .context import HandlerContext
11
11
  from ..protocol.event import Event, EventType
12
12
  from ..protocol.edge import EdgeProfile, EdgeStatus, EdgeType
13
13
  from ..protocol.node import NodeProfile
@@ -135,7 +135,7 @@ def edge_negotiation_handler(ctx: HandlerContext, kobj: KnowledgeObject):
135
135
 
136
136
  if abort:
137
137
  event = Event.from_rid(EventType.FORGET, kobj.rid)
138
- ctx.event_queue.push_event_to(event, peer_rid, flush=True)
138
+ ctx.event_queue.push(event, peer_rid, flush=True)
139
139
  return STOP_CHAIN
140
140
 
141
141
  else:
@@ -144,7 +144,7 @@ def edge_negotiation_handler(ctx: HandlerContext, kobj: KnowledgeObject):
144
144
  edge_profile.status = EdgeStatus.APPROVED
145
145
  updated_bundle = Bundle.generate(kobj.rid, edge_profile.model_dump())
146
146
 
147
- ctx.kobj_queue.put_kobj(bundle=updated_bundle, event_type=EventType.UPDATE)
147
+ ctx.kobj_queue.push(bundle=updated_bundle, event_type=EventType.UPDATE)
148
148
  return
149
149
 
150
150
  elif edge_profile.target == ctx.identity.rid:
@@ -216,7 +216,7 @@ def node_contact_handler(ctx: HandlerContext, kobj: KnowledgeObject):
216
216
 
217
217
  # queued for processing
218
218
  edge_bundle = Bundle.generate(edge_rid, edge_profile.model_dump())
219
- ctx.kobj_queue.put_kobj(bundle=edge_bundle)
219
+ ctx.kobj_queue.push(bundle=edge_bundle)
220
220
 
221
221
  log.info("Catching up on network state")
222
222
 
@@ -234,7 +234,7 @@ def node_contact_handler(ctx: HandlerContext, kobj: KnowledgeObject):
234
234
 
235
235
  # marked as external since we are handling RIDs from another node
236
236
  # will fetch remotely instead of checking local cache
237
- ctx.kobj_queue.put_kobj(rid=rid, source=kobj.rid)
237
+ ctx.kobj_queue.push(rid=rid, source=kobj.rid)
238
238
  log.info("Done")
239
239
 
240
240
 
@@ -296,4 +296,4 @@ def forget_edge_on_node_deletion(ctx: HandlerContext, kobj: KnowledgeObject):
296
296
 
297
297
  if kobj.rid in (edge_profile.source, edge_profile.target):
298
298
  log.debug("Identified edge with forgotten node")
299
- ctx.kobj_queue.put_kobj(rid=edge_rid, event_type=EventType.FORGET)
299
+ ctx.kobj_queue.push(rid=edge_rid, event_type=EventType.FORGET)
@@ -1,8 +1,7 @@
1
1
  from pydantic import BaseModel
2
2
  from rid_lib import RID
3
- from rid_lib.ext import Manifest
4
- from rid_lib.ext.bundle import Bundle
5
- from rid_lib.types.koi_net_node import KoiNetNode
3
+ from rid_lib.ext import Manifest, Bundle
4
+ from rid_lib.types import KoiNetNode
6
5
  from ..protocol.event import Event, EventType
7
6
 
8
7
 
@@ -16,7 +16,7 @@ class KobjQueue:
16
16
  def __init__(self):
17
17
  self.q = Queue()
18
18
 
19
- def put_kobj(
19
+ def push(
20
20
  self,
21
21
  rid: RID | None = None,
22
22
  manifest: Manifest | None = None,
@@ -13,7 +13,7 @@ from .handler import (
13
13
  StopChain
14
14
  )
15
15
  from .knowledge_object import KnowledgeObject
16
- from ..context import HandlerContext
16
+ from .context import HandlerContext
17
17
 
18
18
  log = structlog.stdlib.get_logger()
19
19
 
@@ -193,6 +193,6 @@ class KnowledgePipeline:
193
193
  log.debug("No network targets set")
194
194
 
195
195
  for node in kobj.network_targets:
196
- self.event_queue.push_event_to(kobj.normalized_event, node)
196
+ self.event_queue.push(kobj.normalized_event, node)
197
197
 
198
198
  kobj = self.call_handler_chain(HandlerType.Final, kobj)
koi_net/protocol/node.py CHANGED
@@ -1,5 +1,5 @@
1
1
  from enum import StrEnum
2
- from pydantic import BaseModel, Field
2
+ from pydantic import BaseModel
3
3
  from rid_lib import RIDType
4
4
 
5
5
 
@@ -8,8 +8,8 @@ class NodeType(StrEnum):
8
8
  PARTIAL = "PARTIAL"
9
9
 
10
10
  class NodeProvides(BaseModel):
11
- event: list[RIDType] = Field(default_factory=list)
12
- state: list[RIDType] = Field(default_factory=list)
11
+ event: list[RIDType] = []
12
+ state: list[RIDType] = []
13
13
 
14
14
  class NodeProfile(BaseModel):
15
15
  base_url: str | None = None
@@ -1,3 +1,4 @@
1
+ from rid_lib.types import KoiNetNode
1
2
  import structlog
2
3
  from base64 import b64decode, b64encode
3
4
  from cryptography.hazmat.primitives import hashes
@@ -134,6 +135,11 @@ class PublicKey:
134
135
  )
135
136
  ).decode()
136
137
 
138
+ def to_node_rid(self, name) -> KoiNetNode:
139
+ return KoiNetNode(
140
+ name=name,
141
+ hash=sha256_hash(self.to_der())
142
+ )
137
143
 
138
144
  def verify(self, signature: str, message: bytes) -> bool:
139
145
  # hashed_message = sha256_hash(message.decode())
koi_net/secure.py CHANGED
@@ -1,6 +1,5 @@
1
1
  import structlog
2
2
  from functools import wraps
3
-
4
3
  import cryptography.exceptions
5
4
  from rid_lib.ext import Bundle, Cache
6
5
  from rid_lib.ext.utils import sha256_hash
@@ -18,7 +17,7 @@ from .protocol.errors import (
18
17
  InvalidSignatureError,
19
18
  InvalidTargetError
20
19
  )
21
- from .config import NodeConfig
20
+ from .config.core import NodeConfig
22
21
 
23
22
  log = structlog.stdlib.get_logger()
24
23
 
@@ -0,0 +1,2 @@
1
+ from .event_worker import EventProcessingWorker
2
+ from .kobj_worker import KnowledgeProcessingWorker
@@ -6,13 +6,13 @@ import structlog
6
6
  from rid_lib.ext import Cache
7
7
  from rid_lib.types import KoiNetNode
8
8
 
9
- from koi_net.config import NodeConfig
10
- from koi_net.network.event_queue import EventQueue, QueuedEvent
11
- from koi_net.network.request_handler import RequestHandler
12
- from koi_net.network.poll_event_buffer import PollEventBuffer
13
- from koi_net.protocol.event import Event
14
- from koi_net.protocol.node import NodeProfile, NodeType
15
- from koi_net.interfaces.worker import ThreadWorker, STOP_WORKER
9
+ from ..config.core import NodeConfig
10
+ from ..network.event_queue import EventQueue, QueuedEvent
11
+ from ..network.request_handler import RequestHandler
12
+ from ..network.poll_event_buffer import PollEventBuffer
13
+ from ..protocol.event import Event
14
+ from ..protocol.node import NodeProfile, NodeType
15
+ from .base import ThreadWorker, STOP_WORKER
16
16
 
17
17
  log = structlog.stdlib.get_logger()
18
18
 
@@ -63,7 +63,7 @@ class EventProcessingWorker(ThreadWorker):
63
63
  return True
64
64
 
65
65
  elif node_profile.node_type == NodeType.PARTIAL:
66
- self.poll_event_buf.put(item.target, item.event)
66
+ self.poll_event_buf.push(item.target, item.event)
67
67
  return False
68
68
 
69
69
  elif item.target == self.config.koi_net.first_contact.rid:
@@ -2,9 +2,9 @@ import queue
2
2
  import traceback
3
3
  import structlog
4
4
 
5
- from .pipeline import KnowledgePipeline
6
- from .kobj_queue import KobjQueue
7
- from koi_net.interfaces.worker import ThreadWorker, STOP_WORKER
5
+ from ..processor.pipeline import KnowledgePipeline
6
+ from ..processor.kobj_queue import KobjQueue
7
+ from .base import ThreadWorker, STOP_WORKER
8
8
 
9
9
  log = structlog.stdlib.get_logger()
10
10
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: koi-net
3
- Version: 1.2.0b2
3
+ Version: 1.2.0b3
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>
@@ -0,0 +1,56 @@
1
+ koi_net/__init__.py,sha256=9z9lpKDuE7KF-evTBkAZechSvL9eQL4p0-ksmwZwMMU,21
2
+ koi_net/assembler.py,sha256=XR-e0-XHlrbXrZPJoO0tKaPH2xJ80KckfcjOeu9qr4o,3229
3
+ koi_net/core.py,sha256=gnR7moGHYkXHUxoV-mJRxi-tKZuPqvG9lg0jiVfAjXg,2257
4
+ koi_net/default_actions.py,sha256=2y7f9rUaENYRO8traTZbEQ7ySFZP_P8pUqf82bZj8Gk,602
5
+ koi_net/effector.py,sha256=fZEIBtvQQZmJx6HIcRB0jjP_EE00GREWuMQJ5m0uXOc,4937
6
+ koi_net/handshaker.py,sha256=d6s2R2eYxbOfpvRafKHNb_dD7LRdTkF4IsqFu7jQ-sQ,1211
7
+ koi_net/identity.py,sha256=-5YYda4xQ78EeGBspN9whWTuWttsUhZ8gxT2oLDEkpI,574
8
+ koi_net/lifecycle.py,sha256=axmr9KfEXzDT5HMVTVC6komMm9pdPQcODkudp7xVZ1k,4750
9
+ koi_net/logger.py,sha256=EzpQNvNrbi5LmMCobyuN1_wOz5VuMDeaPbLcyMrLKGI,6172
10
+ koi_net/secure.py,sha256=SUJqXScoSXgBs5PeeKtRKyDqGf35tGeNhXhwFa61IXE,4915
11
+ koi_net/utils.py,sha256=4K6BqtifExDUfPP8zJAICgPV1mcabz_MaFB0P0fSnic,411
12
+ koi_net/cli/__init__.py,sha256=Vpq0yLN0ROyF0qQYsyiuWFbjs-zsa90G1DpAv13qaiw,25
13
+ koi_net/cli/commands.py,sha256=5eVsvJAnHjwJdt8MNYrk5zSzWWm1ooiP35bJeQxYIq4,2592
14
+ koi_net/cli/models.py,sha256=9x66SSmIezw61KFbdk7VNoPQTi9JQGxtIlfWMNt5ZfU,1158
15
+ koi_net/config/core.py,sha256=RogkUeDHoQzpvZugqqk_8BkJiGVJX8ekLAZwYXtmsxs,2256
16
+ koi_net/config/full_node.py,sha256=sVxraN_fyM_jFHBhG7LEALHOlYbRvPIONuci8ws_bcA,945
17
+ koi_net/config/loader.py,sha256=3vFVz0V8pv6Ohq9pSMTpa40stYOlFB2do-aBKo7Wr8c,1311
18
+ koi_net/config/partial_node.py,sha256=ALfYXJ4lrMFhKt1nAr-Zn8HBVw9YLBSbN9ykEdwc91E,497
19
+ koi_net/entrypoints/__init__.py,sha256=DdKtM7uXYYZLDaHkzYVOVQh-g2S3bG0xdGAFXok6tj8,61
20
+ koi_net/entrypoints/base.py,sha256=nuaWRD4_0u5Cmieq4MiiJ2NrwOnoC4iaP4ulXXiInmI,85
21
+ koi_net/entrypoints/poller.py,sha256=5oo5Zj2fD43qkE7ai1M_PQi9vxDGbXPoZ4pAjL2H8X4,1472
22
+ koi_net/entrypoints/server.py,sha256=gbmRnSPo-OEaK2TyzTJ_1t-DlmtyARNSiqb07tq74bE,3090
23
+ koi_net/network/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
+ koi_net/network/error_handler.py,sha256=ZH0Py-XuSsnQiSB6rVZ2pywvMcKHr_VywnAiTI8RKEw,1780
25
+ koi_net/network/event_queue.py,sha256=vPrC5-QS0s57ALjdt2ddhNcSMwbvGakCvCKBMx4U6pw,734
26
+ koi_net/network/graph.py,sha256=ZJ1CY-SnYhnZAMm3e9YCbBflk80ZDETnoQKaBk5kLgo,4161
27
+ koi_net/network/poll_event_buffer.py,sha256=Wh4JcGnFaTHbveCzLWcqOzXAU_yk9EkUsukX5hI3pn8,735
28
+ koi_net/network/request_handler.py,sha256=XSX-JAqRua42YOakmia--9NnKcT32Fpoc-7aYfjDpwg,6752
29
+ koi_net/network/resolver.py,sha256=wg9yyJkZbS1G251u4tVav9SeIpH_Aq7FE0rLPvExn3g,5282
30
+ koi_net/network/response_handler.py,sha256=6GewpouDqMl1Ozgfkro_EcUqeJZEfY7msi1U7TQigCY,4212
31
+ koi_net/processor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
+ koi_net/processor/context.py,sha256=64rUQ6Oy3wbA5CtH40hqW7_ZPVDj4Wzw7dtVC0yIxkY,1323
33
+ koi_net/processor/handler.py,sha256=3z1PreLRH_48HU6o9lUD_5CAOgA8O9PuSB9iAusVa_c,2510
34
+ koi_net/processor/knowledge_handlers.py,sha256=H0DTHg2JI4_FvpafHjTMFC2mjjtgTCAew1s7V_fzajE,10908
35
+ koi_net/processor/knowledge_object.py,sha256=NJBNxzYdt_JNYpA71E1vaOuZNIKrkxRpK8l459mjbnc,4129
36
+ koi_net/processor/kobj_queue.py,sha256=tM_ssv2t_2t2A0w_X6rq-Gfxzl0NGCjt387dqTGxKxM,1833
37
+ koi_net/processor/pipeline.py,sha256=4CkOMOXyJ4J17Y5ulnlqJVnINjYqCGI1MBRz2oKylRM,8658
38
+ koi_net/protocol/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
+ koi_net/protocol/api_models.py,sha256=lPd_w-sncyrQlTQ__iae9Li1lFARu8nKiMMlXu7-Hls,1856
40
+ koi_net/protocol/consts.py,sha256=bisbVEojPIHlLhkLafBzfIhH25TjNfvTORF1g6YXzIM,243
41
+ koi_net/protocol/edge.py,sha256=PzdEhC43T1KO5iMSEu7I4tiz-7sZxtz41dJfWf-oHA0,1034
42
+ koi_net/protocol/envelope.py,sha256=4SKF4tP1P1ex7UEmYOJt7IP9_8fCWsa_o6ZBOu8SOKk,1877
43
+ koi_net/protocol/errors.py,sha256=uKPQ-TGLouZuK0xd2pXuCQoRTyu_JFsydSCLml13Cz8,595
44
+ koi_net/protocol/event.py,sha256=HxzLN-iCXPyr2YzrswMIkgZYeUdFbBpa5v98dAB06lQ,1328
45
+ koi_net/protocol/model_map.py,sha256=W0quo25HqVkzp8HQ7l_FNTtN4ZX0u7MIqp68Ir81fuk,1671
46
+ koi_net/protocol/node.py,sha256=7GQzHORFr9cP4BqJgir6EGSWCskL-yqmvJksIiLfcWU,409
47
+ koi_net/protocol/secure.py,sha256=_JRwPLLqifQQG_Z8QGeHfICX-pvOsppGvDy6_q8U8I8,5298
48
+ koi_net/workers/__init__.py,sha256=cTCXr4X_ONobHJxN0H8x3hvMgDpQnt7AeDbvcWzyz6Y,98
49
+ koi_net/workers/base.py,sha256=IvtXBTVmthUrURmB9Cn9wffeVv9_Cphsk97_GCLb5NQ,294
50
+ koi_net/workers/event_worker.py,sha256=Z-sShvc0jY3bNqN_P3INhAXFNKWP02YAyhzIFX984lk,4140
51
+ koi_net/workers/kobj_worker.py,sha256=VKGZZZMzSjp1NtuNGCUMmOxRFL0YwbLpTd6XlkQWfF0,1239
52
+ koi_net-1.2.0b3.dist-info/METADATA,sha256=PM-J7K9mH88xHgSeuDpcawOAQU8J8W3BqUJJ90cTUGY,37347
53
+ koi_net-1.2.0b3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
54
+ koi_net-1.2.0b3.dist-info/entry_points.txt,sha256=l7He_JTyXrfKIHkttnPWXHI717v8WpLLfCduL5QcEWA,40
55
+ koi_net-1.2.0b3.dist-info/licenses/LICENSE,sha256=03mgCL5qth2aD9C3F3qNVs4sFJSpK9kjtYCyOwdSp7s,1069
56
+ koi_net-1.2.0b3.dist-info/RECORD,,
koi_net/config.py DELETED
@@ -1,161 +0,0 @@
1
- import os
2
- from rid_lib import RIDType
3
- from ruamel.yaml import YAML
4
- from pydantic import BaseModel, Field, PrivateAttr
5
- from dotenv import load_dotenv
6
- from rid_lib.ext.utils import sha256_hash
7
- from rid_lib.types import KoiNetNode
8
- from .protocol.secure import PrivateKey
9
- from .protocol.node import NodeProfile, NodeType
10
-
11
-
12
- class ServerConfig(BaseModel):
13
- """Config for the node server (full node only)."""
14
-
15
- host: str = "127.0.0.1"
16
- port: int = 8000
17
- path: str | None = "/koi-net"
18
-
19
- @property
20
- def url(self) -> str:
21
- return f"http://{self.host}:{self.port}{self.path or ''}"
22
-
23
- class NodeContact(BaseModel):
24
- rid: KoiNetNode | None = None
25
- url: str | None = None
26
-
27
- class KoiNetConfig(BaseModel):
28
- """Config for KOI-net."""
29
-
30
- node_name: str
31
- node_rid: KoiNetNode | None = None
32
- node_profile: NodeProfile
33
-
34
- rid_types_of_interest: list[RIDType] = Field(
35
- default_factory=lambda: [KoiNetNode])
36
-
37
- cache_directory_path: str = ".rid_cache"
38
- event_queues_path: str = "event_queues.json"
39
- private_key_pem_path: str = "priv_key.pem"
40
- polling_interval: int = 5
41
-
42
- first_contact: NodeContact = Field(default_factory=NodeContact)
43
-
44
- _priv_key: PrivateKey | None = PrivateAttr(default=None)
45
-
46
- class EnvConfig(BaseModel):
47
- """Config for environment variables.
48
-
49
- Values set in the config are the variables names, and are loaded
50
- from the environment at runtime. For example, if the config YAML
51
- sets `priv_key_password: PRIV_KEY_PASSWORD` accessing
52
- `priv_key_password` would retrieve the value of `PRIV_KEY_PASSWORD`
53
- from the environment.
54
- """
55
-
56
- priv_key_password: str | None = "PRIV_KEY_PASSWORD"
57
-
58
- def __init__(self, **kwargs):
59
- super().__init__(**kwargs)
60
- load_dotenv()
61
-
62
- def __getattribute__(self, name):
63
- value = super().__getattribute__(name)
64
- if name in type(self).model_fields:
65
- env_val = os.getenv(value)
66
- if env_val is None:
67
- raise ValueError(f"Required environment variable {value} not set")
68
- return env_val
69
- return value
70
-
71
- class NodeConfig(BaseModel):
72
- """Base configuration class for all nodes.
73
-
74
- Designed to be extensible for custom node implementations. Classes
75
- inheriting from `NodeConfig` may add additional config groups.
76
- """
77
-
78
- server: ServerConfig = Field(default_factory=ServerConfig)
79
- koi_net: KoiNetConfig
80
- env: EnvConfig = Field(default_factory=EnvConfig)
81
-
82
- _file_path: str = PrivateAttr(default="config.yaml")
83
- _file_content: str | None = PrivateAttr(default=None)
84
-
85
- @classmethod
86
- def load_from_yaml(
87
- cls,
88
- file_path: str = "config.yaml",
89
- generate_missing: bool = True
90
- ):
91
- """Loads config state from YAML file.
92
-
93
- Defaults to `config.yaml`. If `generate_missing` is set to
94
- `True`, a private key and RID will be generated if not already
95
- present in the config.
96
- """
97
- yaml = YAML()
98
-
99
- try:
100
- with open(file_path, "r") as f:
101
- file_content = f.read()
102
- config_data = yaml.load(file_content)
103
- config = cls.model_validate(config_data)
104
- config._file_content = file_content
105
-
106
- except FileNotFoundError:
107
- # empty_fields = {}
108
- # for name, field in cls.model_fields.items():
109
-
110
- # if field.default is None or field.default_factory is None:
111
- # print(empty_fields)
112
- config = cls()
113
-
114
-
115
- config._file_path = file_path
116
-
117
- if generate_missing:
118
- if not config.koi_net.node_rid:
119
- priv_key = PrivateKey.generate()
120
- pub_key = priv_key.public_key()
121
-
122
- config.koi_net.node_rid = KoiNetNode(
123
- config.koi_net.node_name,
124
- sha256_hash(pub_key.to_der())
125
- )
126
-
127
- with open(config.koi_net.private_key_pem_path, "w") as f:
128
- f.write(
129
- priv_key.to_pem(config.env.priv_key_password)
130
- )
131
-
132
- config.koi_net.node_profile.public_key = pub_key.to_der()
133
-
134
- if config.koi_net.node_profile.node_type == NodeType.FULL:
135
- config.koi_net.node_profile.base_url = (
136
- config.koi_net.node_profile.base_url or config.server.url
137
- )
138
-
139
- config.save_to_yaml()
140
-
141
- return config
142
-
143
- def save_to_yaml(self):
144
- """Saves config state to YAML file.
145
-
146
- File path is set by `load_from_yaml` class method.
147
- """
148
-
149
- yaml = YAML()
150
-
151
- with open(self._file_path, "w") as f:
152
- try:
153
- config_data = self.model_dump(mode="json")
154
- yaml.dump(config_data, f)
155
- except Exception as e:
156
- if self._file_content:
157
- f.seek(0)
158
- f.truncate()
159
- f.write(self._file_content)
160
- raise e
161
-
@@ -1,5 +0,0 @@
1
- from typing import Protocol
2
-
3
-
4
- class EntryPoint(Protocol):
5
- def run(self): ...
koi_net/sentry.py DELETED
@@ -1,13 +0,0 @@
1
- # import sentry_sdk
2
- # from sentry_sdk.integrations.logging import LoggingIntegration
3
-
4
- # sentry_sdk.init(
5
- # dsn="https://7bbafef3c7dbd652506db3cb2aca9f98@o4510149352357888.ingest.us.sentry.io/4510149355765760",
6
- # # Add data like request headers and IP for users,
7
- # # see https://docs.sentry.io/platforms/python/data-management/data-collected/ for more info
8
- # send_default_pii=True,
9
- # enable_logs=True,
10
- # integrations=[
11
- # LoggingIntegration(sentry_logs_level=None)
12
- # ]
13
- # )
@@ -1,52 +0,0 @@
1
- koi_net/__init__.py,sha256=ZJQHfYaMtu3Qv6ZtKxq49N0T1GbVd3dvrjXZdeNYnQw,41
2
- koi_net/assembler.py,sha256=kV7qB1xnPvAVUrunaNgx4f9lb2qQlvlA4zZs1xKq62Q,2831
3
- koi_net/config.py,sha256=yV53GFQrJchyKKRs3sOhj27pyM6rwiUhIgDZ81rvZ48,5238
4
- koi_net/context.py,sha256=mBKMR1o6Tqy_cyhj7_niGkMSMOQeEMPhP9cpNDlML1s,1323
5
- koi_net/core.py,sha256=owbJYN_kCMwKz3ecWXt_tQXOEECL_q1uq4CcFAuR6EA,2428
6
- koi_net/default_actions.py,sha256=y9oaDeb3jJGSvVbuonmyGWkKWlzpEX3V32MjgEuYWc8,622
7
- koi_net/effector.py,sha256=0hW2NnHWjVZyRPXWh_X_0EBxqpCJBBhJCHFvB6uC3SM,4941
8
- koi_net/handshaker.py,sha256=sd2bYe7Fh5hCTq5q18_knKWAMzvH5a6zHzCcBKbkhWQ,1229
9
- koi_net/identity.py,sha256=jZjTSlgO8aJhfOx6-ppQVveHih6h0dP2Gtbsw6GGdTI,569
10
- koi_net/lifecycle.py,sha256=AhJCkXHuBhUHMXXAzI3akz0pTRE77aNEHwjsnbe98TE,4775
11
- koi_net/logger.py,sha256=EzpQNvNrbi5LmMCobyuN1_wOz5VuMDeaPbLcyMrLKGI,6172
12
- koi_net/poller.py,sha256=OZLYAMHxXxM75ENetHd_nnNaiiZTSpMgeP3xxAphVEg,1463
13
- koi_net/secure.py,sha256=qayAzO7xWF8wa33rmNCTupVVaYXwNuimlXpPFWJfQT8,4911
14
- koi_net/sentry.py,sha256=9UCVMPoEzua3KMUHe4inciqEnqTF_gNSQO2zhpUN8ts,506
15
- koi_net/server.py,sha256=GJbkHp2BmDhSHWdF6PObLus7f0BiMZuhcZALj7kNiF4,3087
16
- koi_net/utils.py,sha256=4K6BqtifExDUfPP8zJAICgPV1mcabz_MaFB0P0fSnic,411
17
- koi_net/cli/__init__.py,sha256=Vpq0yLN0ROyF0qQYsyiuWFbjs-zsa90G1DpAv13qaiw,25
18
- koi_net/cli/commands.py,sha256=5eVsvJAnHjwJdt8MNYrk5zSzWWm1ooiP35bJeQxYIq4,2592
19
- koi_net/cli/models.py,sha256=ON-rqMgHDng3J2hbBbGYzkynaWc9Tq4QfOJIu_6pFuA,1190
20
- koi_net/interfaces/entrypoint.py,sha256=8FEG1r0YIws_1AojTtIPWB-Th3GOS3U2qi89RlyBJYs,80
21
- koi_net/interfaces/worker.py,sha256=IvtXBTVmthUrURmB9Cn9wffeVv9_Cphsk97_GCLb5NQ,294
22
- koi_net/network/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
- koi_net/network/error_handler.py,sha256=4i_r7EWBW52_bhdmyU-1A_Cnu0Q-jHO9O1EXgO1NGws,1784
24
- koi_net/network/event_queue.py,sha256=JqSMRk_PvBn5hlnUKF2jl9uxaOCX793fwZsblx-pEKs,743
25
- koi_net/network/graph.py,sha256=ZJ1CY-SnYhnZAMm3e9YCbBflk80ZDETnoQKaBk5kLgo,4161
26
- koi_net/network/poll_event_buffer.py,sha256=PO9HnmlhQ0V-uPGOf5b15GhbJtjAzEfMDf6TtsQLtPA,734
27
- koi_net/network/request_handler.py,sha256=XSX-JAqRua42YOakmia--9NnKcT32Fpoc-7aYfjDpwg,6752
28
- koi_net/network/resolver.py,sha256=i8YsdIYVo9--YYW5AK9PO-f_lpXIVKZONImJ9wYMySY,5277
29
- koi_net/network/response_handler.py,sha256=OyEd_5ltQf-sdGDI4QalPuHVLqrSMpAjRQCDtlNR8WU,4216
30
- koi_net/processor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
- koi_net/processor/event_worker.py,sha256=z6Zef5TFDokwywSNzaMh6oDmEaAoss6m--dRHHmU3YY,4190
32
- koi_net/processor/handler.py,sha256=PJlQCPfKm3zYsJrwmGIw5xZmc6vArKz_UoeJuXBj16Y,2356
33
- koi_net/processor/handlers.py,sha256=rGvjrud72szKBM8rhZRrQ2qO8Ng97oGLIfUG9Af-oxw,10934
34
- koi_net/processor/knowledge_object.py,sha256=0VyBOqkCoINMK3fqYhLlXU-Ri7gKEpJloDHfhaGITxg,4172
35
- koi_net/processor/kobj_queue.py,sha256=A4jdS0WCrL-fg3Kl8bHPbzIjSfYNGOBBqzCbSJhfMZ4,1837
36
- koi_net/processor/kobj_worker.py,sha256=26DG8fU3hLbKZmS6mcuOEnUWcVLkq-1fl8AGNLrYFY0,1237
37
- koi_net/processor/pipeline.py,sha256=FpU3nORIeJxJuX8QHTSqIji8iMU69GuTR4UMeThOzUo,8668
38
- koi_net/protocol/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
- koi_net/protocol/api_models.py,sha256=lPd_w-sncyrQlTQ__iae9Li1lFARu8nKiMMlXu7-Hls,1856
40
- koi_net/protocol/consts.py,sha256=bisbVEojPIHlLhkLafBzfIhH25TjNfvTORF1g6YXzIM,243
41
- koi_net/protocol/edge.py,sha256=PzdEhC43T1KO5iMSEu7I4tiz-7sZxtz41dJfWf-oHA0,1034
42
- koi_net/protocol/envelope.py,sha256=4SKF4tP1P1ex7UEmYOJt7IP9_8fCWsa_o6ZBOu8SOKk,1877
43
- koi_net/protocol/errors.py,sha256=uKPQ-TGLouZuK0xd2pXuCQoRTyu_JFsydSCLml13Cz8,595
44
- koi_net/protocol/event.py,sha256=HxzLN-iCXPyr2YzrswMIkgZYeUdFbBpa5v98dAB06lQ,1328
45
- koi_net/protocol/model_map.py,sha256=W0quo25HqVkzp8HQ7l_FNTtN4ZX0u7MIqp68Ir81fuk,1671
46
- koi_net/protocol/node.py,sha256=KH_SjHDzW-V4pn2tqpTDhIzfuCgKgM1YqCafyofLN3k,466
47
- koi_net/protocol/secure.py,sha256=y3-l0ldQ4oQ6ReEmunDy0ncF836kZvLdGFeEgmuJw44,5110
48
- koi_net-1.2.0b2.dist-info/METADATA,sha256=t4T3T0cGyG24XvptQg6vy10B8_gHCWGW-s0PntA9aX8,37347
49
- koi_net-1.2.0b2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
50
- koi_net-1.2.0b2.dist-info/entry_points.txt,sha256=l7He_JTyXrfKIHkttnPWXHI717v8WpLLfCduL5QcEWA,40
51
- koi_net-1.2.0b2.dist-info/licenses/LICENSE,sha256=03mgCL5qth2aD9C3F3qNVs4sFJSpK9kjtYCyOwdSp7s,1069
52
- koi_net-1.2.0b2.dist-info/RECORD,,
File without changes