Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add logic to load tools from json and validate #5

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
73 changes: 70 additions & 3 deletions bagel/tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@


class Tool(NamedTuple):
"""
A tool that can run against compatible benchmarks.
"""
name: str
version: str
benchmarks: Iterable[str]
Expand All @@ -12,8 +15,72 @@ def __str__(self) -> str:


def load_tool(file: IO) -> Tool:
pass
"""
Load a tool metadata object from its JSON file. Raises a ``ValueError``
if the object is malformed in any way. Use ``validate_tool`` to get
more information about an error.

TODO Adjust file paths to be relative to the metadata file location
"""
import json

def validate_tool(file: Union[IO, Dict]) -> List[str]:
pass
try:
tool_meta = json.load(file)
return Tool(**tool_meta)
except:
raise ValueError()


def validate_tool(data: Union[IO, Dict]) -> List[str]:
"""
Validate a tool metadata object in JSON format or a pre-loaded
dictionary. This includes verifying that all required fields exist and that
they are of the correct types.
"""
import json
from json.decoder import JSONDecodeError

if isinstance(data, dict):
tool_meta = data
else:
try:
tool_meta = json.load(data)
except JSONDecodeError as err:
return [f"invalid JSON object: line {err.lineno}"]

if not isinstance(tool_meta, dict):
return [f"invalid JSON object: type is {type(tool_meta)}"]

fields = [
("name", str),
("version", str),
("families", list),
("image", str),
("results", dict),
]

msgs = []

for key, dt in fields:
if key not in tool_meta:
msgs.append(f"required field not found: {key}")
continue
if not isinstance(tool_meta[key], dt):
msgs.append(f"incorrect field type ({type(tool_meta[key])}): {key}")

if msgs:
return msgs

for bmark_family in tool_meta["families"]:
if not isinstance(bmark_family, str):
msgs.append(
f"incorrect benchmark family type ({type(bmark_family)}): {bmark_family}"
)

for key, value in tool_meta["results"].items():
if not isinstance(key, str):
msgs.append(f"incorrect results key type ({type(key)}): {key}")
if not isinstance(value, str):
msgs.append(f"incorrect results value type ({type(value)}): {key}")

return msgs