Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
90afe72
⏺ Perfect! Everything is working correctly:
FBumann Nov 21, 2025
c235428
Update CHANGELOG.md and dependencies
FBumann Nov 21, 2025
81eaa6b
Updaet remaining classes to regular logger
FBumann Nov 21, 2025
9120226
Remove lazy and opt calls from loguru
FBumann Nov 21, 2025
ef694cf
Console defaults to stdout
FBumann Nov 21, 2025
dc520e3
Change critical level to bold red
FBumann Nov 21, 2025
764ba78
⏺ Perfect! The new improved format is now implemented and documented.
FBumann Nov 21, 2025
bdf109e
Also show ms
FBumann Nov 21, 2025
2d3cd60
Format: 2025-11-21 21:27:37.203 INFO │ Message
FBumann Nov 21, 2025
181f694
Use default color for INFO
FBumann Nov 21, 2025
4a2f323
Use thin for timestamp
FBumann Nov 21, 2025
f39df1b
Exported formatters - Users can now import MultilineFormatter and Col…
FBumann Nov 21, 2025
29f3fef
Synchronize formater in file and console
FBumann Nov 21, 2025
e20c1df
Add more presets and improve docstrings
FBumann Nov 21, 2025
f8058b5
Improve docstrings
FBumann Nov 21, 2025
a79df17
Make logging defualt and wanring only by default
FBumann Nov 21, 2025
5b1a738
Move logging setup to __init__.py
FBumann Nov 21, 2025
760b473
Update test_config.py
FBumann Nov 21, 2025
d582419
Simplify config tests
FBumann Nov 21, 2025
8de0381
Remove get_logger method
FBumann Nov 21, 2025
1ac223d
Bugfix from loguru code
FBumann Nov 21, 2025
44315dc
Bugfix
FBumann Nov 21, 2025
4a9b176
fixed all the imports for DEPRECATION_REMOVAL_VERSION to import from…
FBumann Nov 21, 2025
c73b8a8
linting
FBumann Nov 21, 2025
81796d6
fixed the critical exception handling bug in both custom formatters
FBumann Nov 21, 2025
c950d7a
moved the escape_codes import to module scope
FBumann Nov 21, 2025
2a3694d
1. Clarified the comment (line 64):
FBumann Nov 21, 2025
2a38495
Add guards for lazy logging
FBumann Nov 21, 2025
a05c8a2
logging instead of printing network app start
FBumann Nov 21, 2025
1cd0a70
fix the loguru-style logger.warning calls in linear_converters.py
FBumann Nov 21, 2025
e29fd26
Remove docstring message about deprecation
FBumann Nov 21, 2025
9b8b984
Improve CHANGELOG.md
FBumann Nov 21, 2025
27c8028
Shorten CHANGELOG.md
FBumann Nov 21, 2025
124ce4d
added two new tests to tests/test_config.py to verify exception loggi…
FBumann Nov 21, 2025
76a3632
Guard __all__ export of ColoredMultilineFormatter on COLORLOG_AVAILABLE
FBumann Nov 21, 2025
6c35188
fixed the handler-filtering logic in CONFIG.Logging.enable_file() an…
FBumann Nov 21, 2025
3c679eb
Fix CHANGELOG.md
FBumann Nov 21, 2025
f2783c0
Remove notebook preset
FBumann Nov 21, 2025
1761d6e
Update CHANGELOG.md
FBumann Nov 21, 2025
4b44aac
Update docs
FBumann Nov 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ body:
import numpy as np
import flixopt as fx

fx.CONFIG.Logging.console = True
fx.CONFIG.Logging.level = 'DEBUG'
fx.CONFIG.apply()
fx.CONFIG.Logging.enable_console('DEBUG')
flow_system = fx.FlowSystem(pd.date_range('2020-01-01', periods=3, freq='h'))

flow_system.add_elements(
Expand Down
95 changes: 94 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,107 @@ If upgrading from v2.x, see the [v3.0.0 release notes](https://github.com/flixOp
### 📦 Dependencies

### 📝 Docs
- Added missing examples to docs.

### 👷 Development

### 🚧 Known Issues

---

## [4.1.0] - 2025-11-21

**Summary**: Logging migrated from loguru to standard Python logging for stability and security. Simpler API with convenient presets.

!!! info "Migration Required?"
**Most users**: No action needed (silent by default). Methods like `CONFIG.exploring()`, `CONFIG.debug()`, etc. continue to work exactly as before.
**If you customized logging**: Simple API update (see migration below).
**If you used loguru directly**: Breaking change (loguru only in v3.6.0-v4.0.0, ~4 days).

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/).

### ✨ Added

**New logging presets**:
```python
CONFIG.production('app.log') # File-only, no console/plots
```

**New logging methods**:
- `CONFIG.Logging.enable_console(level, colored, stream)` - Console output with colors
- `CONFIG.Logging.enable_file(level, path, max_bytes, backup_count)` - File logging with rotation
- `CONFIG.Logging.disable()` - Disable all logging
- `CONFIG.Logging.set_colors(log_colors)` - Customize colors

**Enhanced formatting**:
- Multi-line messages with box borders (┌─, │, └─)
- Exception tracebacks with proper indentation
- Timestamps: `2025-11-21 14:30:45.123`

### 💥 Breaking Changes

**Logging migration** (edge cases only):

| Old (v3.6.0-v4.0.0) | New (v4.1.0+) |
|---------------------|---------------|
| `CONFIG.Logging.level = 'INFO'`<br>`CONFIG.Logging.console = True`<br>`CONFIG.apply()` | `CONFIG.Logging.enable_console('INFO')`<br>or `CONFIG.exploring()` |
| `CONFIG.Logging.file = 'app.log'` | `CONFIG.Logging.enable_file('INFO', 'app.log')` |
| `logger.opt(lazy=True)` | Built-in (automatic) |

**Migration**:
```python
# Before (v3.6.0-v4.0.0)
CONFIG.Logging.level = 'INFO'
CONFIG.Logging.console = True
CONFIG.apply()

# After (v4.1.0+)
CONFIG.Logging.enable_console('INFO') # or CONFIG.exploring()
```

### ♻️ Changed

- Replaced loguru with Python `logging` + optional `colorlog` for colors
- Configuration immediate (no `CONFIG.apply()` needed)
- Log format: `[dimmed timestamp] [colored level] │ message`
- Logs to `stdout` by default (configurable)
- SUCCESS level preserved (green, level 25)
- Performance: Expensive operations guarded with `logger.isEnabledFor()` checks

### 🗑️ Deprecated

- `change_logging_level(level)` → Use `CONFIG.Logging.enable_console(level)`. Removal in v5.0.0.

### 🔥 Removed

**CONFIG methods/attributes**:
- `CONFIG.apply()` → Use helper methods directly
- `CONFIG.Logging.level`, `.console`, `.file` → Use `enable_console()`/`enable_file()`
- `CONFIG.Logging.verbose_tracebacks`, `.rich`, `.Colors`, `.date_format`, `.format`, `.console_width`, `.show_path`, `.show_logger_name` → Use standard logging
- loguru features (`logger.opt()`, etc.)

### 🐛 Fixed

- `TypeError` in `check_bounds()` with loguru-style formatting
- Exception tracebacks not appearing in custom formatters
- Inconsistent formatting between console and file logs

### 🔒 Security

- Removed loguru dependency for reduced supply chain risk

### 📦 Dependencies

- **Removed:** `loguru >= 0.7.0`
- **Added:** `colorlog >= 6.8.0, < 7` (optional)

### 📝 Docs

- Preset comparison table in `CONFIG.Logging` docstring
- Color customization examples
- Migration guide with before/after code

---

Until here -->

## [4.0.0] - 2025-11-19
Expand Down
15 changes: 10 additions & 5 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,25 @@ pip install "flixopt[full]"

## Logging

FlixOpt uses [loguru](https://loguru.readthedocs.io/) for logging. Logging is silent by default but can be easily configured. For beginners, use our internal convenience methods. Experts can use loguru directly.
FlixOpt uses Python's standard logging module with optional colored output via [colorlog](https://github.com/borntyping/python-colorlog). Logging is silent by default but can be easily configured.

```python
from flixopt import CONFIG

# Enable console logging
CONFIG.Logging.console = True
CONFIG.Logging.level = 'INFO'
CONFIG.apply()
# Enable colored console logging
CONFIG.Logging.enable_console('INFO')

# Or use a preset configuration for exploring
CONFIG.exploring()
```

For advanced logging configuration, you can use Python's standard logging module directly:

```python
import logging
logging.basicConfig(level=logging.DEBUG)
```

For more details on logging configuration, see the [`CONFIG.Logging`][flixopt.config.CONFIG.Logging] documentation.

## Basic Workflow
Expand Down
12 changes: 6 additions & 6 deletions docs/user-guide/migration-guide-v3.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,12 @@ Terminology changed and sharing system inverted: effects now "pull" shares.

### Other Changes

| Category | Old (v2.x) | New (v3.0.0) |
|----------|------------|--------------|
| System model class | `SystemModel` | `FlowSystemModel` |
| Element submodel | `Model` | `Submodel` |
| Logging default | Enabled | Disabled |
| Enable logging | (default) | `fx.CONFIG.Logging.console = True; fx.CONFIG.apply()` |
| Category | Old (v2.x) | New (v3.0.0+) |
|------------------------|------------|---------------|
| System model class | `SystemModel` | `FlowSystemModel` |
| Element submodel | `Model` | `Submodel` |
| Logging default | Enabled | Disabled (silent) |
| Enable console logging | (default) | `fx.CONFIG.Logging.enable_console('INFO')` or `fx.CONFIG.exploring()` |

---

Expand Down
4 changes: 3 additions & 1 deletion examples/05_Two-stage-optimization/two_stage_optimization.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,17 @@
While the final optimum might differ from the global optimum, the solving will be much faster.
"""

import logging
import pathlib
import timeit

import pandas as pd
import xarray as xr
from loguru import logger

import flixopt as fx

logger = logging.getLogger('flixopt')

if __name__ == '__main__':
fx.CONFIG.exploring()

Expand Down
6 changes: 6 additions & 0 deletions flixopt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
This module bundles all common functionality of flixopt and sets up the logging
"""

import logging
import warnings
from importlib.metadata import PackageNotFoundError, version

Expand Down Expand Up @@ -60,6 +61,11 @@
'solvers',
]

# Initialize logger with default configuration (silent: WARNING level, NullHandler)
logger = logging.getLogger('flixopt')
logger.setLevel(logging.WARNING)
logger.addHandler(logging.NullHandler())

# === Runtime warning suppression for third-party libraries ===
# These warnings are from dependencies and cannot be fixed by end users.
# They are suppressed at runtime to provide a cleaner user experience.
Expand Down
7 changes: 5 additions & 2 deletions flixopt/aggregation.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
from __future__ import annotations

import copy
import logging
import pathlib
import timeit
from typing import TYPE_CHECKING

import numpy as np
from loguru import logger

try:
import tsam.timeseriesaggregation as tsam
Expand All @@ -37,6 +37,8 @@
from .elements import Component
from .flow_system import FlowSystem

logger = logging.getLogger('flixopt')


class Aggregation:
"""
Expand Down Expand Up @@ -104,7 +106,8 @@ def cluster(self) -> None:
self.aggregated_data = self.tsam.predictOriginalData()

self.clustering_duration_seconds = timeit.default_timer() - start_time # Zeit messen:
logger.opt(lazy=True).info('{result}', result=lambda: self.describe_clusters())
if logger.isEnabledFor(logging.INFO):
logger.info(self.describe_clusters())

def describe_clusters(self) -> str:
description = {}
Expand Down
12 changes: 6 additions & 6 deletions flixopt/calculation.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from __future__ import annotations

import logging
import math
import pathlib
import sys
Expand All @@ -19,7 +20,6 @@
from typing import TYPE_CHECKING, Annotated, Any

import numpy as np
from loguru import logger
from tqdm import tqdm

from . import io as fx_io
Expand All @@ -39,6 +39,8 @@
from .solvers import _Solver
from .structure import FlowSystemModel

logger = logging.getLogger('flixopt')


class Calculation:
"""
Expand Down Expand Up @@ -255,11 +257,9 @@ def solve(

# Log the formatted output
should_log = log_main_results if log_main_results is not None else CONFIG.Solving.log_main_results
if should_log:
logger.opt(lazy=True).info(
'{result}',
result=lambda: f'{" Main Results ":#^80}\n'
+ fx_io.format_yaml_string(self.main_results, compact_numeric_lists=True),
if should_log and logger.isEnabledFor(logging.INFO):
logger.info(
f'{" Main Results ":#^80}\n' + fx_io.format_yaml_string(self.main_results, compact_numeric_lists=True)
)

self.results = CalculationResults.from_calculation(self)
Expand Down
5 changes: 4 additions & 1 deletion flixopt/color_processing.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@

from __future__ import annotations

import logging

import matplotlib.colors as mcolors
import matplotlib.pyplot as plt
import plotly.express as px
from loguru import logger
from plotly.exceptions import PlotlyError

logger = logging.getLogger('flixopt')


def _rgb_string_to_hex(color: str) -> str:
"""Convert Plotly RGB/RGBA string format to hex.
Expand Down
7 changes: 5 additions & 2 deletions flixopt/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,30 @@

from __future__ import annotations

import logging
import warnings
from typing import TYPE_CHECKING, Literal

import numpy as np
import xarray as xr
from loguru import logger

from . import io as fx_io
from .config import DEPRECATION_REMOVAL_VERSION
from .core import PlausibilityError
from .elements import Component, ComponentModel, Flow
from .features import InvestmentModel, PiecewiseModel
from .interface import InvestParameters, OnOffParameters, PiecewiseConversion
from .modeling import BoundingPatterns
from .structure import DEPRECATION_REMOVAL_VERSION, FlowSystemModel, register_class_for_io
from .structure import FlowSystemModel, register_class_for_io

if TYPE_CHECKING:
import linopy

from .flow_system import FlowSystem
from .types import Numeric_PS, Numeric_TPS

logger = logging.getLogger('flixopt')


@register_class_for_io
class LinearConverter(Component):
Expand Down
Loading