Skip to content

Commit

Permalink
refactor: generate asset/ecalc model schema (#157)
Browse files Browse the repository at this point in the history
  • Loading branch information
jsolaas authored Sep 11, 2023
1 parent 7a99b5b commit 6818848
Show file tree
Hide file tree
Showing 8 changed files with 173 additions and 193 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@

from libecalc.dto.ecalc_model import SchemaSettings
from libecalc.input.validation import json_schemas
from libecalc.input.yaml_types.components.asset import YamlAsset

# This just needs to be a unique ID, it is required, but we do not need to have anything at that URI
# since we are embedding everything within one file
# Do not change this URI, since it has already been used in all json schemas
from libecalc.input.yaml_types.models.turbine import Turbine
from libecalc.input.yaml_types.variable import Variables
from pydantic import schema_of

BASE_URI = "$SERVER_NAME/api/v1/schema-validation"
Expand All @@ -33,18 +33,58 @@ def get_template(schema: str, schema_name: str, is_root: bool = False) -> str:
return template


def replace_property_with_legacy_json_schema(schema: dict, property_key: str, property_ref: str) -> dict:
del schema["schema"]["properties"][property_key]["type"]
schema["schema"]["properties"][property_key]["$ref"] = property_ref
return schema


def generate_json_schemas(server_url: str, docs_keywords_url: str) -> List[SchemaSettings]:
schemas = []

# First we get the root schema
with open(JSON_SCHEMA_PATH / ROOT_JSON_SCHEMA_FILE_NAME) as root_model_file:
root_model_schema = root_model_file.read()
schema = get_template(
schema=root_model_schema,
schema_name="ecalc-model.json",
is_root=True,
schema = json.loads(
get_template(
schema=json.dumps(YamlAsset.schema(by_alias=True)), schema_name=ROOT_JSON_SCHEMA_FILE_NAME, is_root=True
)
schemas.append(schema)
)

schema = replace_property_with_legacy_json_schema(
schema=schema,
property_key="TIME_SERIES",
property_ref="$SERVER_NAME/api/v1/schema-validation/time-series.json#properties/TIME_SERIES",
)
schema = replace_property_with_legacy_json_schema(
schema=schema,
property_key="FACILITY_INPUTS",
property_ref="$SERVER_NAME/api/v1/schema-validation/facility-files.json#properties/FACILITY_INPUTS",
)
schema = replace_property_with_legacy_json_schema(
schema=schema,
property_key="MODELS",
property_ref="$SERVER_NAME/api/v1/schema-validation/models.json#properties/MODELS",
)
schema = replace_property_with_legacy_json_schema(
schema=schema,
property_key="FUEL_TYPES",
property_ref="$SERVER_NAME/api/v1/schema-validation/fuel-types.json#properties/FUEL_TYPES",
)
schema = replace_property_with_legacy_json_schema(
schema=schema,
property_key="INSTALLATIONS",
property_ref="$SERVER_NAME/api/v1/schema-validation/installations.json#properties/INSTALLATIONS",
)

variables_schema = schema["schema"]["properties"]["VARIABLES"]
# Patterned properties not supported in monaco-yaml, replace with additionalProperties.
monaco_variables_schema = {key: value for key, value in variables_schema.items() if key != "patternProperties"}
variables_pattern_properties = list(variables_schema["patternProperties"].values())
if len(variables_pattern_properties) > 1:
raise ValueError("Multiple patternProperties is not handled.")
monaco_variables_schema["additionalProperties"] = variables_pattern_properties[0]
schema["schema"]["properties"]["VARIABLES"] = monaco_variables_schema

schemas.append(json.dumps(schema))

# Then we just take the rest
for json_schema_file in sorted([file for file in JSON_SCHEMA_PATH.iterdir() if file.suffix == ".json"]):
Expand All @@ -66,21 +106,6 @@ def generate_json_schemas(server_url: str, docs_keywords_url: str) -> List[Schem
)
schemas.append(schema)

variables_schema = schema_of(
Variables, by_alias=True, title="Variables", ref_template=f"{VARIABLES_URI}#/definitions/{{model}}"
)

# Patterned properties not supported in monaco-yaml, replace with additionalProperties.
monaco_schema = {key: value for key, value in variables_schema.items() if key != "patternProperties"}

variables_pattern_properties = list(variables_schema["patternProperties"].values())

if len(variables_pattern_properties) > 1:
raise ValueError("Multiple patternProperties is not handled.")

monaco_schema["additionalProperties"] = variables_pattern_properties[0]
schemas.append(get_template(schema=json.dumps(monaco_schema), schema_name="variables.json", is_root=False))

processed_schemas = []
for schema in schemas:
content = schema.replace("$SERVER_NAME", server_url)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
"description": "Facility files",
"properties": {
"FACILITY_INPUTS": {
"title": "FACILITY_INPUTS",
"description": "Defines input files which characterize various facility elements.\n\n$ECALC_DOCS_KEYWORDS_URL/FACILITY_INPUTS",
"type": "array",
"items": {
"type": "object",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
"description": "Fuel types",
"properties": {
"FUEL_TYPES": {
"title": "FUEL_TYPES",
"description": "Specifies the various fuel types and associated emissions used in the model.\n\n$ECALC_DOCS_KEYWORDS_URL/FUEL_TYPES",
"type": "array",
"items": {
"type": "object",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
"description": "Installations",
"properties": {
"INSTALLATIONS": {
"title": "INSTALLATIONS",
"description": "Description of the system of energy consumers.\n\n$ECALC_DOCS_KEYWORDS_URL/INSTALLATIONS",
"type": "array",
"items": {
"type": "object",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
"description": "Models",
"properties": {
"MODELS": {
"title": "MODELS",
"description": "Defines input files which characterize various facility elements.\n\n$ECALC_DOCS_KEYWORDS_URL/MODELS",
"type": "array",
"items": {
"type": "object",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
from typing import Dict, Optional

from libecalc.input.yaml_types import YamlBase
from libecalc.input.yaml_types.variable import Variables
from pydantic import Field

# Dummy type used for attributes that aren't yet converted to pydantic yaml models
DummyType = Optional[Dict]


class YamlAsset(YamlBase):
"""An eCalc™ yaml file"""

class Config:
title = "Asset"

time_series: DummyType = Field(
None,
title="TIME_SERIES",
description="Defines the inputs for time dependent variables, or 'reservoir variables'."
"\n\n$ECALC_DOCS_KEYWORDS_URL/TIME_SERIES",
)
facility_inputs: DummyType = Field(
None,
title="FACILITY_INPUTS",
description="Defines input files which characterize various facility elements."
"\n\n$ECALC_DOCS_KEYWORDS_URL/FACILITY_INPUTS",
)
models: DummyType = Field(
None,
title="MODELS",
description="Defines input files which characterize various facility elements."
"\n\n$ECALC_DOCS_KEYWORDS_URL/MODELS",
)
fuel_types: DummyType = Field(
None,
title="FUEL_TYPES",
description="Specifies the various fuel types and associated emissions used in the model."
"\n\n$ECALC_DOCS_KEYWORDS_URL/FUEL_TYPES",
)
variables: Variables = Field(
None,
title="VARIABLES",
description="Defines variables used in an energy usage model by means of expressions or constants."
"\n\n$ECALC_DOCS_KEYWORDS_URL/VARIABLES",
)
installations: DummyType = Field(
...,
title="INSTALLATIONS",
description="Description of the system of energy consumers." "\n\n$ECALC_DOCS_KEYWORDS_URL/INSTALLATIONS",
)
start: str = Field(
None, # TODO: DefaultDatetime?
title="START",
description="Global start date for eCalc calculations in <YYYY-MM-DD> format."
"\n\n$ECALC_DOCS_KEYWORDS_URL/START",
)
end: str = Field(
None, # TODO: DefaultDatetime?
title="END",
description="Global end date for eCalc calculations in <YYYY-MM-DD> format." "\n\n$ECALC_DOCS_KEYWORDS_URL/END",
)
Loading

0 comments on commit 6818848

Please sign in to comment.