mirror of
https://github.com/Akkudoktor-EOS/EOS.git
synced 2026-11-13 09:13:30 +01:00
The provider settings (weather, PV forecast, load, electricity price, feed-in tariff, electricity fee) validate their provider id against the providers of the prediction instance. While the configuration is created, that instance does not exist yet, and the validation falls back to fixed lists. These were incomplete: weather knew only 'WeatherImport', load lacked 'LoadAkkudoktorAdjusted'. A configuration file with e.g. weather provider 'OpenMeteo' then fails to load: Provider 'OpenMeteo' is not a valid weather provider: ['WeatherImport'] This is hidden today because ConfigEOS.documentation_mode() is always true (_force_documentation_mode is a pydantic private attribute, whose class attribute is a truthy descriptor), and get_prediction() then creates the prediction instance on access. Once documentation mode is enabled only explicitly, the configuration does not load. Derive the provider ids from the provider classes instead (prediction_provider_ids). They no longer depend on whether the prediction instance exists, so the validation is the same before and after initialization. Additional changes - Add the test fixture uncreated_config, which lets get_config(init=True) create a new configuration from the config file and restores the old one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
52 lines
1.7 KiB
Python
52 lines
1.7 KiB
Python
"""Weather forecast module for weather predictions."""
|
|
|
|
from typing import Optional
|
|
|
|
from pydantic import Field, computed_field, field_validator
|
|
|
|
from akkudoktoreos.config.configabc import SettingsBaseModel
|
|
from akkudoktoreos.prediction.weatherabc import WeatherProvider
|
|
from akkudoktoreos.prediction.weatherimport import WeatherImportCommonSettings
|
|
|
|
|
|
def weather_provider_ids() -> list[str]:
|
|
"""Valid weather provider ids."""
|
|
# From the provider classes: valid also while the configuration is created,
|
|
# before the prediction instance exists.
|
|
from akkudoktoreos.prediction.prediction import prediction_provider_ids
|
|
|
|
return prediction_provider_ids(WeatherProvider)
|
|
|
|
|
|
class WeatherCommonSettings(SettingsBaseModel):
|
|
"""Weather Forecast Configuration."""
|
|
|
|
provider: Optional[str] = Field(
|
|
default=None,
|
|
json_schema_extra={
|
|
"description": "Weather provider id of provider to be used.",
|
|
"examples": ["WeatherImport"],
|
|
},
|
|
)
|
|
|
|
weatherimport: WeatherImportCommonSettings = Field(
|
|
default_factory=WeatherImportCommonSettings,
|
|
json_schema_extra={"description": "Weather import provider settings"},
|
|
)
|
|
|
|
@computed_field # type: ignore[prop-decorator]
|
|
@property
|
|
def providers(self) -> list[str]:
|
|
"""Available weather provider ids."""
|
|
return weather_provider_ids()
|
|
|
|
# Validators
|
|
@field_validator("provider", mode="after")
|
|
@classmethod
|
|
def validate_provider(cls, value: Optional[str]) -> Optional[str]:
|
|
if value is None or value in weather_provider_ids():
|
|
return value
|
|
raise ValueError(
|
|
f"Provider '{value}' is not a valid weather provider: {weather_provider_ids()}."
|
|
)
|