chore: improve type hinting
This commit is contained in:
parent
1fac2fbbfb
commit
eabbcfe7c6
|
@ -1,4 +1,7 @@
|
||||||
Value = str | bool | int
|
from typing import Optional, Union
|
||||||
|
|
||||||
|
|
||||||
|
Value = Union[str, bool, int]
|
||||||
|
|
||||||
|
|
||||||
class Args:
|
class Args:
|
||||||
|
@ -24,14 +27,14 @@ class Args:
|
||||||
return result
|
return result
|
||||||
return default
|
return default
|
||||||
|
|
||||||
def tryConsumeOpt(self, key: str) -> Value | None:
|
def tryConsumeOpt(self, key: str) -> Optional[Value]:
|
||||||
if key in self.opts:
|
if key in self.opts:
|
||||||
result = self.opts[key]
|
result = self.opts[key]
|
||||||
del self.opts[key]
|
del self.opts[key]
|
||||||
return result
|
return result
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def consumeArg(self) -> str | None:
|
def consumeArg(self) -> Optional[str]:
|
||||||
if len(self.args) == 0:
|
if len(self.args) == 0:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,11 @@ import tempfile
|
||||||
import requests
|
import requests
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from typing import Callable, cast
|
from typing import Callable, cast, Optional, NoReturn
|
||||||
|
|
||||||
from cutekit import context, shell, const, vt100, builder, graph, project
|
from cutekit import context, shell, const, vt100, builder, graph, project
|
||||||
from cutekit.args import Args
|
from cutekit.args import Args
|
||||||
|
from cutekit.jexpr import Json
|
||||||
from cutekit.model import Extern
|
from cutekit.model import Extern
|
||||||
from cutekit.context import contextFor
|
from cutekit.context import contextFor
|
||||||
|
|
||||||
|
@ -17,13 +18,13 @@ logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Cmd:
|
class Cmd:
|
||||||
shortName: str | None
|
shortName: Optional[str]
|
||||||
longName: str
|
longName: str
|
||||||
helpText: str
|
helpText: str
|
||||||
callback: Callable[[Args], None]
|
callback: Callable[[Args], NoReturn]
|
||||||
isPlugin: bool = False
|
isPlugin: bool = False
|
||||||
|
|
||||||
def __init__(self, shortName: str | None, longName: str, helpText: str, callback: Callable[[Args], None]):
|
def __init__(self, shortName: Optional[str], longName: str, helpText: str, callback: Callable[[Args], NoReturn]):
|
||||||
self.shortName = shortName
|
self.shortName = shortName
|
||||||
self.longName = longName
|
self.longName = longName
|
||||||
self.helpText = helpText
|
self.helpText = helpText
|
||||||
|
@ -197,7 +198,7 @@ def graphCmd(args: Args):
|
||||||
targetSpec = cast(str, args.consumeOpt(
|
targetSpec = cast(str, args.consumeOpt(
|
||||||
"target", "host-" + shell.uname().machine))
|
"target", "host-" + shell.uname().machine))
|
||||||
|
|
||||||
scope: str | None = cast(str | None, args.tryConsumeOpt("scope"))
|
scope: Optional[str] = cast(Optional[str], args.tryConsumeOpt("scope"))
|
||||||
onlyLibs: bool = args.consumeOpt("only-libs", False) == True
|
onlyLibs: bool = args.consumeOpt("only-libs", False) == True
|
||||||
showDisabled: bool = args.consumeOpt("show-disabled", False) == True
|
showDisabled: bool = args.consumeOpt("show-disabled", False) == True
|
||||||
|
|
||||||
|
@ -221,7 +222,7 @@ def grabExtern(extern: dict[str, Extern]):
|
||||||
print(f"Installing {extSpec}-{ext.tag} from {ext.git}...")
|
print(f"Installing {extSpec}-{ext.tag} from {ext.git}...")
|
||||||
shell.popen("git", "clone", "--depth", "1", "--branch",
|
shell.popen("git", "clone", "--depth", "1", "--branch",
|
||||||
ext.tag, ext.git, extPath)
|
ext.tag, ext.git, extPath)
|
||||||
|
|
||||||
if os.path.exists(os.path.join(extPath, "project.json")):
|
if os.path.exists(os.path.join(extPath, "project.json")):
|
||||||
grabExtern(context.loadProject(extPath).extern)
|
grabExtern(context.loadProject(extPath).extern)
|
||||||
|
|
||||||
|
@ -259,9 +260,10 @@ def initCmd(args: Args):
|
||||||
print('\n'.join(
|
print('\n'.join(
|
||||||
f"* {entry['id']} - {entry['description']}" for entry in registry))
|
f"* {entry['id']} - {entry['description']}" for entry in registry))
|
||||||
else:
|
else:
|
||||||
if not any(filter(lambda t: t['id'] == template, registry)):
|
template_match: Callable[[Json], str] = lambda t: t['id'] == template
|
||||||
|
if not any(filter(template_match, registry)):
|
||||||
raise RuntimeError(f"Unknown template {template}")
|
raise RuntimeError(f"Unknown template {template}")
|
||||||
|
|
||||||
with tempfile.TemporaryDirectory() as tmp:
|
with tempfile.TemporaryDirectory() as tmp:
|
||||||
shell.exec(*["git", "clone", "-n", "--depth=1",
|
shell.exec(*["git", "clone", "-n", "--depth=1",
|
||||||
"--filter=tree:0", f"https://github.com/{repo}", tmp, "-q"])
|
"--filter=tree:0", f"https://github.com/{repo}", tmp, "-q"])
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from typing import cast, Protocol, Iterable
|
from typing import cast, Optional, Protocol, Iterable
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import os
|
import os
|
||||||
|
@ -95,7 +95,7 @@ class Context(IContext):
|
||||||
self.instances = instances
|
self.instances = instances
|
||||||
self.tools = tools
|
self.tools = tools
|
||||||
|
|
||||||
def componentByName(self, name: str) -> ComponentInstance | None:
|
def componentByName(self, name: str) -> Optional[ComponentInstance]:
|
||||||
result = list(filter(lambda x: x.manifest.id == name, self.instances))
|
result = list(filter(lambda x: x.manifest.id == name, self.instances))
|
||||||
if len(result) == 0:
|
if len(result) == 0:
|
||||||
return None
|
return None
|
||||||
|
@ -120,10 +120,11 @@ def loadAllTargets() -> list[TargetManifest]:
|
||||||
projectRoot = project.root()
|
projectRoot = project.root()
|
||||||
if projectRoot is None:
|
if projectRoot is None:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
pj = loadProject(projectRoot)
|
pj = loadProject(projectRoot)
|
||||||
paths = list(
|
paths = list(
|
||||||
map(lambda e: os.path.join(const.EXTERN_DIR, e, const.TARGETS_DIR), pj.extern.keys())
|
map(lambda e: os.path.join(const.EXTERN_DIR,
|
||||||
|
e, const.TARGETS_DIR), pj.extern.keys())
|
||||||
) + [const.TARGETS_DIR]
|
) + [const.TARGETS_DIR]
|
||||||
|
|
||||||
ret = []
|
ret = []
|
||||||
|
@ -161,7 +162,7 @@ def filterDisabled(components: list[ComponentManifest], target: TargetManifest)
|
||||||
list(filter(lambda c: not c.isEnabled(target)[0], components))
|
list(filter(lambda c: not c.isEnabled(target)[0], components))
|
||||||
|
|
||||||
|
|
||||||
def providerFor(what: str, components: list[ComponentManifest]) -> tuple[str | None, str]:
|
def providerFor(what: str, components: list[ComponentManifest]) -> tuple[Optional[str], str]:
|
||||||
result: list[ComponentManifest] = list(
|
result: list[ComponentManifest] = list(
|
||||||
filter(lambda c: c.id == what, components))
|
filter(lambda c: c.id == what, components))
|
||||||
|
|
||||||
|
@ -217,7 +218,7 @@ def resolveDeps(componentSpec: str, components: list[ComponentManifest], target:
|
||||||
return enabled, unresolvedReason, resolved
|
return enabled, unresolvedReason, resolved
|
||||||
|
|
||||||
|
|
||||||
def instanciate(componentSpec: str, components: list[ComponentManifest], target: TargetManifest) -> ComponentInstance | None:
|
def instanciate(componentSpec: str, components: list[ComponentManifest], target: TargetManifest) -> Optional[ComponentInstance]:
|
||||||
manifest = next(filter(lambda c: c.id == componentSpec, components))
|
manifest = next(filter(lambda c: c.id == componentSpec, components))
|
||||||
wildcards = set(
|
wildcards = set(
|
||||||
chain(*map(lambda rule: rule.fileIn, rules.rules.values())))
|
chain(*map(lambda rule: rule.fileIn, rules.rules.values())))
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from typing import Optional
|
||||||
from cutekit.context import Context
|
from cutekit.context import Context
|
||||||
from cutekit import vt100
|
from cutekit import vt100
|
||||||
|
|
||||||
|
|
||||||
def view(context: Context, scope: str | None = None, showExe: bool = True, showDisabled: bool = False):
|
def view(context: Context, scope: Optional[str] = None, showExe: bool = True, showDisabled: bool = False):
|
||||||
from graphviz import Digraph
|
from graphviz import Digraph
|
||||||
|
|
||||||
g = Digraph(context.target.id, filename='graph.gv')
|
g = Digraph(context.target.id, filename='graph.gv')
|
||||||
|
|
|
@ -14,11 +14,11 @@ BUILTINS: Final[dict[str, Builtin]] = {
|
||||||
"evalRead": lambda arg, ctx: evalRead(arg),
|
"evalRead": lambda arg, ctx: evalRead(arg),
|
||||||
"join": lambda lhs, rhs, ctx: cast(Json, {**lhs, **rhs} if isinstance(lhs, dict) else lhs + rhs),
|
"join": lambda lhs, rhs, ctx: cast(Json, {**lhs, **rhs} if isinstance(lhs, dict) else lhs + rhs),
|
||||||
"concat": lambda *args, ctx: "".join(args),
|
"concat": lambda *args, ctx: "".join(args),
|
||||||
"eval": lambda arg, ctx: eval(arg),
|
"eval": lambda arg, ctx: eval(arg, ctx["filepath"]),
|
||||||
"read": lambda arg, ctx: read(arg),
|
"read": lambda arg, ctx: read(arg),
|
||||||
"exec": lambda *args, ctx: shell.popen(*args).splitlines(),
|
"exec": lambda *args, ctx: shell.popen(*args).splitlines(),
|
||||||
"latest": lambda arg, ctx: shell.latest(arg),
|
"latest": lambda arg, ctx: shell.latest(arg),
|
||||||
"abspath": lambda *args, ctx: os.path.normpath(os.path.join(os.path.dirname(ctx["filepath"]), *args))
|
"abspath": lambda *args, ctx: os.path.normpath(os.path.join(os.path.dirname(ctx["filepath"]), *args))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import os
|
import os
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
def root() -> str | None:
|
|
||||||
|
def root() -> Optional[str]:
|
||||||
cwd = os.getcwd()
|
cwd = os.getcwd()
|
||||||
while cwd != "/":
|
while cwd != "/":
|
||||||
if os.path.isfile(os.path.join(cwd, "project.json")):
|
if os.path.isfile(os.path.join(cwd, "project.json")):
|
||||||
|
@ -12,6 +14,7 @@ def root() -> str | None:
|
||||||
def chdir() -> None:
|
def chdir() -> None:
|
||||||
projectRoot = root()
|
projectRoot = root()
|
||||||
if projectRoot is None:
|
if projectRoot is None:
|
||||||
raise RuntimeError("No project.json found in this directory or any parent directory")
|
raise RuntimeError(
|
||||||
|
"No project.json found in this directory or any parent directory")
|
||||||
os.chdir(projectRoot)
|
|
||||||
|
os.chdir(projectRoot)
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
class Rule:
|
class Rule:
|
||||||
id: str
|
id: str
|
||||||
fileIn: list[str]
|
fileIn: list[str]
|
||||||
fileOut: list[str]
|
fileOut: list[str]
|
||||||
rule: str
|
rule: str
|
||||||
args: list[str]
|
args: list[str]
|
||||||
deps: str | None = None
|
deps: Optional[str] = None
|
||||||
|
|
||||||
def __init__(self, id: str, fileIn: list[str], fileOut: list[str], rule: str, args: list[str] = [], deps: str | None = None):
|
def __init__(self, id: str, fileIn: list[str], fileOut: list[str], rule: str, args: list[str] = [], deps: Optional[str] = None):
|
||||||
self.id = id
|
self.id = id
|
||||||
self.fileIn = fileIn
|
self.fileIn = fileIn
|
||||||
self.fileOut = fileOut
|
self.fileOut = fileOut
|
||||||
|
@ -14,17 +17,18 @@ class Rule:
|
||||||
self.args = args
|
self.args = args
|
||||||
self.deps = deps
|
self.deps = deps
|
||||||
|
|
||||||
|
|
||||||
rules: dict[str, Rule] = {
|
rules: dict[str, Rule] = {
|
||||||
"cc": Rule("cc", ["*.c"], ["*.o"], "-c -o $out $in -MD -MF $out.d $flags $cincs $cdefs", ["-std=gnu2x",
|
"cc": Rule("cc", ["*.c"], ["*.o"], "-c -o $out $in -MD -MF $out.d $flags $cincs $cdefs", ["-std=gnu2x",
|
||||||
"-Wall",
|
"-Wall",
|
||||||
"-Wextra",
|
"-Wextra",
|
||||||
"-Werror"], "$out.d"),
|
"-Werror"], "$out.d"),
|
||||||
"cxx": Rule("cxx", ["*.cpp", "*.cc", "*.cxx"], ["*.o"], "-c -o $out $in -MD -MF $out.d $flags $cincs $cdefs", ["-std=gnu++2b",
|
"cxx": Rule("cxx", ["*.cpp", "*.cc", "*.cxx"], ["*.o"], "-c -o $out $in -MD -MF $out.d $flags $cincs $cdefs", ["-std=gnu++2b",
|
||||||
"-Wall",
|
"-Wall",
|
||||||
"-Wextra",
|
"-Wextra",
|
||||||
"-Werror",
|
"-Werror",
|
||||||
"-fno-exceptions",
|
"-fno-exceptions",
|
||||||
"-fno-rtti"], "$out.d"),
|
"-fno-rtti"], "$out.d"),
|
||||||
"as": Rule("as", ["*.s", "*.asm", "*.S"], ["*.o"], "-o $out $in $flags"),
|
"as": Rule("as", ["*.s", "*.asm", "*.S"], ["*.o"], "-o $out $in $flags"),
|
||||||
"ar": Rule("ar", ["*.o"], ["*.a"], "$flags $out $in"),
|
"ar": Rule("ar", ["*.o"], ["*.a"], "$flags $out $in"),
|
||||||
"ld": Rule("ld", ["*.o", "*.a"], ["*.out"], "-o $out $in $flags"),
|
"ld": Rule("ld", ["*.o", "*.a"], ["*.out"], "-o $out $in $flags"),
|
||||||
|
@ -35,7 +39,7 @@ def append(rule: Rule):
|
||||||
rules[rule.id] = rule
|
rules[rule.id] = rule
|
||||||
|
|
||||||
|
|
||||||
def byFileIn(fileIn: str) -> Rule | None:
|
def byFileIn(fileIn: str) -> Optional[Rule]:
|
||||||
for key in rules:
|
for key in rules:
|
||||||
rule = rules[key]
|
rule = rules[key]
|
||||||
for ext in rule.fileIn:
|
for ext in rule.fileIn:
|
||||||
|
@ -44,5 +48,5 @@ def byFileIn(fileIn: str) -> Rule | None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def byId(id: str) -> Rule | None:
|
def byId(id: str) -> Optional[Rule]:
|
||||||
return rules.get(id, None)
|
return rules.get(id, None)
|
||||||
|
|
|
@ -10,6 +10,7 @@ import fnmatch
|
||||||
import platform
|
import platform
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from typing import Optional
|
||||||
from cutekit import const
|
from cutekit import const
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -100,7 +101,7 @@ def rmrf(path: str) -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def wget(url: str, path: str | None = None) -> str:
|
def wget(url: str, path: Optional[str] = None) -> str:
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
if path is None:
|
if path is None:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from typing import Any, TypeVar, cast
|
from typing import Any, TypeVar, cast, Optional, Union
|
||||||
import json
|
import json
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ def uniq(l: list[str]) -> list[str]:
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def hash(obj: Any, keys: list[str] = [], cls: type[json.JSONEncoder] | None = None) -> str:
|
def hash(obj: Any, keys: list[str] = [], cls: Optional[type[json.JSONEncoder]] = None) -> str:
|
||||||
toHash = {}
|
toHash = {}
|
||||||
if len(keys) == 0:
|
if len(keys) == 0:
|
||||||
toHash = obj
|
toHash = obj
|
||||||
|
@ -50,7 +50,7 @@ def key(obj: Any, keys: list[str] = []) -> str:
|
||||||
return "-".join(k)
|
return "-".join(k)
|
||||||
|
|
||||||
|
|
||||||
def asList(i: T | list[T] | None) -> list[T]:
|
def asList(i: Optional[Union[T, list[T]]]) -> list[T]:
|
||||||
if i is None:
|
if i is None:
|
||||||
return []
|
return []
|
||||||
if isinstance(i, list):
|
if isinstance(i, list):
|
||||||
|
|
Loading…
Reference in a new issue