Skip to content

Commit

Permalink
fix: ensure emission names are unique
Browse files Browse the repository at this point in the history
Refs:
ECALC-896
  • Loading branch information
jsolaas committed Dec 10, 2024
1 parent 0b5e0ce commit 2bbb989
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 154 deletions.

This file was deleted.

38 changes: 0 additions & 38 deletions src/libecalc/examples/simple/model_duplicate_names.yaml

This file was deleted.

31 changes: 0 additions & 31 deletions src/libecalc/presentation/yaml/mappers/create_references.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

from libecalc.common.errors.exceptions import EcalcError
from libecalc.common.logger import logger
from libecalc.common.string.string_utils import get_duplicates
from libecalc.dto import EnergyModel
from libecalc.presentation.yaml.domain.reference_service import ReferenceService
from libecalc.presentation.yaml.mappers.facility_input import FacilityInputMapper
Expand Down Expand Up @@ -34,31 +33,6 @@ def create_references(configuration: YamlValidator, resources: Resources) -> Ref
resources=resources,
)

duplicated_fuel_names = get_duplicates([fuel_data.name for fuel_data in configuration.fuel_types])

if len(duplicated_fuel_names) > 0:
raise EcalcError(
title="Duplicate names",
message="Fuel type names must be unique across installations."
f" Duplicated names are: {', '.join(duplicated_fuel_names)}",
)

fuel_types_emissions = [fuel_data.emissions for fuel_data in configuration.fuel_types]

# Check each fuel for duplicated emissions
duplicated_emissions = []
for emissions in fuel_types_emissions:
duplicated_emissions.append(get_duplicates([emission.name for emission in emissions]))

duplicated_emissions_names = ",".join(name for string in duplicated_emissions for name in string if len(string) > 0)

if len(duplicated_emissions_names) > 0:
raise EcalcError(
title="Duplicate names",
message="Emission names must be unique for each fuel type. "
f"Duplicated names are: {duplicated_emissions_names}",
)

fuel_types = {fuel_data.name: FuelMapper.from_yaml_to_dto(fuel_data) for fuel_data in configuration.fuel_types}

return References(
Expand All @@ -79,11 +53,6 @@ def create_model_references(

for model in sorted_models:
model_reference = model.name
if model_reference in models_map:
raise EcalcError(
title="Duplicate reference",
message=f"The model '{model_reference}' is defined multiple times",
)
models_map[model_reference] = model_mapper.from_yaml_to_dto(model, models_map)

return models_map
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from pydantic import ConfigDict, Field
from pydantic import ConfigDict, Field, field_validator
from pydantic_core.core_schema import ValidationInfo

from libecalc.common.string.string_utils import get_duplicates
from libecalc.dto.types import FuelTypeUserDefinedCategoryType
from libecalc.presentation.yaml.yaml_types import YamlBase
from libecalc.presentation.yaml.yaml_types.components.yaml_category_field import (
Expand Down Expand Up @@ -30,3 +32,17 @@ class YamlFuelType(YamlBase):
description="Warning! Deprecated. Does not have any effect. Lower heating value [MJ/Sm3] of fuel. "
"Lower heating value is also known as net calorific value",
)

@field_validator("emissions", mode="after")
@classmethod
def ensure_unique_emission_names(cls, emissions, info: ValidationInfo):
names = [emission.name for emission in emissions]
duplicated_names = get_duplicates(names)

if len(duplicated_names) > 0:
raise ValueError(
f"{cls.model_fields[info.field_name].alias} names must be unique."
f" Duplicated names are: {', '.join(duplicated_names)}"
)

return emissions
14 changes: 0 additions & 14 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,9 @@ def rounded_snapshot(data: dict, snapshot_name: str):
}

invalid_example_cases = {
"simple_duplicate_names": (Path(simple.__file__).parent / "model_duplicate_names.yaml").absolute(),
"simple_multiple_energy_models_one_consumer": (
Path(simple.__file__).parent / "model_multiple_energy_models_one_consumer.yaml"
).absolute(),
"simple_duplicate_emissions_in_fuel": (
Path(simple.__file__).parent / "model_duplicate_emissions_in_fuel.yaml"
).absolute(),
}


Expand All @@ -94,21 +90,11 @@ def simple_temporal_yaml_path():
return valid_example_cases["simple_temporal"]


@pytest.fixture(scope="session")
def simple_duplicate_names_yaml_path():
return invalid_example_cases["simple_duplicate_names"]


@pytest.fixture(scope="session")
def simple_multiple_energy_models_yaml_path():
return invalid_example_cases["simple_multiple_energy_models_one_consumer"]


@pytest.fixture(scope="session")
def simple_duplicate_emissions_yaml_path():
return invalid_example_cases["simple_duplicate_emissions_in_fuel"]


@pytest.fixture(scope="session")
def advanced_yaml_path():
return valid_example_cases["advanced"]
Expand Down
28 changes: 0 additions & 28 deletions tests/ecalc_cli/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
from typer.testing import CliRunner

from ecalc_cli import main
from libecalc.common.errors.exceptions import EcalcError
from libecalc.common.run_info import RunInfo
from libecalc.dto.utils.validators import COMPONENT_NAME_ALLOWED_CHARS
from libecalc.presentation.yaml.model_validation_exception import ModelValidationException
Expand Down Expand Up @@ -459,33 +458,6 @@ def test_yaml_file_error(self):
f"Allowed characters are {COMPONENT_NAME_ALLOWED_CHARS}" in str(ee.value)
)

def test_yaml_duplicate_emissions_in_fuel(self, simple_duplicate_emissions_yaml_path, tmp_path):
"""
TEST SCOPE: Check that duplicate emission names for one fuel type are not allowed in Yaml file.
Args:
simple model file with duplicate emission names:
Returns:
"""
with pytest.raises(EcalcError) as exc_info:
runner.invoke(
main.app,
_get_args(
model_file=simple_duplicate_emissions_yaml_path,
csv=True,
output_folder=tmp_path,
name_prefix="test",
output_frequency="YEAR",
),
catch_exceptions=False,
)

assert "Emission names must be unique for each fuel type. " "Duplicated names are: CO2,CH4" in str(
exc_info.value
)

def test_yaml_multiple_energy_models_one_consumer(self, simple_multiple_energy_models_yaml_path, tmp_path):
"""
TEST SCOPE: Check that multiple energy models for one consumer are not allowed in Yaml file.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import pytest
from inline_snapshot import snapshot
from pydantic import ValidationError

from libecalc.testing.yaml_builder import YamlEmissionBuilder, YamlFuelTypeBuilder


@pytest.mark.snapshot
@pytest.mark.inlinesnapshot
def test_duplicate_emission_names():
with pytest.raises(ValidationError) as exc_info:
YamlFuelTypeBuilder().with_test_data().with_emissions(
[
YamlEmissionBuilder().with_test_data().with_name("co2").validate(),
YamlEmissionBuilder().with_test_data().with_name("co2").validate(),
]
).validate()

errors = exc_info.value.errors()
assert len(errors) == 1

assert errors[0]["msg"] == snapshot("Value error, EMISSIONS names must be unique. Duplicated names are: co2")

0 comments on commit 2bbb989

Please sign in to comment.