Skip to content

Commit 4fb6ea9

Browse files
authored
Re-add mistakenly removed method for loading a config from file (#492)
1 parent b10dfe8 commit 4fb6ea9

2 files changed

Lines changed: 79 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,17 @@ If upgrading from v2.x, see the [v3.0.0 release notes](https://github.com/flixOp
8181
8282
Until here -->
8383

84+
## [4.1.3] - 2025-11-25
85+
86+
**Summary**: Re-add mistakenly removed method for loading a config from file
87+
88+
If upgrading from v2.x, see the [v3.0.0 release notes](https://github.com/flixOpt/flixOpt/releases/tag/v3.0.0) and [Migration Guide](https://flixopt.github.io/flixopt/latest/user-guide/migration-guide-v3/).
89+
90+
### 🐛 Fixed
91+
- Re-added `CONFIG.load_from_file()` method that was accidentally removed
92+
93+
---
94+
8495
## [4.1.2] - 2025-11-24
8596

8697
**Summary**:

flixopt/config.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,74 @@ def browser_plotting(cls) -> type[CONFIG]:
718718

719719
return cls
720720

721+
@classmethod
722+
def load_from_file(cls, config_file: str | Path) -> type[CONFIG]:
723+
"""Load configuration from YAML file and apply it.
724+
725+
Args:
726+
config_file: Path to the YAML configuration file.
727+
728+
Returns:
729+
The CONFIG class for method chaining.
730+
731+
Raises:
732+
FileNotFoundError: If the config file does not exist.
733+
734+
Examples:
735+
```python
736+
CONFIG.load_from_file('my_config.yaml')
737+
```
738+
739+
Example YAML file:
740+
```yaml
741+
config_name: my_project
742+
modeling:
743+
big: 10000000
744+
epsilon: 0.00001
745+
solving:
746+
mip_gap: 0.001
747+
time_limit_seconds: 600
748+
plotting:
749+
default_engine: matplotlib
750+
default_dpi: 600
751+
```
752+
"""
753+
# Import here to avoid circular import
754+
from . import io as fx_io
755+
756+
config_path = Path(config_file)
757+
if not config_path.exists():
758+
raise FileNotFoundError(f'Config file not found: {config_file}')
759+
760+
config_dict = fx_io.load_yaml(config_path)
761+
cls._apply_config_dict(config_dict)
762+
763+
return cls
764+
765+
@classmethod
766+
def _apply_config_dict(cls, config_dict: dict) -> None:
767+
"""Apply configuration dictionary to class attributes.
768+
769+
Args:
770+
config_dict: Dictionary containing configuration values.
771+
"""
772+
for key, value in config_dict.items():
773+
if key == 'modeling' and isinstance(value, dict):
774+
for nested_key, nested_value in value.items():
775+
if hasattr(cls.Modeling, nested_key):
776+
setattr(cls.Modeling, nested_key, nested_value)
777+
elif key == 'solving' and isinstance(value, dict):
778+
for nested_key, nested_value in value.items():
779+
if hasattr(cls.Solving, nested_key):
780+
setattr(cls.Solving, nested_key, nested_value)
781+
elif key == 'plotting' and isinstance(value, dict):
782+
for nested_key, nested_value in value.items():
783+
if hasattr(cls.Plotting, nested_key):
784+
setattr(cls.Plotting, nested_key, nested_value)
785+
elif hasattr(cls, key) and key != 'logging':
786+
# Skip 'logging' as it requires special handling via CONFIG.Logging methods
787+
setattr(cls, key, value)
788+
721789

722790
def change_logging_level(level_name: str | int) -> None:
723791
"""Change the logging level for the flixopt logger.

0 commit comments

Comments
 (0)