diff --git a/doc/release_notes.md b/doc/release_notes.md index a14921cf77..6a2b9a305c 100644 --- a/doc/release_notes.md +++ b/doc/release_notes.md @@ -6,6 +6,8 @@ +* Fix: `lines: types` must now define a line type for the 380 kV level; the config validation fails early with a clear message instead of the workflow failing later ([#2166](https://github.com/PyPSA/pypsa-eur/issues/2166)). + * Feature: New switches `industry: solid_biomass_for_industry_cc`, `industry: gas_for_industry_cc` and `industry: process_emissions_cc` to disable the carbon capture options for solid biomass for industry, gas for industry and industrial process emissions. All default to `true`, which matches the previous behaviour ([#2357](https://github.com/PyPSA/pypsa-eur/pull/2357)). * Feature: New option `sector: electrolysis` to allow hydrogen electrolysis to be configurable ([#2358](https://github.com/PyPSA/pypsa-eur/pull/2358)). diff --git a/scripts/lib/validation/config/lines.py b/scripts/lib/validation/config/lines.py index 125025f70c..e485e75d2c 100644 --- a/scripts/lib/validation/config/lines.py +++ b/scripts/lib/validation/config/lines.py @@ -10,7 +10,7 @@ from typing import Literal -from pydantic import BaseModel, Field +from pydantic import BaseModel, Field, field_validator from scripts.lib.validation.config._base import ConfigModel @@ -89,3 +89,12 @@ class LinesConfig(BaseModel): default_factory=_DynamicLineRatingConfig, description="Configuration for dynamic line rating.", ) + + @field_validator("types") + @classmethod + def check_380_defined(cls, value: dict[float, str]) -> dict[float, str]: + if 380.0 not in value: + raise ValueError( + "`lines: types` must define a line type for the 380 kV voltage level." + ) + return value diff --git a/test/test_config_schema.py b/test/test_config_schema.py index d6e8db1778..9d9d454a39 100644 --- a/test/test_config_schema.py +++ b/test/test_config_schema.py @@ -232,3 +232,15 @@ def test_config_file_is_valid(configfile): assert not invalid, f"Invalid config entries in {configfile}:\n" + "\n".join( f" - {path}: {'; '.join(msgs)}" for path, msgs in invalid.items() ) + + +class TestLineTypes: + def test_default_defines_380kv(self): + config = validate_config({}) + assert 380.0 in config.lines.types + + def test_missing_380kv_is_rejected(self): + with pytest.raises(ValueError, match="380"): + validate_config( + {"lines": {"types": {220.0: "Al/St 240/40 2-bundle 220.0"}}} + )