Skip to content

Commit

Permalink
[tooling] Update schema generation (#280)
Browse files Browse the repository at this point in the history
* Update schema generation code

* Run schema generation
  • Loading branch information
BenjaminPelletier authored Oct 23, 2023
1 parent 6c484c3 commit efd11c1
Show file tree
Hide file tree
Showing 84 changed files with 1,997 additions and 576 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class FlightCheckTableSpecification(ImplicitDict):
table: FlightCheckTable


class FlightCheckTableResource(Resource):
class FlightCheckTableResource(Resource[FlightCheckTableSpecification]):
table: FlightCheckTable

def __init__(self, specification: FlightCheckTableSpecification):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class FeatureCheckTableSpecification(ImplicitDict):
table: FeatureCheckTable


class FeatureCheckTableResource(Resource):
class FeatureCheckTableResource(Resource[FeatureCheckTableSpecification]):
table: FeatureCheckTable

def __init__(self, specification: FeatureCheckTableSpecification):
Expand Down
93 changes: 70 additions & 23 deletions schemas/manage_type_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,24 @@
import json
import os
import sys
from typing import Optional, Set, Dict, Type
from typing import Optional, Set, Dict, Type, get_type_hints, get_args, get_origin

import implicitdict
from implicitdict import ImplicitDict
import implicitdict.jsonschema
from implicitdict.jsonschema import SchemaVars, SchemaVarsResolver
from loguru import logger

import monitoring
import monitoring.uss_qualifier.action_generators
import monitoring.uss_qualifier.resources
from monitoring.monitorlib.inspection import fullname, import_submodules
from monitoring.uss_qualifier.action_generators.action_generator import ActionGenerator
from monitoring.uss_qualifier.configurations.configuration import (
USSQualifierConfiguration,
)
from monitoring.uss_qualifier.reports.report import TestRunReport
from monitoring.uss_qualifier.resources.resource import Resource


class Action(str, enum.Enum):
Expand Down Expand Up @@ -41,34 +51,64 @@ def parse_args() -> argparse.Namespace:
return parser.parse_args()


def _find_type_schemas(
module,
def _make_type_schemas(
parent: Type[ImplicitDict],
reference_resolver: SchemaVarsResolver,
repo: Optional[Dict[str, dict]] = None,
repo: Dict[str, dict],
already_checked: Optional[Set[str]] = None,
) -> Dict[str, dict]:
) -> None:
implicitdict.jsonschema.make_json_schema(parent, reference_resolver, repo)
if already_checked is None:
already_checked = set()
already_checked.add(module.__name__)
already_checked.add(fullname(parent))

# TODO: Expose get_fields formally in implicitdict
all_fields, _ = implicitdict._get_fields(parent)
hints = get_type_hints(parent)
for field in all_fields:
if field not in hints:
continue
field_type = hints[field]

pending_types = [field_type]
while pending_types:
pending_type = pending_types.pop(0)
generic_type = get_origin(pending_type)
if generic_type:
pending_types.extend(get_args(pending_type))
else:
if (
issubclass(pending_type, ImplicitDict)
and fullname(pending_type) not in already_checked
):
_make_type_schemas(
pending_type, reference_resolver, repo, already_checked
)


if repo is None:
repo = {}
def _find_specifications(
module,
repo: Dict[str, Type[ImplicitDict]],
already_checked: Optional[Set[str]] = None,
) -> None:
if already_checked is None:
already_checked = set()
already_checked.add(module.__name__)

for name, member in inspect.getmembers(module):
if (
inspect.ismodule(member)
and member.__name__ not in already_checked
and member.__name__.startswith("monitoring")
):
_find_type_schemas(member, reference_resolver, repo, already_checked)
elif (
inspect.isclass(member)
and issubclass(member, ImplicitDict)
and member != ImplicitDict
):
implicitdict.jsonschema.make_json_schema(member, reference_resolver, repo)

return repo
_find_specifications(member, repo, already_checked)
elif inspect.isclass(member):
if issubclass(member, Resource) and member != Resource:
spec_type = get_args(member.__orig_bases__[0])[0]
repo[fullname(spec_type)] = spec_type
elif issubclass(member, ActionGenerator) and member != ActionGenerator:
spec_type = get_args(member.__orig_bases__[0])[0]
repo[fullname(spec_type)] = spec_type


def main() -> int:
Expand Down Expand Up @@ -114,12 +154,19 @@ def path_to(t_dest: Type, t_src: Type) -> str:
description=f"{full_name(schema_type)}, as defined in {path_of_py_file(schema_type)}",
)

from monitoring.uss_qualifier.reports.report import TestRunReport
from monitoring.uss_qualifier.configurations.configuration import (
USSQualifierConfiguration,
)

schemas = _find_type_schemas(monitoring, schema_vars_resolver)
schemas = {}
_make_type_schemas(TestRunReport, schema_vars_resolver, schemas)
_make_type_schemas(USSQualifierConfiguration, schema_vars_resolver, schemas)

repo = {}
import_submodules(monitoring.uss_qualifier.resources)
_find_specifications(monitoring.uss_qualifier.resources, repo)
import_submodules(monitoring.uss_qualifier.action_generators)
_find_specifications(monitoring.uss_qualifier.action_generators, repo)
for spec_type in repo.values():
implicitdict.jsonschema.make_json_schema(
spec_type, schema_vars_resolver, schemas
)

repo_root = os.path.abspath(
os.path.join(os.path.dirname(monitoring.__file__), "..")
Expand Down
38 changes: 19 additions & 19 deletions schemas/monitoring/monitorlib/fetch/RequestDescription.json
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
{
"$id": "https://github.com/interuss/monitoring/blob/main/schemas/monitoring/monitorlib/fetch/RequestDescription.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"description": "monitoring.monitorlib.fetch.RequestDescription, as defined in monitoring/monitorlib/fetch/__init__.py",
"properties": {
"$ref": {
"type": "string",
"description": "Path to content that replaces the $ref"
"description": "Path to content that replaces the $ref",
"type": "string"
},
"initiated_at": {
"body": {
"type": [
"string",
"null"
],
"format": "date-time"
]
},
"received_at": {
"headers": {
"type": [
"string",
"object",
"null"
],
"format": "date-time"
]
},
"headers": {
"initiated_at": {
"format": "date-time",
"type": [
"object",
"string",
"null"
]
},
Expand All @@ -35,20 +35,20 @@
"method": {
"type": "string"
},
"url": {
"type": "string"
},
"body": {
"received_at": {
"format": "date-time",
"type": [
"string",
"null"
]
},
"url": {
"type": "string"
}
},
"$id": "https://github.com/interuss/monitoring/blob/main/schemas/monitoring/monitorlib/fetch/RequestDescription.json",
"description": "monitoring.monitorlib.fetch.RequestDescription, as defined in monitoring/monitorlib/fetch/__init__.py",
"required": [
"method",
"url"
]
],
"type": "object"
}
34 changes: 17 additions & 17 deletions schemas/monitoring/monitorlib/fetch/ResponseDescription.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
{
"$id": "https://github.com/interuss/monitoring/blob/main/schemas/monitoring/monitorlib/fetch/ResponseDescription.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"description": "monitoring.monitorlib.fetch.ResponseDescription, as defined in monitoring/monitorlib/fetch/__init__.py",
"properties": {
"$ref": {
"type": "string",
"description": "Path to content that replaces the $ref"
"description": "Path to content that replaces the $ref",
"type": "string"
},
"body": {
"type": [
"string",
"null"
]
},
"code": {
"type": [
"integer",
"null"
]
},
"elapsed_s": {
"type": "number"
},
"failure": {
"type": [
"string",
Expand All @@ -30,24 +40,14 @@
"null"
]
},
"elapsed_s": {
"type": "number"
},
"body": {
"type": [
"string",
"null"
]
},
"reported": {
"type": "string",
"format": "date-time"
"format": "date-time",
"type": "string"
}
},
"$id": "https://github.com/interuss/monitoring/blob/main/schemas/monitoring/monitorlib/fetch/ResponseDescription.json",
"description": "monitoring.monitorlib.fetch.ResponseDescription, as defined in monitoring/monitorlib/fetch/__init__.py",
"required": [
"elapsed_s",
"reported"
]
],
"type": "object"
}
34 changes: 0 additions & 34 deletions schemas/monitoring/monitorlib/geo/LatLngBoundingBox.json

This file was deleted.

52 changes: 0 additions & 52 deletions schemas/monitoring/monitorlib/geo/Volume3D.json

This file was deleted.

Loading

0 comments on commit efd11c1

Please sign in to comment.