Make sure plugins are loaded when printiung help or usages

This commit is contained in:
Sleepy Monax 2024-02-19 15:29:03 +01:00
parent 7743b566bd
commit 886c90dd6f
6 changed files with 52 additions and 17 deletions

View file

@ -3,7 +3,6 @@ import logging
import dataclasses as dt import dataclasses as dt
from pathlib import Path from pathlib import Path
import sys
from typing import Callable, Literal, TextIO, Union from typing import Callable, Literal, TextIO, Union
from . import cli, shell, rules, model, ninja, const, vt100 from . import cli, shell, rules, model, ninja, const, vt100

View file

@ -1,8 +1,8 @@
import sys
from enum import Enum from enum import Enum
from types import GenericAlias from types import GenericAlias
import typing as tp import typing as tp
import dataclasses as dt import dataclasses as dt
import logging
from typing import Any, Callable, Optional, Union from typing import Any, Callable, Optional, Union
from cutekit import vt100, const from cutekit import vt100, const
@ -10,6 +10,8 @@ from cutekit import vt100, const
T = tp.TypeVar("T") T = tp.TypeVar("T")
_logger = logging.getLogger(__name__)
# --- Scan -------------------------------------------------------------- # # --- Scan -------------------------------------------------------------- #
@ -542,6 +544,7 @@ class Command:
callable: Optional[tp.Callable] = None callable: Optional[tp.Callable] = None
subcommands: dict[str, "Command"] = dt.field(default_factory=dict) subcommands: dict[str, "Command"] = dt.field(default_factory=dict)
populated: bool = False populated: bool = False
path: list[str] = dt.field(default_factory=list)
def _spliceArgs(self, args: list[str]) -> tuple[list[str], list[str]]: def _spliceArgs(self, args: list[str]) -> tuple[list[str], list[str]]:
rest = args[:] rest = args[:]
@ -554,12 +557,12 @@ class Command:
rest = [] rest = []
return curr, rest return curr, rest
def help(self, cmd): def help(self):
vt100.title(f"{cmd}") vt100.title(f"{self.longName}")
print() print()
vt100.subtitle("Usage") vt100.subtitle("Usage")
print(vt100.indent(f"{cmd}{self.usage()}")) print(vt100.indent(f"{' '.join(self.path)}{self.usage()}"))
print() print()
vt100.subtitle("Description") vt100.subtitle("Description")
@ -631,23 +634,38 @@ class Command:
return sub return sub
raise ValueError(f"Unknown subcommand '{name}'") raise ValueError(f"Unknown subcommand '{name}'")
def invoke(self, argv: list[str]):
if self.callable:
if self.schema:
args = self.schema.parse(argv)
self.callable(args)
else:
self.callable()
def eval(self, args: list[str]): def eval(self, args: list[str]):
cmd = args.pop(0) cmd = args.pop(0)
curr, rest = self._spliceArgs(args) curr, rest = self._spliceArgs(args)
if "-h" in curr or "--help" in curr: if "-h" in curr or "--help" in curr:
self.help(cmd) if len(self.path) == 0:
# HACK: This is a special case for the root command
# it need to always be run because it might
# load some plugins that will register subcommands
# that need to be displayed in the help.
self.invoke([])
self.help()
return return
if "-u" in curr or "--usage" in curr: if "-u" in curr or "--usage" in curr:
if len(self.path) == 0:
# HACK: Same as the help flag, the root command needs to be
# always run to load plugins
self.invoke([])
print("Usage: " + cmd + self.usage(), end="\n\n") print("Usage: " + cmd + self.usage(), end="\n\n")
return return
try: try:
if self.callable: self.invoke(curr)
if self.schema:
args = self.schema.parse(curr)
self.callable(args)
else:
self.callable()
if self.subcommands: if self.subcommands:
if len(rest) > 0: if len(rest) > 0:
@ -692,14 +710,18 @@ def command(shortName: Optional[str], longName: str, description: str = "") -> C
schema = Schema.extractFromCallable(fn) schema = Schema.extractFromCallable(fn)
path = _splitPath(longName) path = _splitPath(longName)
cmd = _resolvePath(path) cmd = _resolvePath(path)
_logger.info(f"Registering command '{'.'.join(path)}'")
if cmd.populated: if cmd.populated:
raise ValueError(f"Command '{longName}' is already defined") raise ValueError(f"Command '{longName}' is already defined")
cmd.shortName = shortName cmd.shortName = shortName
cmd.longName = len(path) > 0 and path[-1] or "" cmd.longName = len(path) > 0 and path[-1] or ""
cmd.description = description cmd.description = description
cmd.schema = schema cmd.schema = schema
cmd.callable = fn cmd.callable = fn
cmd.populated = True cmd.populated = True
cmd.path = [const.ARGV0] + path
return fn return fn
return wrap return wrap

View file

@ -565,6 +565,8 @@ class Registry(DataClassJsonMixin):
@staticmethod @staticmethod
def load(project: Project, mixins: list[str], props: Props) -> "Registry": def load(project: Project, mixins: list[str], props: Props) -> "Registry":
_logger.info(f"Loading model for project '{project.id}'")
r = Registry(project) r = Registry(project)
r._append(project) r._append(project)
@ -752,8 +754,8 @@ def view(
class GraphArgs(TargetArgs): class GraphArgs(TargetArgs):
onlyLibs: bool = cli.arg(False, "only-libs", "Show only libraries") onlyLibs: bool = cli.arg(None, "only-libs", "Show only libraries")
showDisabled: bool = cli.arg(False, "show-disabled", "Show disabled components") showDisabled: bool = cli.arg(None, "show-disabled", "Show disabled components")
scope: str = cli.arg( scope: str = cli.arg(
None, "scope", "Show only the specified component and its dependencies" None, "scope", "Show only the specified component and its dependencies"
) )

View file

@ -52,7 +52,7 @@ def loadAll():
class PluginsArgs: class PluginsArgs:
safemod: bool = cli.arg(None, "safemode", "disable plugin loading") safemod: bool = cli.arg(None, "safemode", "Disable plugin loading")
def setup(args: PluginsArgs): def setup(args: PluginsArgs):

View file

@ -1,4 +1,5 @@
import sys import sys
import logging
from typing import Optional from typing import Optional
import docker # type: ignore import docker # type: ignore
import os import os
@ -6,6 +7,7 @@ import dataclasses as dt
from . import cli, model, shell, vt100, const from . import cli, model, shell, vt100, const
_logger = logging.getLogger(__name__)
podPrefix = "CK__" podPrefix = "CK__"
projectRoot = "/project" projectRoot = "/project"
@ -111,6 +113,7 @@ def setup(args: PodSetupArgs):
""" """
if not args.pod: if not args.pod:
return return
_logger.info(f"Reincarnating into pod '{args.pod}'...")
if isinstance(args.pod, str): if isinstance(args.pod, str):
pod = args.pod.strip() pod = args.pod.strip()
pod = podPrefix + pod pod = podPrefix + pod

View file

@ -38,7 +38,12 @@ def uname() -> Uname:
distrib = {"NAME": "Unknown"} distrib = {"NAME": "Unknown"}
result = Uname( result = Uname(
un.system, distrib["NAME"], un.node, un.release, un.version, un.machine un.system,
distrib["NAME"],
un.node,
un.release,
un.version,
un.machine,
) )
match result.machine: match result.machine:
@ -49,6 +54,8 @@ def uname() -> Uname:
case _: case _:
pass pass
_logger.debug(f"uname: {result}")
return result return result
@ -128,6 +135,7 @@ def wget(url: str, path: Optional[str] = None) -> str:
) )
if os.path.exists(path): if os.path.exists(path):
_logger.debug(f"Using cached {path} for {url}")
return path return path
_logger.debug(f"Downloading {url} to {path}") _logger.debug(f"Downloading {url} to {path}")
@ -292,6 +300,8 @@ def cpTree(src: str, dst: str):
def cloneDir(url: str, path: str, dest: str) -> str: def cloneDir(url: str, path: str, dest: str) -> str:
_logger.debug(f"Cloning {url} to {dest}")
with tempfile.TemporaryDirectory() as tmp: with tempfile.TemporaryDirectory() as tmp:
mkdir(tmp) mkdir(tmp)
exec( exec(
@ -378,7 +388,6 @@ def gzip(path: str, dest: Optional[str] = None) -> str:
""" """
Compress a file or directory Compress a file or directory
""" """
if dest is None: if dest is None:
dest = path + ".gz" dest = path + ".gz"