koi-net 1.1.0b8__py3-none-any.whl → 1.2.0b2__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 (48) hide show
  1. koi_net/__init__.py +2 -1
  2. koi_net/assembler.py +82 -0
  3. koi_net/cli/__init__.py +1 -0
  4. koi_net/cli/commands.py +99 -0
  5. koi_net/cli/models.py +41 -0
  6. koi_net/config.py +34 -0
  7. koi_net/context.py +11 -28
  8. koi_net/core.py +63 -179
  9. koi_net/default_actions.py +10 -1
  10. koi_net/effector.py +61 -34
  11. koi_net/handshaker.py +39 -0
  12. koi_net/identity.py +2 -3
  13. koi_net/interfaces/entrypoint.py +5 -0
  14. koi_net/interfaces/worker.py +17 -0
  15. koi_net/lifecycle.py +85 -48
  16. koi_net/logger.py +176 -0
  17. koi_net/network/error_handler.py +18 -16
  18. koi_net/network/event_queue.py +17 -185
  19. koi_net/network/graph.py +15 -10
  20. koi_net/network/poll_event_buffer.py +26 -0
  21. koi_net/network/request_handler.py +54 -47
  22. koi_net/network/resolver.py +18 -21
  23. koi_net/network/response_handler.py +79 -15
  24. koi_net/poller.py +18 -9
  25. koi_net/processor/event_worker.py +117 -0
  26. koi_net/processor/handler.py +4 -2
  27. koi_net/processor/{default_handlers.py → handlers.py} +109 -59
  28. koi_net/processor/knowledge_object.py +19 -7
  29. koi_net/processor/kobj_queue.py +51 -0
  30. koi_net/processor/kobj_worker.py +44 -0
  31. koi_net/processor/{knowledge_pipeline.py → pipeline.py} +31 -53
  32. koi_net/protocol/api_models.py +7 -3
  33. koi_net/protocol/envelope.py +5 -6
  34. koi_net/protocol/model_map.py +61 -0
  35. koi_net/protocol/node.py +3 -3
  36. koi_net/protocol/secure.py +8 -8
  37. koi_net/secure.py +33 -13
  38. koi_net/sentry.py +13 -0
  39. koi_net/server.py +44 -78
  40. koi_net/utils.py +18 -0
  41. {koi_net-1.1.0b8.dist-info → koi_net-1.2.0b2.dist-info}/METADATA +8 -3
  42. koi_net-1.2.0b2.dist-info/RECORD +52 -0
  43. koi_net-1.2.0b2.dist-info/entry_points.txt +2 -0
  44. koi_net/actor.py +0 -60
  45. koi_net/processor/interface.py +0 -101
  46. koi_net-1.1.0b8.dist-info/RECORD +0 -38
  47. {koi_net-1.1.0b8.dist-info → koi_net-1.2.0b2.dist-info}/WHEEL +0 -0
  48. {koi_net-1.1.0b8.dist-info → koi_net-1.2.0b2.dist-info}/licenses/LICENSE +0 -0
koi_net/__init__.py CHANGED
@@ -1 +1,2 @@
1
- from .core import NodeInterface
1
+ from . import logger
2
+ from . import sentry
koi_net/assembler.py ADDED
@@ -0,0 +1,82 @@
1
+ import inspect
2
+ from typing import Protocol
3
+ from dataclasses import make_dataclass
4
+
5
+ import structlog
6
+
7
+ from .interfaces.entrypoint import EntryPoint
8
+
9
+ log = structlog.stdlib.get_logger()
10
+
11
+
12
+ class BuildOrderer(type):
13
+ def __new__(cls, name: str, bases: tuple, dct: dict[str]):
14
+ """Sets `cls._build_order` from component order in class definition."""
15
+ cls = super().__new__(cls, name, bases, dct)
16
+
17
+ if "_build_order" not in dct:
18
+ components = {}
19
+ # adds components from base classes (including cls)
20
+ for base in reversed(inspect.getmro(cls)[:-1]):
21
+ for k, v in vars(base).items():
22
+ # excludes built in and private attributes
23
+ if not k.startswith("_"):
24
+ components[k] = v
25
+
26
+ # recipe list constructed from names of non-None components
27
+ cls._build_order = [
28
+ name for name, _type in components.items()
29
+ if _type is not None
30
+ ]
31
+
32
+ return cls
33
+
34
+ class NodeContainer(Protocol):
35
+ entrypoint = EntryPoint
36
+
37
+ class NodeAssembler(metaclass=BuildOrderer):
38
+ def __new__(self) -> NodeContainer:
39
+ return self._build()
40
+
41
+ @classmethod
42
+ def _build(cls) -> NodeContainer:
43
+ components = {}
44
+ for comp_name in cls._build_order:
45
+ comp_factory = getattr(cls, comp_name, None)
46
+
47
+ if comp_factory is None:
48
+ raise Exception(f"Couldn't find factory for component '{comp_name}'")
49
+
50
+ sig = inspect.signature(comp_factory)
51
+
52
+ required_comps = []
53
+ for name, param in sig.parameters.items():
54
+ required_comps.append((name, param.annotation))
55
+
56
+ if len(required_comps) == 0:
57
+ s = comp_name
58
+ else:
59
+ s = f"{comp_name} -> {', '.join([name for name, _type in required_comps])}"
60
+
61
+ print(s.replace("graph", "_graph"), end=";\n")
62
+
63
+ dependencies = {}
64
+ for req_comp_name, req_comp_type in required_comps:
65
+ if req_comp_name not in components:
66
+ raise Exception(f"Couldn't find required component '{req_comp_name}'")
67
+
68
+ dependencies[req_comp_name] = components[req_comp_name]
69
+
70
+ components[comp_name] = comp_factory(**dependencies)
71
+
72
+ NodeContainer = make_dataclass(
73
+ cls_name="NodeContainer",
74
+ fields=[
75
+ (name, type(component))
76
+ for name, component
77
+ in components.items()
78
+ ],
79
+ frozen=True
80
+ )
81
+
82
+ return NodeContainer(**components)
@@ -0,0 +1 @@
1
+ from .commands import app
@@ -0,0 +1,99 @@
1
+ import os
2
+ import typer
3
+ from typing import Callable
4
+ from rich.console import Console
5
+ from rich.table import Table
6
+
7
+ from importlib.metadata import entry_points
8
+
9
+ from koi_net.cli.models import KoiNetworkConfig
10
+ from koi_net.core import NodeInterface
11
+ import shutil
12
+
13
+ app = typer.Typer()
14
+ console = Console()
15
+
16
+ installed_nodes = entry_points(group='koi_net.node')
17
+
18
+ net_config = KoiNetworkConfig.load_from_yaml()
19
+
20
+ @app.command()
21
+ def list_node_types():
22
+ table = Table(title="installed node types")
23
+ table.add_column("name", style="cyan")
24
+ table.add_column("module", style="magenta")
25
+
26
+ for node in installed_nodes:
27
+ table.add_row(node.name, node.module)
28
+ console.print(table)
29
+
30
+ @app.command()
31
+ def list_nodes():
32
+ table = Table(title="created nodes")
33
+ table.add_column("name", style="cyan")
34
+ table.add_column("rid", style="magenta")
35
+
36
+ for dir in os.listdir('.'):
37
+ if not os.path.isdir(dir):
38
+ continue
39
+ for file in os.listdir(dir):
40
+ file_path = os.path.join(dir, file)
41
+ if not (os.path.isfile(file_path) and file == "config.yaml"):
42
+ continue
43
+
44
+ print(os.getcwd())
45
+ os.chdir(dir)
46
+ print(os.getcwd())
47
+
48
+ node_type = net_config.nodes.get(dir)
49
+
50
+ ep = list(installed_nodes.select(name=node_type))[0]
51
+ create_node: Callable[[], NodeInterface] = ep.load()
52
+
53
+ node = create_node()
54
+
55
+ print(ep)
56
+ print(dir)
57
+ print(node.identity.rid)
58
+
59
+ table.add_row(dir, str(node.identity.rid))
60
+
61
+ os.chdir('..')
62
+ print(os.getcwd())
63
+
64
+ console.print(table)
65
+
66
+ @app.command()
67
+ def create(type: str, name: str):
68
+ # if name not in installed_nodes:
69
+ # console.print(f"[bold red]Error:[/bold red] node type '{name}' doesn't exist")
70
+ # raise typer.Exit(code=1)
71
+
72
+ eps = installed_nodes.select(name=type)
73
+ if eps:
74
+ ep = list(eps)[0]
75
+
76
+ os.mkdir(name)
77
+ os.chdir(name)
78
+
79
+ ep.load()
80
+
81
+ os.chdir('..')
82
+
83
+ net_config.nodes[name] = type
84
+ net_config.save_to_yaml()
85
+
86
+ @app.command()
87
+ def remove(name: str):
88
+ shutil.rmtree(name)
89
+ net_config.nodes.pop(name, None)
90
+ net_config.save_to_yaml()
91
+
92
+ @app.command()
93
+ def start(name: str):
94
+ os.chdir(name)
95
+ node_type = net_config.nodes.get(name)
96
+ ep = list(installed_nodes.select(name=node_type))[0]
97
+ create_node: Callable[[], NodeInterface] = ep.load()
98
+
99
+ create_node().server.run()
koi_net/cli/models.py ADDED
@@ -0,0 +1,41 @@
1
+ from pydantic import BaseModel, Field, PrivateAttr
2
+ from ruamel.yaml import YAML
3
+
4
+
5
+ class KoiNetworkConfig(BaseModel):
6
+ nodes: dict[str, str] = Field(default_factory=dict)
7
+ _file_path: str = PrivateAttr(default="koi-net-config.yaml")
8
+
9
+ @classmethod
10
+ def load_from_yaml(
11
+ cls,
12
+ file_path: str = "koi-net-config.yaml",
13
+ ):
14
+ yaml = YAML()
15
+
16
+ try:
17
+ with open(file_path, "r") as f:
18
+ file_content = f.read()
19
+ config_data = yaml.load(file_content)
20
+ config = cls.model_validate(config_data)
21
+
22
+ except FileNotFoundError:
23
+ config = cls()
24
+
25
+ config._file_path = file_path
26
+ config.save_to_yaml()
27
+ return config
28
+
29
+ def save_to_yaml(self):
30
+ yaml = YAML()
31
+
32
+ with open(self._file_path, "w") as f:
33
+ try:
34
+ config_data = self.model_dump(mode="json")
35
+ yaml.dump(config_data, f)
36
+ except Exception as e:
37
+ if self._file_content:
38
+ f.seek(0)
39
+ f.truncate()
40
+ f.write(self._file_content)
41
+ raise e
koi_net/config.py CHANGED
@@ -1,4 +1,5 @@
1
1
  import os
2
+ from rid_lib import RIDType
2
3
  from ruamel.yaml import YAML
3
4
  from pydantic import BaseModel, Field, PrivateAttr
4
5
  from dotenv import load_dotenv
@@ -9,6 +10,8 @@ from .protocol.node import NodeProfile, NodeType
9
10
 
10
11
 
11
12
  class ServerConfig(BaseModel):
13
+ """Config for the node server (full node only)."""
14
+
12
15
  host: str = "127.0.0.1"
13
16
  port: int = 8000
14
17
  path: str | None = "/koi-net"
@@ -22,10 +25,15 @@ class NodeContact(BaseModel):
22
25
  url: str | None = None
23
26
 
24
27
  class KoiNetConfig(BaseModel):
28
+ """Config for KOI-net."""
29
+
25
30
  node_name: str
26
31
  node_rid: KoiNetNode | None = None
27
32
  node_profile: NodeProfile
28
33
 
34
+ rid_types_of_interest: list[RIDType] = Field(
35
+ default_factory=lambda: [KoiNetNode])
36
+
29
37
  cache_directory_path: str = ".rid_cache"
30
38
  event_queues_path: str = "event_queues.json"
31
39
  private_key_pem_path: str = "priv_key.pem"
@@ -36,6 +44,15 @@ class KoiNetConfig(BaseModel):
36
44
  _priv_key: PrivateKey | None = PrivateAttr(default=None)
37
45
 
38
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
+
39
56
  priv_key_password: str | None = "PRIV_KEY_PASSWORD"
40
57
 
41
58
  def __init__(self, **kwargs):
@@ -52,6 +69,12 @@ class EnvConfig(BaseModel):
52
69
  return value
53
70
 
54
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
+
55
78
  server: ServerConfig = Field(default_factory=ServerConfig)
56
79
  koi_net: KoiNetConfig
57
80
  env: EnvConfig = Field(default_factory=EnvConfig)
@@ -65,6 +88,12 @@ class NodeConfig(BaseModel):
65
88
  file_path: str = "config.yaml",
66
89
  generate_missing: bool = True
67
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
+ """
68
97
  yaml = YAML()
69
98
 
70
99
  try:
@@ -112,6 +141,11 @@ class NodeConfig(BaseModel):
112
141
  return config
113
142
 
114
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
+
115
149
  yaml = YAML()
116
150
 
117
151
  with open(self._file_path, "w") as f:
koi_net/context.py CHANGED
@@ -1,45 +1,35 @@
1
1
  from rid_lib.ext import Cache
2
2
 
3
+ from koi_net.effector import Effector
3
4
  from koi_net.network.resolver import NetworkResolver
4
5
  from .config import NodeConfig
5
- from .effector import Effector
6
6
  from .network.graph import NetworkGraph
7
- from .network.event_queue import NetworkEventQueue
7
+ from .network.event_queue import EventQueue
8
8
  from .network.request_handler import RequestHandler
9
9
  from .identity import NodeIdentity
10
- from .processor.interface import ProcessorInterface
10
+ from .processor.kobj_queue import KobjQueue
11
11
 
12
12
 
13
- class ActionContext:
14
- identity: NodeIdentity
15
- effector: Effector
16
-
17
- def __init__(
18
- self,
19
- identity: NodeIdentity,
20
- effector: Effector
21
- ):
22
- self.identity = identity
23
- self.effector = effector
24
-
25
-
26
13
  class HandlerContext:
14
+ """Provides knowledge handlers access to other subsystems."""
15
+
27
16
  identity: NodeIdentity
28
17
  config: NodeConfig
29
18
  cache: Cache
30
- event_queue: NetworkEventQueue
19
+ event_queue: EventQueue
20
+ kobj_queue: KobjQueue
31
21
  graph: NetworkGraph
32
22
  request_handler: RequestHandler
33
23
  resolver: NetworkResolver
34
24
  effector: Effector
35
- _processor: ProcessorInterface | None
36
25
 
37
26
  def __init__(
38
27
  self,
39
28
  identity: NodeIdentity,
40
29
  config: NodeConfig,
41
30
  cache: Cache,
42
- event_queue: NetworkEventQueue,
31
+ event_queue: EventQueue,
32
+ kobj_queue: KobjQueue,
43
33
  graph: NetworkGraph,
44
34
  request_handler: RequestHandler,
45
35
  resolver: NetworkResolver,
@@ -49,15 +39,8 @@ class HandlerContext:
49
39
  self.config = config
50
40
  self.cache = cache
51
41
  self.event_queue = event_queue
42
+ self.kobj_queue = kobj_queue
52
43
  self.graph = graph
53
44
  self.request_handler = request_handler
54
45
  self.resolver = resolver
55
- self.effector = effector
56
- self._processor = None
57
-
58
- def set_processor(self, processor: ProcessorInterface):
59
- self._processor = processor
60
-
61
- @property
62
- def handle(self):
63
- return self._processor.handle
46
+ self.effector = effector
koi_net/core.py CHANGED
@@ -1,194 +1,78 @@
1
- import logging
2
- from typing import Generic, TypeVar
3
1
  from rid_lib.ext import Cache
4
- from .network.resolver import NetworkResolver
5
- from .network.event_queue import NetworkEventQueue
2
+ from .assembler import NodeAssembler
3
+ from .config.base import BaseConfig
4
+ from .context import HandlerContext
5
+ from .effector import Effector
6
+ from .handshaker import Handshaker
7
+ from .identity import NodeIdentity
8
+ from .processor.kobj_worker import KnowledgeProcessingWorker
9
+ from .lifecycle import NodeLifecycle
10
+ from .network.error_handler import ErrorHandler
11
+ from .network.event_queue import EventQueue
6
12
  from .network.graph import NetworkGraph
7
13
  from .network.request_handler import RequestHandler
14
+ from .network.resolver import NetworkResolver
8
15
  from .network.response_handler import ResponseHandler
9
- from .network.error_handler import ErrorHandler
10
- from .actor import Actor
11
- from .processor.interface import ProcessorInterface
12
- from .processor import default_handlers
13
- from .processor.handler import KnowledgeHandler
14
- from .processor.knowledge_pipeline import KnowledgePipeline
15
- from .identity import NodeIdentity
16
+ from .network.poll_event_buffer import PollEventBuffer
17
+ from .poller import NodePoller
18
+ from .processor.handlers import (
19
+ basic_manifest_handler,
20
+ basic_network_output_filter,
21
+ basic_rid_handler,
22
+ node_contact_handler,
23
+ edge_negotiation_handler,
24
+ forget_edge_on_node_deletion,
25
+ secure_profile_handler
26
+ )
27
+ from .processor.event_worker import EventProcessingWorker
28
+ from .processor.pipeline import KnowledgePipeline
29
+ from .processor.kobj_queue import KobjQueue
16
30
  from .secure import Secure
17
- from .config import NodeConfig
18
- from .context import HandlerContext, ActionContext
19
- from .effector import Effector
20
31
  from .server import NodeServer
21
- from .lifecycle import NodeLifecycle
22
- from .poller import NodePoller
23
- from . import default_actions
24
-
25
- logger = logging.getLogger(__name__)
26
-
27
-
28
- T = TypeVar("T", bound=NodeConfig)
29
32
 
30
- class NodeInterface(Generic[T]):
31
- config: T
32
- cache: Cache
33
- identity: NodeIdentity
34
- resolver: NetworkResolver
35
- event_queue: NetworkEventQueue
36
- graph: NetworkGraph
37
- processor: ProcessorInterface
38
- secure: Secure
39
- server: NodeServer
40
-
41
- use_kobj_processor_thread: bool
42
-
43
- def __init__(
44
- self,
45
- config: T,
46
- use_kobj_processor_thread: bool = False,
47
- handlers: list[KnowledgeHandler] | None = None,
48
-
49
- CacheOverride: type[Cache] | None = None,
50
- NodeIdentityOverride: type[NodeIdentity] | None = None,
51
- EffectorOverride: type[Effector] | None = None,
52
- NetworkGraphOverride: type[NetworkGraph] | None = None,
53
- SecureOverride: type[Secure] | None = None,
54
- RequestHandlerOverride: type[RequestHandler] | None = None,
55
- ResponseHandlerOverride: type[ResponseHandler] | None = None,
56
- NetworkResolverOverride: type[NetworkResolver] | None = None,
57
- NetworkEventQueueOverride: type[NetworkEventQueue] | None = None,
58
- ActorOverride: type[Actor] | None = None,
59
- ActionContextOverride: type[ActionContext] | None = None,
60
- HandlerContextOverride: type[HandlerContext] | None = None,
61
- KnowledgePipelineOverride: type[KnowledgePipeline] | None = None,
62
- ProcessorInterfaceOverride: type[ProcessorInterface] | None = None,
63
- ErrorHandlerOverride: type[ErrorHandler] | None = None,
64
- NodeLifecycleOverride: type[NodeLifecycle] | None = None,
65
- NodeServerOverride: type[NodeServer] | None = None,
66
- NodePollerOverride: type[NodePoller] | None = None,
67
- ):
68
- self.config = config
69
- self.cache = (CacheOverride or Cache)(
70
- directory_path=self.config.koi_net.cache_directory_path
71
- )
72
33
 
73
- self.identity = (NodeIdentityOverride or NodeIdentity)(config=self.config)
74
- self.effector = (EffectorOverride or Effector)(cache=self.cache)
34
+ # factory functions for components with non standard initializiation
75
35
 
76
- self.graph = (NetworkGraphOverride or NetworkGraph)(
77
- cache=self.cache,
78
- identity=self.identity
79
- )
36
+ def make_config() -> BaseConfig:
37
+ return BaseConfig.load_from_yaml()
80
38
 
81
- self.secure = (SecureOverride or Secure)(
82
- identity=self.identity,
83
- effector=self.effector,
84
- config=self.config
85
- )
39
+ def make_cache(config: BaseConfig) -> Cache:
40
+ return Cache(directory_path=config.koi_net.cache_directory_path)
86
41
 
87
- self.request_handler = (RequestHandlerOverride or RequestHandler)(
88
- effector=self.effector,
89
- identity=self.identity,
90
- secure=self.secure
91
- )
92
42
 
93
- self.response_handler = (ResponseHandlerOverride or ResponseHandler)(self.cache, self.effector)
43
+ class BaseNode(NodeAssembler):
44
+ config = lambda: None
45
+ kobj_queue = KobjQueue
46
+ event_queue = EventQueue
47
+ poll_event_buf = PollEventBuffer
48
+ knowledge_handlers = lambda: [
49
+ basic_rid_handler,
50
+ basic_manifest_handler,
51
+ secure_profile_handler,
52
+ edge_negotiation_handler,
53
+ node_contact_handler,
54
+ basic_network_output_filter,
55
+ forget_edge_on_node_deletion
56
+ ]
57
+ cache = make_cache
58
+ identity = NodeIdentity
59
+ graph = NetworkGraph
60
+ secure = Secure
61
+ handshaker = Handshaker
62
+ error_handler = ErrorHandler
63
+ request_handler = RequestHandler
64
+ response_handler = ResponseHandler
65
+ resolver = NetworkResolver
66
+ effector = Effector
67
+ handler_context = HandlerContext
68
+ pipeline = KnowledgePipeline
69
+ kobj_worker = KnowledgeProcessingWorker
70
+ event_worker = EventProcessingWorker
71
+ lifecycle = NodeLifecycle
94
72
 
95
- self.resolver = (NetworkResolverOverride or NetworkResolver)(
96
- config=self.config,
97
- cache=self.cache,
98
- identity=self.identity,
99
- graph=self.graph,
100
- request_handler=self.request_handler,
101
- effector=self.effector
102
- )
103
73
 
104
- self.event_queue = (NetworkEventQueueOverride or NetworkEventQueue)(
105
- config=self.config,
106
- cache=self.cache,
107
- identity=self.identity,
108
- graph=self.graph,
109
- request_handler=self.request_handler,
110
- effector=self.effector
111
- )
112
-
113
- self.actor = (ActorOverride or Actor)()
114
-
115
- # pull all handlers defined in default_handlers module
116
- if handlers is None:
117
- handlers = [
118
- obj for obj in vars(default_handlers).values()
119
- if isinstance(obj, KnowledgeHandler)
120
- ]
74
+ class FullNode(BaseNode):
75
+ entrypoint = NodeServer
121
76
 
122
- self.use_kobj_processor_thread = use_kobj_processor_thread
123
-
124
- self.action_context = (ActionContextOverride or ActionContext)(
125
- identity=self.identity,
126
- effector=self.effector
127
- )
128
-
129
- self.handler_context = (HandlerContextOverride or HandlerContext)(
130
- identity=self.identity,
131
- config=self.config,
132
- cache=self.cache,
133
- event_queue=self.event_queue,
134
- graph=self.graph,
135
- request_handler=self.request_handler,
136
- resolver=self.resolver,
137
- effector=self.effector
138
- )
139
-
140
- self.pipeline = (KnowledgePipelineOverride or KnowledgePipeline)(
141
- handler_context=self.handler_context,
142
- cache=self.cache,
143
- request_handler=self.request_handler,
144
- event_queue=self.event_queue,
145
- graph=self.graph,
146
- default_handlers=handlers
147
- )
148
-
149
- self.processor = (ProcessorInterfaceOverride or ProcessorInterface)(
150
- pipeline=self.pipeline,
151
- use_kobj_processor_thread=self.use_kobj_processor_thread
152
- )
153
-
154
- self.error_handler = (ErrorHandlerOverride or ErrorHandler)(
155
- processor=self.processor,
156
- actor=self.actor
157
- )
158
-
159
- self.request_handler.set_error_handler(self.error_handler)
160
-
161
- self.handler_context.set_processor(self.processor)
162
-
163
- self.effector.set_processor(self.processor)
164
- self.effector.set_resolver(self.resolver)
165
- self.effector.set_action_context(self.action_context)
166
-
167
- self.actor.set_ctx(self.handler_context)
168
-
169
- self.lifecycle = (NodeLifecycleOverride or NodeLifecycle)(
170
- config=self.config,
171
- identity=self.identity,
172
- graph=self.graph,
173
- processor=self.processor,
174
- effector=self.effector,
175
- actor=self.actor,
176
- use_kobj_processor_thread=use_kobj_processor_thread
177
- )
178
-
179
- # if self.config.koi_net.node_profile.node_type == NodeType.FULL:
180
- self.server = (NodeServerOverride or NodeServer)(
181
- config=self.config,
182
- lifecycle=self.lifecycle,
183
- secure=self.secure,
184
- processor=self.processor,
185
- event_queue=self.event_queue,
186
- response_handler=self.response_handler
187
- )
188
-
189
- self.poller = (NodePollerOverride or NodePoller)(
190
- processor=self.processor,
191
- lifecycle=self.lifecycle,
192
- resolver=self.resolver,
193
- config=self.config
194
- )
77
+ class PartialNode(BaseNode):
78
+ entrypoint = NodePoller
@@ -1,3 +1,5 @@
1
+ """Implementations of default dereference actions."""
2
+
1
3
  from .context import ActionContext
2
4
  from rid_lib.types import KoiNetNode
3
5
  from rid_lib.ext import Bundle
@@ -5,7 +7,14 @@ from .effector import Effector
5
7
 
6
8
 
7
9
  @Effector.register_default_action(KoiNetNode)
8
- def dereference_koi_node(ctx: ActionContext, rid: KoiNetNode) -> Bundle:
10
+ def dereference_koi_node(
11
+ ctx: ActionContext, rid: KoiNetNode
12
+ ) -> Bundle | None:
13
+ """Dereference function for this KOI node.
14
+
15
+ Generates a bundle from this node's profile data in the config.
16
+ """
17
+
9
18
  if rid != ctx.identity.rid:
10
19
  return
11
20