cutekit/osdk/model.py

273 lines
7.7 KiB
Python
Raw Normal View History

import os
from enum import Enum
from typing import Any
2023-02-06 10:14:32 +00:00
from osdk.jexpr import Json
from osdk.logger import Logger
logger = Logger("model")
Props = dict[str, Any]
class Type(Enum):
2023-02-07 11:40:00 +00:00
UNKNOWN = "unknown"
PROJECT = "project"
TARGET = "target"
LIB = "lib"
EXE = "exe"
class Manifest:
2023-02-07 11:40:00 +00:00
id: str = ""
type: Type = Type.UNKNOWN
path: str = ""
2023-03-25 14:26:34 +00:00
def __init__(self, json: Json = None, path: str = "", strict: bool = True, **kwargs: Any):
2023-02-07 11:40:00 +00:00
if json is not None:
if not "id" in json:
raise ValueError("Missing id")
2023-02-07 11:40:00 +00:00
self.id = json["id"]
2023-02-07 11:40:00 +00:00
if not "type" in json and strict:
raise ValueError("Missing type")
2023-02-07 11:40:00 +00:00
self.type = Type(json["type"])
2023-02-07 11:40:00 +00:00
self.path = path
elif strict:
raise ValueError("Missing json")
for key in kwargs:
setattr(self, key, kwargs[key])
2023-04-20 06:18:37 +00:00
def toJson(self) -> Json:
return {
"id": self.id,
"type": self.type.value,
"path": self.path
}
def __str__(self):
return f"Manifest(id={self.id}, type={self.type}, path={self.path})"
def __repr__(self):
return f"Manifest({id})"
def dirname(self) -> str:
return os.path.dirname(self.path)
class Extern:
git: str = ""
tag: str = ""
2023-03-25 14:26:34 +00:00
def __init__(self, json: Json = None, strict: bool = True, **kwargs: Any):
if json is not None:
if not "git" in json and strict:
raise ValueError("Missing git")
self.git = json["git"]
if not "tag" in json and strict:
raise ValueError("Missing tag")
self.tag = json["tag"]
elif strict:
raise ValueError("Missing json")
for key in kwargs:
setattr(self, key, kwargs[key])
2023-04-20 06:18:37 +00:00
def toJson(self) -> Json:
return {
"git": self.git,
"tag": self.tag
}
def __str__(self):
return f"Extern(git={self.git}, tag={self.tag})"
def __repr__(self):
return f"Extern({self.git})"
class ProjectManifest(Manifest):
description: str = ""
extern: dict[str, Extern] = {}
2023-03-25 14:26:34 +00:00
def __init__(self, json: Json = None, path: str = "", strict: bool = True, **kwargs: Any):
if json is not None:
if not "description" in json and strict:
raise ValueError("Missing description")
self.description = json["description"]
self.extern = {k: Extern(v)
for k, v in json.get("extern", {}).items()}
elif strict:
raise ValueError("Missing json")
super().__init__(json, path, strict, **kwargs)
2023-04-20 06:18:37 +00:00
def toJson(self) -> Json:
return {
**super().toJson(),
"description": self.description,
"extern": {k: v.toJson() for k, v in self.extern.items()}
}
def __str__(self):
return f"ProjectManifest(id={self.id}, type={self.type}, path={self.path}, description={self.description}, extern={self.extern})"
def __repr__(self):
return f"ProjectManifest({self.id})"
class Tool:
2023-02-07 11:40:00 +00:00
cmd: str = ""
args: list[str] = []
files: list[str] = []
2023-03-25 14:26:34 +00:00
def __init__(self, json: Json = None, strict: bool = True, **kwargs: Any):
2023-02-07 11:40:00 +00:00
if json is not None:
if not "cmd" in json and strict:
raise ValueError("Missing cmd")
self.cmd = json.get("cmd", self.cmd)
if not "args" in json and strict:
raise ValueError("Missing args")
2023-02-07 11:40:00 +00:00
self.args = json.get("args", [])
2023-02-07 11:40:00 +00:00
self.files = json.get("files", [])
elif strict:
raise ValueError("Missing json")
for key in kwargs:
setattr(self, key, kwargs[key])
2023-04-20 06:18:37 +00:00
def toJson(self) -> Json:
return {
"cmd": self.cmd,
"args": self.args,
"files": self.files
}
def __str__(self):
2023-02-07 11:40:00 +00:00
return f"Tool(cmd={self.cmd}, args={self.args}, files={self.files})"
def __repr__(self):
return f"Tool({self.cmd})"
2023-02-07 15:27:04 +00:00
Tools = dict[str, Tool]
class TargetManifest(Manifest):
props: Props
2023-02-07 15:27:04 +00:00
tools: Tools
routing: dict[str, str]
2023-03-25 14:26:34 +00:00
def __init__(self, json: Json = None, path: str = "", strict: bool = True, **kwargs: Any):
2023-02-07 11:40:00 +00:00
if json is not None:
if not "props" in json and strict:
raise ValueError("Missing props")
2023-02-07 11:40:00 +00:00
self.props = json["props"]
2023-02-07 11:40:00 +00:00
if not "tools" in json and strict:
raise ValueError("Missing tools")
2023-02-07 11:40:00 +00:00
self.tools = {k: Tool(v) for k, v in json["tools"].items()}
2023-02-07 11:40:00 +00:00
self.routing = json.get("routing", {})
2023-02-07 11:40:00 +00:00
super().__init__(json, path, strict, **kwargs)
2023-04-20 06:18:37 +00:00
def toJson(self) -> Json:
return {
**super().toJson(),
"props": self.props,
"tools": {k: v.toJson() for k, v in self.tools.items()},
"routing": self.routing
}
def __repr__(self):
return f"TargetManifest({self.id})"
def route(self, componentSpec: str):
return self.routing[componentSpec] if componentSpec in self.routing else componentSpec
2023-02-06 10:14:32 +00:00
def cdefs(self) -> list[str]:
defines: list[str] = []
for key in self.props:
macroname = key.lower().replace("-", "_")
prop = self.props[key]
macrovalue = str(prop).lower().replace(" ", "_").replace("-", "_")
if isinstance(prop, bool):
if prop:
defines += [f"-D__osdk_{macroname}__"]
else:
defines += [f"-D__osdk_{macroname}_{macrovalue}__"]
return defines
class ComponentManifest(Manifest):
2023-02-07 11:40:00 +00:00
decription: str = "(No description)"
props: Props = {}
2023-02-07 15:27:04 +00:00
tools: Tools = {}
2023-02-07 11:40:00 +00:00
enableIf: dict[str, list[Any]] = {}
requires: list[str] = []
provides: list[str] = []
2023-02-20 21:28:45 +00:00
subdirs: list[str] = []
2023-02-07 11:40:00 +00:00
2023-03-25 14:26:34 +00:00
def __init__(self, json: Json = None, path: str = "", strict: bool = True, **kwargs: Any):
2023-02-07 11:40:00 +00:00
if json is not None:
self.decription = json.get("description", self.decription)
self.props = json.get("props", self.props)
self.tools = {k: Tool(v, strict=False)
for k, v in json.get("tools", {}).items()}
self.enableIf = json.get("enableIf", self.enableIf)
self.requires = json.get("requires", self.requires)
self.provides = json.get("provides", self.provides)
2023-02-20 21:28:45 +00:00
self.subdirs = list(map(lambda x: os.path.join(os.path.dirname(
path), x), json.get("subdirs", [""])))
2023-02-07 11:40:00 +00:00
super().__init__(json, path, strict, **kwargs)
2023-04-20 06:18:37 +00:00
def toJson(self) -> Json:
return {
**super().toJson(),
"description": self.decription,
"props": self.props,
"tools": {k: v.toJson() for k, v in self.tools.items()},
"enableIf": self.enableIf,
"requires": self.requires,
"provides": self.provides,
"subdirs": self.subdirs
}
def __repr__(self):
return f"ComponentManifest({self.id})"
def isEnabled(self, target: TargetManifest) -> tuple[bool, str]:
for k, v in self.enableIf.items():
2023-01-31 20:09:28 +00:00
if not k in target.props:
logger.log(
f"Component {self.id} disabled by missing {k} in target")
return False, f"Missing props '{k}' in target"
2023-01-31 20:09:28 +00:00
if not target.props[k] in v:
vStrs = [f"'{str(x)}'" for x in v]
2023-01-31 20:09:28 +00:00
logger.log(
f"Component {self.id} disabled by {k}={target.props[k]} not in {v}")
return False, f"Props missmatch for '{k}': Got '{target.props[k]}' but expected {', '.join(vStrs)}"
2023-01-31 20:09:28 +00:00
return True, ""