Skip to content

Commit

Permalink
feat: generate empty metadata files
Browse files Browse the repository at this point in the history
Fixes #14
  • Loading branch information
alvarolopez committed Aug 22, 2024
1 parent 5e37644 commit f56c519
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 1 deletion.
25 changes: 24 additions & 1 deletion src/ai4_metadata/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import typer

import ai4_metadata
from ai4_metadata import generate
from ai4_metadata import exceptions
from ai4_metadata import migrate
from ai4_metadata import utils
Expand Down Expand Up @@ -110,10 +111,32 @@ def _generate(
ai4_metadata.MetadataVersions,
typer.Option(help="AI4 application metadata version."),
] = ai4_metadata.get_latest_version().value,
sample_values: Annotated[
bool, typer.Option("--sample-values", help="Generate sample values.")
] = False,
required: Annotated[
bool, typer.Option("--required-only", help="Include only required fields.")
] = False,
output: Annotated[
Optional[pathlib.Path],
typer.Option("--output", "-o", help="Output file for generated metadata."),
] = None,
):
"""Generate an AI4 metadata schema."""
schema = ai4_metadata.get_schema(metadata_version)
utils.format_rich_ok(f"Loaded schema for version {metadata_version.value} from '{schema}'")

try:
generated_json = generate.generate(schema, sample_values, required)
except exceptions.InvalidSchemaError as e:
utils.format_rich_error(e)
raise typer.Exit(1)

utils.dump_json(generated_json, output)

if output:
utils.format_rich_ok(
f"Sample file stored in '{output}' for version {metadata_version.value}"
)


def version_callback(value: bool):
Expand Down
10 changes: 10 additions & 0 deletions src/ai4_metadata/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ class InvalidYAMLError(InvalidFileError):
message = "Error loading YAML file '{f}': {e}"


class InvalidSchemaError(BaseExceptionError):
"""Exception raised when a schema is invalid."""

message = "Schema file '{schema_file}' is invalid: {error}"

def __init__(self, schema_file: typing.Union[str, pathlib.Path], error: str):
"""Initialize the exception."""
super().__init__(self.message.format(schema_file=schema_file, error=error))


class SchemaValidationError(BaseExceptionError):
"""Exception raised when a schema is invalid."""

Expand Down
61 changes: 61 additions & 0 deletions src/ai4_metadata/generate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""Generate an AI4 metadata follwowing schema with empty of with samples."""

import collections
import json
import pathlib
import typing

from ai4_metadata import exceptions


def generate(
schema: typing.Union[pathlib.Path, str],
sample_values: bool = False,
required_only: bool = False,
) -> collections.OrderedDict:
"""Generate an AI4 metadata schema empty of with samples."""
schema_json = json.load(open(schema, "r"))

properties = schema_json.get("properties")
required = schema_json.get("required", [])

if required_only:
properties = {k: v for k, v in properties.items() if k in required}

if not properties:
raise exceptions.InvalidSchemaError(
schema, "No definitions found in the schema."
)

generated_json: collections.OrderedDict[str, typing.Any] = collections.OrderedDict()

# NOTE(aloga): this works for the current schema, but we need to handle this
# recursively in order to make it work for nested objects
for key, value in properties.items():
# If type is object, we need to go deeper
if value.get("type") == "object":
required_sub = value.get("required", [])
if required_only:
value["properties"] = {
k: v
for k, v in value.get("properties").items()
if k in required_sub
}
generated_json[key] = collections.OrderedDict()
for sub_key, sub_value in value.get("properties").items():
if sample_values:
generated_json[key][sub_key] = sub_value.get("example", "")
else:
generated_json[key][sub_key] = ""
elif value.get("type") == "array":
if sample_values:
generated_json[key] = value.get("example", [])
else:
generated_json[key] = []
else:
if sample_values:
generated_json[key] = value.get("example", "")
else:
generated_json[key] = ""

return generated_json

0 comments on commit f56c519

Please sign in to comment.