Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,8 @@ examples = [
"rich",
]

[project.scripts]
koi = "koi_net.cli:app"

[project.urls]
Homepage = "https://github.com/BlockScience/koi-net/"
1 change: 1 addition & 0 deletions src/koi_net/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .commands import app
99 changes: 99 additions & 0 deletions src/koi_net/cli/commands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import os
import typer
from typing import Callable
from rich.console import Console
from rich.table import Table

from importlib.metadata import entry_points

from koi_net.cli.models import KoiNetworkConfig
from koi_net.core import NodeInterface
import shutil

app = typer.Typer()
console = Console()

installed_nodes = entry_points(group='koi_net.node')

net_config = KoiNetworkConfig.load_from_yaml()

@app.command()
def list_node_types():
table = Table(title="installed node types")
table.add_column("name", style="cyan")
table.add_column("module", style="magenta")

for node in installed_nodes:
table.add_row(node.name, node.module)
console.print(table)

@app.command()
def list_nodes():
table = Table(title="created nodes")
table.add_column("name", style="cyan")
table.add_column("rid", style="magenta")

for dir in os.listdir('.'):
if not os.path.isdir(dir):
continue
for file in os.listdir(dir):
file_path = os.path.join(dir, file)
if not (os.path.isfile(file_path) and file == "config.yaml"):
continue

print(os.getcwd())
os.chdir(dir)
print(os.getcwd())

node_type = net_config.nodes.get(dir)

ep = list(installed_nodes.select(name=node_type))[0]
create_node: Callable[[], NodeInterface] = ep.load()

node = create_node()

print(ep)
print(dir)
print(node.identity.rid)

table.add_row(dir, str(node.identity.rid))

os.chdir('..')
print(os.getcwd())

console.print(table)

@app.command()
def create(type: str, name: str):
# if name not in installed_nodes:
# console.print(f"[bold red]Error:[/bold red] node type '{name}' doesn't exist")
# raise typer.Exit(code=1)

eps = installed_nodes.select(name=type)
if eps:
ep = list(eps)[0]

os.mkdir(name)
os.chdir(name)

ep.load()

os.chdir('..')

net_config.nodes[name] = type
net_config.save_to_yaml()

@app.command()
def remove(name: str):
shutil.rmtree(name)
net_config.nodes.pop(name, None)
net_config.save_to_yaml()

@app.command()
def start(name: str):
os.chdir(name)
node_type = net_config.nodes.get(name)
ep = list(installed_nodes.select(name=node_type))[0]
create_node: Callable[[], NodeInterface] = ep.load()

create_node().server.run()
41 changes: 41 additions & 0 deletions src/koi_net/cli/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from pydantic import BaseModel, Field, PrivateAttr
from ruamel.yaml import YAML


class KoiNetworkConfig(BaseModel):
nodes: dict[str, str] = Field(default_factory=dict)
_file_path: str = PrivateAttr(default="koi-net-config.yaml")

@classmethod
def load_from_yaml(
cls,
file_path: str = "koi-net-config.yaml",
):
yaml = YAML()

try:
with open(file_path, "r") as f:
file_content = f.read()
config_data = yaml.load(file_content)
config = cls.model_validate(config_data)

except FileNotFoundError:
config = cls()

config._file_path = file_path
config.save_to_yaml()
return config

def save_to_yaml(self):
yaml = YAML()

with open(self._file_path, "w") as f:
try:
config_data = self.model_dump(mode="json")
yaml.dump(config_data, f)
except Exception as e:
if self._file_content:
f.seek(0)
f.truncate()
f.write(self._file_content)
raise e