Skip to content

Commit ab4eb0c

Browse files
committed
refined node assembler, parses through all base classes in reverse order to construct _build_order, moved base, partial, and full node defintions back to core.py. marking for 1.2.0b2 release
1 parent 5aed08c commit ab4eb0c

File tree

4 files changed

+74
-337
lines changed

4 files changed

+74
-337
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "koi-net"
7-
version = "1.2.0b1"
7+
version = "1.2.0b2"
88
description = "Implementation of KOI-net protocol in Python"
99
authors = [
1010
{name = "Luke Miller", email = "luke@block.science"}

src/koi_net/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
1-
from .core import NodeContainer
21
from . import logger
32
from . import sentry

src/koi_net/assembler.py

Lines changed: 22 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -4,61 +4,25 @@
44

55
import structlog
66

7-
from rid_lib.ext import Cache
8-
from koi_net.config import NodeConfig
9-
from koi_net.context import HandlerContext
10-
from koi_net.core import NodeContainer
11-
from koi_net.effector import Effector
12-
from koi_net.handshaker import Handshaker
13-
from koi_net.identity import NodeIdentity
14-
from koi_net.interfaces.entrypoint import EntryPoint
15-
from koi_net.processor.kobj_worker import KnowledgeProcessingWorker
16-
from koi_net.lifecycle import NodeLifecycle
17-
from koi_net.network.error_handler import ErrorHandler
18-
from koi_net.network.event_queue import EventQueue
19-
from koi_net.network.graph import NetworkGraph
20-
from koi_net.network.request_handler import RequestHandler
21-
from koi_net.network.resolver import NetworkResolver
22-
from koi_net.network.response_handler import ResponseHandler
23-
from koi_net.network.poll_event_buffer import PollEventBuffer
24-
from koi_net.poller import NodePoller
25-
from koi_net.processor.handlers import (
26-
basic_manifest_handler,
27-
basic_network_output_filter,
28-
basic_rid_handler,
29-
node_contact_handler,
30-
edge_negotiation_handler,
31-
forget_edge_on_node_deletion,
32-
secure_profile_handler
33-
)
34-
from koi_net.processor.event_worker import EventProcessingWorker
35-
from koi_net.processor.pipeline import KnowledgePipeline
36-
from koi_net.processor.kobj_queue import KobjQueue
37-
from koi_net.secure import Secure
38-
from koi_net.server import NodeServer
7+
from .interfaces.entrypoint import EntryPoint
398

409
log = structlog.stdlib.get_logger()
4110

4211

4312
class BuildOrderer(type):
4413
def __new__(cls, name: str, bases: tuple, dct: dict[str]):
14+
"""Sets `cls._build_order` from component order in class definition."""
4515
cls = super().__new__(cls, name, bases, dct)
4616

47-
def safe_update(d1: dict[str], d2: dict[str]):
48-
for k, v in d2.items():
49-
# excludes private and reserved attributes
50-
if not k.startswith("_"):
51-
d1[k] = v
52-
5317
if "_build_order" not in dct:
5418
components = {}
55-
for base in bases:
56-
# adds components from base classes
57-
safe_update(components, vars(base))
58-
59-
# adds components from this class
60-
safe_update(components, dct)
61-
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+
6226
# recipe list constructed from names of non-None components
6327
cls._build_order = [
6428
name for name, _type in components.items()
@@ -67,7 +31,6 @@ def safe_update(d1: dict[str], d2: dict[str]):
6731

6832
return cls
6933

70-
7134
class NodeContainer(Protocol):
7235
entrypoint = EntryPoint
7336

@@ -78,32 +41,33 @@ def __new__(self) -> NodeContainer:
7841
@classmethod
7942
def _build(cls) -> NodeContainer:
8043
components = {}
81-
for comp_name in cls._build_order:
82-
log.info(f"Assembling component '{comp_name}'")
83-
44+
for comp_name in cls._build_order:
8445
comp_factory = getattr(cls, comp_name, None)
8546

8647
if comp_factory is None:
87-
log.error("Couldn't find factory for component")
88-
return
48+
raise Exception(f"Couldn't find factory for component '{comp_name}'")
8949

9050
sig = inspect.signature(comp_factory)
9151

9252
required_comps = []
9353
for name, param in sig.parameters.items():
9454
required_comps.append((name, param.annotation))
9555

96-
log.info(f"Component requires {[d[0] for d in required_comps]}")
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])}"
9760

98-
kwargs = {}
61+
print(s.replace("graph", "_graph"), end=";\n")
62+
63+
dependencies = {}
9964
for req_comp_name, req_comp_type in required_comps:
100-
comp = components.get(req_comp_name)
101-
if not comp:
102-
log.error(f"failed to resolve dependency {req_comp_name}")
65+
if req_comp_name not in components:
66+
raise Exception(f"Couldn't find required component '{req_comp_name}'")
10367

104-
kwargs[req_comp_name] = comp
68+
dependencies[req_comp_name] = components[req_comp_name]
10569

106-
components[comp_name] = comp_factory(**kwargs)
70+
components[comp_name] = comp_factory(**dependencies)
10771

10872
NodeContainer = make_dataclass(
10973
cls_name="NodeContainer",
@@ -116,62 +80,3 @@ def _build(cls) -> NodeContainer:
11680
)
11781

11882
return NodeContainer(**components)
119-
120-
121-
122-
def make_config() -> NodeConfig:
123-
return NodeConfig.load_from_yaml()
124-
125-
def make_cache(config: NodeConfig) -> Cache:
126-
return Cache(directory_path=config.koi_net.cache_directory_path)
127-
128-
129-
class BaseNode(NodeAssembler):
130-
config = make_config
131-
kobj_queue = KobjQueue
132-
event_queue = EventQueue
133-
poll_event_buf = PollEventBuffer
134-
knowledge_handlers = lambda: [
135-
basic_rid_handler,
136-
basic_manifest_handler,
137-
secure_profile_handler,
138-
edge_negotiation_handler,
139-
node_contact_handler,
140-
basic_network_output_filter,
141-
forget_edge_on_node_deletion
142-
]
143-
cache = make_cache
144-
identity = NodeIdentity
145-
graph = NetworkGraph
146-
secure = Secure
147-
handshaker = Handshaker
148-
error_handler = ErrorHandler
149-
request_handler = RequestHandler
150-
response_handler = ResponseHandler
151-
resolver = NetworkResolver
152-
effector = Effector
153-
handler_context = HandlerContext
154-
pipeline = KnowledgePipeline
155-
kobj_worker = KnowledgeProcessingWorker
156-
event_worker = EventProcessingWorker
157-
lifecycle = NodeLifecycle
158-
server = NodeServer
159-
160-
class FullNode(BaseNode):
161-
entrypoint = NodeServer
162-
163-
class PartialNode(BaseNode):
164-
entrypoint = NodePoller
165-
166-
167-
if __name__ == "__main__":
168-
print("Full Node:")
169-
for n, name in enumerate(FullNode._build_order):
170-
print(f"{n}. {name}")
171-
172-
print("Partial Node:")
173-
for n, name in enumerate(PartialNode._build_order):
174-
print(f"{n}. {name}")
175-
176-
partial_node = PartialNode()
177-
full_node = FullNode()

0 commit comments

Comments
 (0)