diff --git a/docs/_generated/openapi.md b/docs/_generated/openapi.md index b7130adf..de1cea46 100644 --- a/docs/_generated/openapi.md +++ b/docs/_generated/openapi.md @@ -1,6 +1,6 @@ # Akkudoktor-EOS -**Version**: `v0.3.0.dev2607171715033828` +**Version**: `v0.3.0.dev2607181096091018` **Description**: This project provides a comprehensive solution for simulating and optimizing an energy system based on renewable energy sources. With a focus on photovoltaic (PV) systems, battery storage (batteries), load management (consumer requirements), heat pumps, electric vehicles, and consideration of electricity price data, this system enables forecasting and optimization of energy flow and costs over a specified period. diff --git a/openapi.json b/openapi.json index c2ca35f4..c7f9db52 100644 --- a/openapi.json +++ b/openapi.json @@ -8,7 +8,7 @@ "name": "Apache 2.0", "url": "https://www.apache.org/licenses/LICENSE-2.0.html" }, - "version": "v0.3.0.dev2607171715033828" + "version": "v0.3.0.dev2607181096091018" }, "paths": { "/v1/admin/cache/clear": { diff --git a/scripts/generate_openapi_md.py b/scripts/generate_openapi_md.py index d3b65122..91f32dda 100755 --- a/scripts/generate_openapi_md.py +++ b/scripts/generate_openapi_md.py @@ -33,7 +33,7 @@ def akkudoktoreos_base_branch(): # Get the current branch try: current_branch = repo.active_branch.name - except: + except Exception: # Maybe detached branch that has no name return None diff --git a/src/akkudoktoreos/adapter/homeassistant.py b/src/akkudoktoreos/adapter/homeassistant.py index 3544d08c..748940ec 100644 --- a/src/akkudoktoreos/adapter/homeassistant.py +++ b/src/akkudoktoreos/adapter/homeassistant.py @@ -146,7 +146,7 @@ class HomeAssistantAdapterCommonSettings(SettingsBaseModel): try: adapter_eos = get_adapter() result = adapter_eos.provider_by_id("HomeAssistant").get_homeassistant_entity_ids() - except: + except Exception: return [] return result @@ -157,7 +157,7 @@ class HomeAssistantAdapterCommonSettings(SettingsBaseModel): try: adapter_eos = get_adapter() result = adapter_eos.provider_by_id("HomeAssistant").get_eos_solution_entity_ids() - except: + except Exception: return [] return result @@ -170,7 +170,7 @@ class HomeAssistantAdapterCommonSettings(SettingsBaseModel): result = adapter_eos.provider_by_id( "HomeAssistant" ).get_eos_device_instruction_entity_ids() - except: + except Exception: return [] return result @@ -256,7 +256,7 @@ class HomeAssistantAdapter(AdapterProvider): optimization_solution_keys = self.config.optimization.keys for key in sorted(optimization_solution_keys): solution_entity_ids.append(self._entity_id_from_solution_key(key)) - except: + except Exception: solution_entity_ids = [] return solution_entity_ids diff --git a/src/akkudoktoreos/core/dataabc.py b/src/akkudoktoreos/core/dataabc.py index a2eee923..ccfa251d 100644 --- a/src/akkudoktoreos/core/dataabc.py +++ b/src/akkudoktoreos/core/dataabc.py @@ -250,7 +250,7 @@ class DataRecord(DataABC, MutableMapping): try: # Let getattr do the work return self.__getattr__(key) - except: + except AttributeError: raise KeyError(f"'{key}' not found in the record fields.") def __setitem__(self, key: str, value: Any) -> None: @@ -266,7 +266,7 @@ class DataRecord(DataABC, MutableMapping): try: # Let setattr do the work self.__setattr__(key, value) - except: + except AttributeError: raise KeyError(f"'{key}' is not a recognized field.") def __delitem__(self, key: str) -> None: @@ -280,7 +280,7 @@ class DataRecord(DataABC, MutableMapping): """ try: self.__delattr__(key) - except: + except AttributeError: raise KeyError(f"'{key}' is not a recognized field.") def __iter__(self) -> Iterator[str]: diff --git a/src/akkudoktoreos/core/databaseabc.py b/src/akkudoktoreos/core/databaseabc.py index 1e50844f..ee5192f0 100644 --- a/src/akkudoktoreos/core/databaseabc.py +++ b/src/akkudoktoreos/core/databaseabc.py @@ -809,7 +809,7 @@ class DatabaseRecordProtocolMixin( self._db_load_phase = DatabaseRecordProtocolLoadPhase.NONE try: del self._db_initialized - except: + except Exception: logger.debug("_db_reset_state called on uninitialized sequence") def _db_clone_empty(self: T_DatabaseRecordProtocol) -> T_DatabaseRecordProtocol: diff --git a/src/akkudoktoreos/core/logsettings.py b/src/akkudoktoreos/core/logsettings.py index 4a32a8d4..2a08c82b 100644 --- a/src/akkudoktoreos/core/logsettings.py +++ b/src/akkudoktoreos/core/logsettings.py @@ -37,7 +37,7 @@ class LoggingCommonSettings(SettingsBaseModel): """Computed log file path based on data output path.""" try: path = SettingsBaseModel.config.general.data_output_path / "eos.log" - except: + except Exception: # Config may not be fully set up path = None return path diff --git a/src/akkudoktoreos/core/pydantic.py b/src/akkudoktoreos/core/pydantic.py index b29466e4..ef496922 100644 --- a/src/akkudoktoreos/core/pydantic.py +++ b/src/akkudoktoreos/core/pydantic.py @@ -133,8 +133,8 @@ class PydanticModelNestedValueMixin: try: self._validate_path_structure(path) pass - except: - raise ValueError(f"Path '{path}' is invalid") + except Exception as e: + raise ValueError(f"Path '{path}' is invalid: {e}") path = path.strip("/") # Use private data workaround # Should be: diff --git a/src/akkudoktoreos/optimization/genetic/genetic.py b/src/akkudoktoreos/optimization/genetic/genetic.py index a420df2f..4c43f93d 100644 --- a/src/akkudoktoreos/optimization/genetic/genetic.py +++ b/src/akkudoktoreos/optimization/genetic/genetic.py @@ -974,7 +974,7 @@ class GeneticOptimization(OptimizationBase): if self.optimize_ev and parameters.eauto and self.simulation.ev: try: penalty = self.config.optimization.genetic.penalties["ev_soc_miss"] - except: + except Exception: # Use default penalty = 10 logger.error( @@ -1005,7 +1005,7 @@ class GeneticOptimization(OptimizationBase): individuals = self.config.optimization.genetic.individuals if individuals is None: raise - except: + except Exception: individuals = 300 logger.error("Individuals not configured. Using {}.", individuals) @@ -1076,7 +1076,7 @@ class GeneticOptimization(OptimizationBase): if generations is None: try: generations = self.config.optimization.genetic.generations - except: + except Exception: generations = 400 logger.error("Generations not configured. Using {}.", generations) diff --git a/src/akkudoktoreos/optimization/genetic/geneticparams.py b/src/akkudoktoreos/optimization/genetic/geneticparams.py index 4469576f..28d2fd64 100644 --- a/src/akkudoktoreos/optimization/genetic/geneticparams.py +++ b/src/akkudoktoreos/optimization/genetic/geneticparams.py @@ -282,9 +282,9 @@ class GeneticOptimizationParameters( fill_method="linear", ) pvforecast_ac_power = (array * power_to_energy_per_interval_factor).to_list() - except: + except Exception as e: logger.info( - "No PV forecast data available - defaulting to demo data. Parameter preparation attempt {}.", + "No PV forecast data available - defaulting to demo data. Parameter preparation attempt {}: {e}", attempt, ) cls.config.merge_settings_from_dict( @@ -336,9 +336,9 @@ class GeneticOptimizationParameters( fill_method="ffill", ) elecprice_marketprice_wh = array.to_list() - except: + except Exception as e: logger.info( - "No Electricity Marketprice forecast data available - defaulting to demo data. Parameter preparation attempt {}.", + "No Electricity Marketprice forecast data available - defaulting to demo data. Parameter preparation attempt {}: {e}", attempt, ) cls.config.elecprice.provider = "ElecPriceAkkudoktor" @@ -353,9 +353,9 @@ class GeneticOptimizationParameters( fill_method="ffill", ) loadforecast_power_w = array.to_list() - except: + except Exception as e: logger.info( - "No Load forecast data available - defaulting to demo data. Parameter preparation attempt {}.", + "No Load forecast data available - defaulting to demo data. Parameter preparation attempt {}: {e}", attempt, ) cls.config.merge_settings_from_dict( @@ -379,9 +379,9 @@ class GeneticOptimizationParameters( fill_method="ffill", ) feed_in_tariff_wh = array.to_list() - except: + except Exception as e: logger.info( - "No feed in tariff forecast data available - defaulting to demo data. Parameter preparation attempt {}.", + "No feed in tariff forecast data available - defaulting to demo data. Parameter preparation attempt {}: {e}", attempt, ) cls.config.merge_settings_from_dict( @@ -407,9 +407,9 @@ class GeneticOptimizationParameters( fill_method="ffill", ) weather_temp_air = array.to_list() - except: + except Exception as e: logger.info( - "No weather forecast data available - defaulting to demo data. Parameter preparation attempt {}.", + "No weather forecast data available - defaulting to demo data. Parameter preparation attempt {}: {e}", attempt, ) cls.config.weather.provider = "BrightSky" @@ -442,9 +442,9 @@ class GeneticOptimizationParameters( max_soc_percentage=battery_config.max_soc_percentage, charge_rates=battery_config.charge_rates, ) - except: + except Exception as e: logger.info( - "No battery device data available - defaulting to demo data. Parameter preparation attempt {}.", + "No battery device data available - defaulting to demo data. Parameter preparation attempt {}: {e}", attempt, ) cls.config.devices.batteries = [{"device_id": "battery1", "capacity_wh": 8000}] @@ -472,7 +472,7 @@ class GeneticOptimizationParameters( initial_soc_factor = 0.0 # genetic parameter is 0..100 as int initial_soc_percentage = int(initial_soc_factor * 100) - except: + except Exception: initial_soc_percentage = None if initial_soc_percentage is None: logger.info( @@ -514,9 +514,9 @@ class GeneticOptimizationParameters( min_soc_percentage=electric_vehicle_config.min_soc_percentage, max_soc_percentage=electric_vehicle_config.max_soc_percentage, ) - except: + except Exception as e: logger.info( - "No electric_vehicle device data available - defaulting to demo data. Parameter preparation attempt {}.", + "No electric_vehicle device data available - defaulting to demo data. Parameter preparation attempt {}: {e}", attempt, ) cls.config.devices.max_electric_vehicles = 1 @@ -544,7 +544,7 @@ class GeneticOptimizationParameters( initial_soc_factor = 0.0 # genetic parameter is 0..100 as int initial_soc_percentage = int(initial_soc_factor * 100) - except: + except Exception: initial_soc_percentage = None if initial_soc_percentage is None: logger.info( @@ -580,9 +580,9 @@ class GeneticOptimizationParameters( dc_to_ac_efficiency=inverter_config.dc_to_ac_efficiency, max_ac_charge_power_w=inverter_config.max_ac_charge_power_w, ) - except: + except Exception as e: logger.info( - "No inverter device data available - defaulting to demo data. Parameter preparation attempt {}.", + "No inverter device data available - defaulting to demo data. Parameter preparation attempt {}: {e}", attempt, ) cls.config.devices.inverters = [ @@ -635,9 +635,9 @@ class GeneticOptimizationParameters( duration_h=home_appliance_config.duration_h, time_windows=home_appliance_config.time_windows, ) - except: + except Exception as e: logger.info( - "No home appliance device data available - defaulting to demo data. Parameter preparation attempt {}.", + "No home appliance device data available - defaulting to demo data. Parameter preparation attempt {}: {e}", attempt, ) cls.config.devices.home_appliances = [ @@ -668,9 +668,9 @@ class GeneticOptimizationParameters( dishwasher=home_appliance_params, start_solution=start_solution, ) - except: + except Exception as e: logger.info( - "Can not prepare optimization parameters - will retry. Parameter preparation attempt {}.", + "Can not prepare optimization parameters - will retry. Parameter preparation attempt {}: {e}", attempt, ) oparams = None diff --git a/src/akkudoktoreos/optimization/optimization.py b/src/akkudoktoreos/optimization/optimization.py index a6c52530..3b66a6d1 100644 --- a/src/akkudoktoreos/optimization/optimization.py +++ b/src/akkudoktoreos/optimization/optimization.py @@ -100,7 +100,7 @@ class OptimizationCommonSettings(SettingsBaseModel): """The keys of the solution.""" try: ems_eos = get_ems() - except: + except Exception: # ems might not be initialized return [] diff --git a/src/akkudoktoreos/prediction/elecprice.py b/src/akkudoktoreos/prediction/elecprice.py index e67bdb91..848758ea 100644 --- a/src/akkudoktoreos/prediction/elecprice.py +++ b/src/akkudoktoreos/prediction/elecprice.py @@ -16,7 +16,7 @@ def elecprice_provider_ids() -> list[str]: """Valid elecprice provider ids.""" try: prediction_eos = get_prediction() - except: + except Exception: # Prediction may not be initialized # Return at least provider used in example return ["ElecPriceAkkudoktor"] diff --git a/src/akkudoktoreos/prediction/feedintariff.py b/src/akkudoktoreos/prediction/feedintariff.py index 559711a2..095970e8 100644 --- a/src/akkudoktoreos/prediction/feedintariff.py +++ b/src/akkudoktoreos/prediction/feedintariff.py @@ -13,7 +13,7 @@ def feedintariff_provider_ids() -> list[str]: """Valid feedintariff provider ids.""" try: prediction_eos = get_prediction() - except: + except Exception: # Prediction may not be initialized # Return at least provider used in example return ["FeedInTariffFixed", "FeedInTarifImport"] diff --git a/src/akkudoktoreos/prediction/feedintarifffixed.py b/src/akkudoktoreos/prediction/feedintarifffixed.py index eab525b4..45566803 100644 --- a/src/akkudoktoreos/prediction/feedintarifffixed.py +++ b/src/akkudoktoreos/prediction/feedintarifffixed.py @@ -40,7 +40,7 @@ class FeedInTariffFixed(FeedInTariffProvider): feed_in_tariff = ( self.config.feedintariff.provider_settings.FeedInTariffFixed.feed_in_tariff_kwh ) - except: + except Exception: logger.exception(error_msg) raise ValueError(error_msg) if feed_in_tariff is None: diff --git a/src/akkudoktoreos/prediction/load.py b/src/akkudoktoreos/prediction/load.py index 6800bf2c..6fe5b2bc 100644 --- a/src/akkudoktoreos/prediction/load.py +++ b/src/akkudoktoreos/prediction/load.py @@ -16,7 +16,7 @@ def load_providers() -> list[str]: """Valid load provider ids.""" try: prediction_eos = get_prediction() - except: + except Exception: # Prediction may not be initialized # Return at least provider used in example return ["LoadAkkudoktor", "LoadVrm", "LoadImport"] diff --git a/src/akkudoktoreos/prediction/pvforecast.py b/src/akkudoktoreos/prediction/pvforecast.py index 61381e73..6816f9a8 100644 --- a/src/akkudoktoreos/prediction/pvforecast.py +++ b/src/akkudoktoreos/prediction/pvforecast.py @@ -20,7 +20,7 @@ def pvforecast_provider_ids() -> list[str]: """Valid PV forecast providers.""" try: prediction_eos = get_prediction() - except: + except Exception: # Prediction may not be initialized # Return at least provider used in example return [ diff --git a/src/akkudoktoreos/prediction/weather.py b/src/akkudoktoreos/prediction/weather.py index 90873b67..65b8d839 100644 --- a/src/akkudoktoreos/prediction/weather.py +++ b/src/akkudoktoreos/prediction/weather.py @@ -14,7 +14,7 @@ def weather_provider_ids() -> list[str]: """Valid weather provider ids.""" try: prediction_eos = get_prediction() - except: + except Exception: # Prediction may not be initialized # Return at least provider used in example return ["WeatherImport"] diff --git a/src/akkudoktoreos/server/dash/configuration.py b/src/akkudoktoreos/server/dash/configuration.py index 255bf9bc..b8fe887b 100644 --- a/src/akkudoktoreos/server/dash/configuration.py +++ b/src/akkudoktoreos/server/dash/configuration.py @@ -528,7 +528,7 @@ def Configuration( value_json_str: str = data.get("value", "") try: value = json.loads(value_json_str) - except: + except Exception: if value_json_str in ("None", "none", "Null", "null"): value = None else: @@ -602,7 +602,7 @@ def Configuration( # find some special configuration values try: max_planes = int(config_details["pvforecast.max_planes"]["value"]) - except: + except Exception: max_planes = 0 logger.debug(f"max_planes: {max_planes}") @@ -610,7 +610,7 @@ def Configuration( homeassistant_entity_ids = json.loads( config_details["adapter.homeassistant.homeassistant_entity_ids"]["value"] ) - except: + except Exception: homeassistant_entity_ids = [] logger.debug(f"homeassistant_entity_ids: {homeassistant_entity_ids}") @@ -619,7 +619,7 @@ def Configuration( eos_solution_entity_ids = json.loads( config_details["adapter.homeassistant.eos_solution_entity_ids"]["value"] ) - except: + except Exception: eos_solution_entity_ids = [] logger.debug(f"eos_solution_entity_ids {eos_solution_entity_ids}") @@ -628,14 +628,14 @@ def Configuration( eos_device_instruction_entity_ids = json.loads( config_details["adapter.homeassistant.eos_device_instruction_entity_ids"]["value"] ) - except: + except Exception: eos_device_instruction_entity_ids = [] logger.debug(f"eos_device_instruction_entity_ids {eos_device_instruction_entity_ids}") devices_measurement_keys = [] try: devices_measurement_keys = json.loads(config_details["devices.measurement_keys"]["value"]) - except: + except Exception: devices_measurement_keys = [] logger.debug(f"devices_measurement_keys {devices_measurement_keys}") @@ -691,7 +691,7 @@ def Configuration( # Special configuration for prediction provider setting try: provider_ids = json.loads(config_details[config["name"] + "s"]["value"]) - except: + except Exception: provider_ids = [] if config["type"].startswith("Optional[list"): update_form_factory = make_config_update_list_form(provider_ids) diff --git a/src/akkudoktoreos/server/eos.py b/src/akkudoktoreos/server/eos.py index 6a1b416c..3ddc8375 100755 --- a/src/akkudoktoreos/server/eos.py +++ b/src/akkudoktoreos/server/eos.py @@ -521,10 +521,10 @@ def fastapi_config_file_put() -> ConfigEOS: try: get_config().to_config_file() return get_config() - except: + except Exception as e: raise HTTPException( status_code=404, - detail=f"Cannot save configuration to file '{get_config().config_file_path}'.", + detail=f"Cannot save configuration to file '{get_config().config_file_path}': {e}", ) diff --git a/src/akkudoktoreos/utils/datetimeutil.py b/src/akkudoktoreos/utils/datetimeutil.py index e7a8370e..f699a0a1 100644 --- a/src/akkudoktoreos/utils/datetimeutil.py +++ b/src/akkudoktoreos/utils/datetimeutil.py @@ -416,8 +416,8 @@ def _parse_time_string(time_str: str, default_date: pendulum.Date = None) -> pen # Try to parse as a standard timezone name try: timezone_info = pendulum.timezone(timezone_str) - except: - raise ValueError(f"Unknown timezone: {timezone_str}") + except Exception as e: + raise ValueError(f"Unknown timezone: {timezone_str}: {e}") elif re.match(r"[+-]\d{2}:?\d{2}", timezone_str): # Handle offset format like +05:30, -08:00, +0530, -0800 clean_tz = timezone_str.replace(":", "") diff --git a/tests/conftest.py b/tests/conftest.py index 2fd64cb4..2eff0cee 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -44,7 +44,7 @@ def caplog(caplog: LogCaptureFixture): yield caplog try: logger.remove(handler_id) - except: + except Exception: # May already be deleted pass @@ -57,7 +57,7 @@ def reportlog(pytestconfig): yield try: logger.remove(handler_id) - except: + except Exception: # May already be deleted pass