Skip to content
Merged
Show file tree
Hide file tree
Changes from 23 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
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,42 @@ If upgrading from v2.x, see the [v3.0.0 release notes](https://github.com/flixOp

### ♻️ Changed

**Logging system simplified:**
- Replaced loguru with standard Python logging module
- Added optional colorlog for colored console output (enabled by default)
- New simplified API:
- `CONFIG.Logging.enable_console('INFO')` - enable colored console logging to stdout (configurable)
- `CONFIG.Logging.enable_file('INFO', 'app.log')` - enable file logging with rotation
- `CONFIG.Logging.disable()` - disable all logging
- Removed `CONFIG.apply()` - configuration is now immediate
- Improved log format: `[dimmed time] [colored level] │ message`
- Logs go to stdout by default (configurable via `stream` parameter)
- Preserved SUCCESS log level (green) and multi-line formatting with box borders
- Users can still use standard `logging.basicConfig()` for full control

### 🗑️ Deprecated

### 🔥 Removed

**Logging:**
- Removed `CONFIG.apply()` method - configuration is now immediate via helper methods
- Removed `CONFIG.Logging.level`, `CONFIG.Logging.console`, `CONFIG.Logging.file` attributes - use new helper methods instead
- Removed loguru dependency

### 🐛 Fixed

### 🔒 Security

- Addressed security concerns by removing loguru dependency

### 📦 Dependencies

- **Replaced:** `loguru` → `colorlog` (optional, for colored console output)
- **Added:** `colorlog >= 6.8.0, < 7` as a core dependency (optional import)

### 📝 Docs
- Added missing examples to docs.
- Updated logging documentation to reflect new simplified API

### 👷 Development

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
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,14 +7,16 @@
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

logger = logging.getLogger('flixopt')

import flixopt as fx

Check failure on line 19 in examples/05_Two-stage-optimization/two_stage_optimization.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (E402)

examples/05_Two-stage-optimization/two_stage_optimization.py:19:1: E402 Module level import not at top of file

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,8 +2,9 @@
This module bundles all common functionality of flixopt and sets up the logging
"""

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

Check failure on line 7 in flixopt/__init__.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (I001)

flixopt/__init__.py:5:1: I001 Import block is un-sorted or un-formatted

try:
__version__ = version('flixopt')
Expand Down Expand Up @@ -60,6 +61,11 @@
'solvers',
]

# Initialize logger with default configuration (silent: WARNING level, no handlers)
_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
5 changes: 3 additions & 2 deletions flixopt/aggregation.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
Through this, aggregating TimeSeriesData is possible.
"""

from __future__ import annotations

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

import numpy as np

Check failure on line 14 in flixopt/aggregation.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (I001)

flixopt/aggregation.py:6:1: I001 Import block is un-sorted or un-formatted
from loguru import logger

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

logger = logging.getLogger('flixopt')

class Aggregation:
"""
Expand Down Expand Up @@ -104,7 +105,7 @@
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())
logger.info(self.describe_clusters())

def describe_clusters(self) -> str:
description = {}
Expand Down
10 changes: 5 additions & 5 deletions flixopt/calculation.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,28 @@
3. SegmentedCalculation: Solves a FlowSystemModel for each individual Segment of the FlowSystem.
"""

from __future__ import annotations

import math
import pathlib
import sys
import timeit
import warnings
from collections import Counter
from typing import TYPE_CHECKING, Annotated, Any
import logging

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

from . import io as fx_io
from .aggregation import Aggregation, AggregationModel, AggregationParameters
from .components import Storage
from .config import CONFIG
from .core import DataConverter, TimeSeriesData, drop_constant_arrays
from .features import InvestmentModel
from .flow_system import FlowSystem
from .results import CalculationResults, SegmentedCalculationResults

Check failure on line 32 in flixopt/calculation.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (I001)

flixopt/calculation.py:11:1: I001 Import block is un-sorted or un-formatted

if TYPE_CHECKING:
import pandas as pd
Expand All @@ -39,6 +39,7 @@
from .solvers import _Solver
from .structure import FlowSystemModel

logger = logging.getLogger('flixopt')

class Calculation:
"""
Expand Down Expand Up @@ -256,10 +257,9 @@
# 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),
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
4 changes: 3 additions & 1 deletion flixopt/color_processing.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@
into a label-to-color mapping dictionary, without needing to know about the plotting engine.
"""

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

Check failure on line 13 in flixopt/color_processing.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (I001)

flixopt/color_processing.py:7:1: I001 Import block is un-sorted or un-formatted

logger = logging.getLogger('flixopt')


def _rgb_string_to_hex(color: str) -> str:
"""Convert Plotly RGB/RGBA string format to hex.
Expand Down
6 changes: 4 additions & 2 deletions flixopt/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,31 @@
This module contains the basic components of the flixopt framework.
"""

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 .core import PlausibilityError
from .elements import Component, ComponentModel, Flow
from .features import InvestmentModel, PiecewiseModel
from .config import DEPRECATION_REMOVAL_VERSION
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

Check failure on line 21 in flixopt/components.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (I001)

flixopt/components.py:5:1: I001 Import block is un-sorted or un-formatted

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