Skip to content

Conversation

@FBumann
Copy link
Member

@FBumann FBumann commented Nov 23, 2025

Description

Brief description of the changes in this PR.

Type of Change

  • Bug fix
  • New feature
  • Documentation update
  • Code refactoring

Related Issues

Closes #(issue number)

Testing

  • I have tested my changes
  • Existing tests still pass

Checklist

  • My code follows the project style
  • I have updated documentation if needed
  • I have added tests for new functionality (if applicable)

Summary by CodeRabbit

  • New Features

    • Added a SUCCESS log level for explicit success-message control.
  • Improvements

    • Improved logger color rendering and formatting for clearer output.
  • Behavior Changes

    • Mixing deprecated and new parameter names now emits a DeprecationWarning (before errors) to ease migration.
  • Tests

    • Tests updated to cover the new SUCCESS level and the deprecation-warning behaviors.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 23, 2025

Walkthrough

Replaces the monkey-patched Logger.success with a registered custom log level SUCCESS (int 25) exported as SUCCESS_LEVEL; updates logging callers to use logger.log(SUCCESS_LEVEL, ...), adjusts logging config signatures/type hints and formatting, and updates tests and CHANGELOG accordingly.

Changes

Cohort / File(s) Summary
Logging core
flixopt/config.py
Adds SUCCESS_LEVEL (value 25) and registers it with logging; removes the logging.Logger.success monkey-patch; adds TYPE_CHECKING/TextIO typing; updates CONFIG.Logging.enable_console/enable_file to accept "SUCCESS" and numeric levels; adjusts formatter spacing; exports SUCCESS_LEVEL in __all__.
Logging callers
flixopt/calculation.py, flixopt/network_app.py, flixopt/results.py
Import SUCCESS_LEVEL and replace logger.success(...) calls with logger.log(SUCCESS_LEVEL, ...).
Tests
tests/test_config.py, tests/test_invest_parameters_deprecation.py
tests/test_config.py updated to exercise SUCCESS_LEVEL (numeric and constant usage, file logging, coloring); tests/test_invest_parameters_deprecation.py updated to assert DeprecationWarning emissions alongside previous errors in parameter-deprecation scenarios.
Changelog
CHANGELOG.md
Documents export of SUCCESS_LEVEL and improved logger coloring/formatting.

Sequence Diagram(s)

(Skipped — changes are registration of a logging level and call-site replacements; no new runtime control-flow worth diagramming.)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review flixopt/config.py for correct registration of the SUCCESS level, correct numeric value propagation, and no remaining monkey-patch of logging.Logger.
  • Verify all call sites consistently use logger.log(SUCCESS_LEVEL, ...) and imports are updated.
  • Check tests (tests/test_config.py, tests/test_invest_parameters_deprecation.py) for correct assertions around the new level and deprecation warnings.

Possibly related PRs

  • Feature/logging #463 — Related changes migrating logging calls and prior introduction of logger.success usage across the same modules.
  • Feature/loguru cve2 #483 — Related modifications to the logging subsystem and exposure of a SUCCESS-level API.

Suggested labels

v3.0.0

Poem

🐰 I hopped through lines both neat and tall,
I set a level — SUCCESS for all.
No monkey-patch, just tidy cheer,
Now logs will sing when wins appear.
🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description uses template placeholders without providing actual content for key sections like summary and related issues, and testing status is incomplete. Replace template placeholders with concrete descriptions of changes, specify the related issue number, and complete the testing checklist with actual testing status.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: improving logging coloring and replacing the logger.success() method with a new SUCCESS_LEVEL constant.
Docstring Coverage ✅ Passed Docstring coverage is 95.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/logging

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@FBumann
Copy link
Member Author

FBumann commented Nov 23, 2025

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 23, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
flixopt/config.py (1)

23-31: SUCCESS level export and mapping look good; update method arg docs for completeness

The introduction of SUCCESS_LEVEL (25), its export via __all__, and the explicit "SUCCESS" string handling in enable_console/enable_file are all consistent with the new Logging docs and usage examples.

Minor nit: the Args: sections for both Logging.enable_console and Logging.enable_file still say:

level: Log level (DEBUG, INFO, WARNING, ERROR, CRITICAL or logging constant)

Given you now explicitly support the 'SUCCESS' string (and document the SUCCESS level below), it would be clearer to mention it here as well, e.g.:

level: Log level (DEBUG, INFO, SUCCESS, WARNING, ERROR, CRITICAL or numeric level)

This avoids users thinking SUCCESS is only available numerically.

Also applies to: 220-257, 283-323, 391-395

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1dd0a5d and 86fecb7.

📒 Files selected for processing (6)
  • CHANGELOG.md (1 hunks)
  • flixopt/calculation.py (3 hunks)
  • flixopt/config.py (7 hunks)
  • flixopt/network_app.py (2 hunks)
  • flixopt/results.py (2 hunks)
  • tests/test_config.py (0 hunks)
💤 Files with no reviewable changes (1)
  • tests/test_config.py
🧰 Additional context used
🧬 Code graph analysis (2)
flixopt/calculation.py (1)
flixopt/config.py (1)
  • CONFIG (162-719)
flixopt/results.py (1)
flixopt/config.py (1)
  • CONFIG (162-719)
🔇 Additional comments (4)
flixopt/config.py (1)

96-105: ColoredMultilineFormatter box-color changes preserve structure

The updated ColoredMultilineFormatter.format() now applies color codes to the box characters (┌─, , └─) while keeping the timestamp dimmed and the alignment identical (same indent and padding).

The string assembly still mirrors the non-colored formatter’s layout, so this should only affect aesthetics, not readability or parsing.

Also applies to: 108-125

flixopt/results.py (1)

18-19: Consistent use of SUCCESS_LEVEL for results-saving log

Importing SUCCESS_LEVEL here and switching the final message in CalculationResults.to_file() to:

logger.log(SUCCESS_LEVEL, f'Saved calculation results "{name}" to {paths.model_documentation.parent}')

keeps success logging consistent with the new logging API while preserving existing behavior and timing of the message.

Also applies to: 1098-1099

flixopt/network_app.py (1)

21-23: Network visualization start message correctly migrated to SUCCESS_LEVEL

Using the shared SUCCESS_LEVEL constant here:

logger.log(SUCCESS_LEVEL, f'Network visualization started on http://127.0.0.1:{port}/')

keeps the visualization “startup” message aligned with the project’s success-level convention and shares the same tuning knobs as other success logs.

Also applies to: 784-785

flixopt/calculation.py (1)

25-30: Calculation success logs unified on SUCCESS_LEVEL

Importing SUCCESS_LEVEL and switching both:

  • FullCalculation.solve completion log, and
  • SegmentedCalculation.do_modeling_and_solve aggregated completion log

to logger.log(SUCCESS_LEVEL, ...) keeps the wording and timing of the messages but unifies them under the shared success log level defined in config.py. This matches how other modules now emit success messages.

Also applies to: 245-247, 676-677

…to capture expected warnings, preventing them from appearing in the test output.

  What was fixed:

  1. test_both_old_and_new_raises_error (lines 122-174): Wrapped each test case with pytest.warns() to capture the deprecation warnings that occur before the ValueError is raised.
  2. test_optional_parameter_deprecation (lines 289-306): Changed from pytest.warns() to warnings.catch_warnings(record=True) because the optional parameter triggers two separate deprecation warnings (one from interface.py and one from structure.py).
  3. test_both_optional_and_mandatory_no_error (lines 325-349): Same fix as above - using warnings.catch_warnings() to capture both warnings.

  The warnings were showing up because:
  - Some tests used pytest.raises() without capturing the warnings that occurred before the exception
  - The optional parameter uniquely triggers two warnings from different code locations, and pytest.warns() with a match pattern only catches one
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
tests/test_invest_parameters_deprecation.py (2)

292-299: Optional parameter deprecation tests are flexible but comment and assertion are slightly out of sync.

The use of warnings.catch_warnings(record=True) plus any(issubclass(..., DeprecationWarning)) is a good, non‑brittle way to allow multiple deprecation sources while only requiring at least one warning. However, the comment “Two warnings are expected (one from interface.py, one from structure.py)” suggests an exact count that the assertion no longer enforces.

Consider either:

  • Tightening the assertion to check for >= 2 deprecation warnings, or
  • Relaxing the comment wording (e.g. “Currently two warnings are emitted... at least one is required by this test”) to avoid confusion.

Also applies to: 301-307


334-341: Same note about warning count expectations for combined optional/mandatory.

Here as well, the comment says “Two warnings are expected (one from interface.py, one from structure.py)” while the logic only asserts that at least one DeprecationWarning is present. The pattern itself is fine and keeps the test future‑proof; the mismatch is only in expectations vs. assertions.

Mirroring the earlier block, consider either enforcing >= 2 deprecation warnings or softening the comment so it doesn’t imply an exact count.

Also applies to: 343-349

tests/test_config.py (2)

97-108: Be explicit about whether the numeric value 25 is part of the public contract

Both test_success_level_numeric and the assert SUCCESS_LEVEL == 25 in test_success_level_constant hard-code the numeric value. This is fine if you intend “SUCCESS is exactly level 25” to be a stable public API guarantee; otherwise, these tests will make future renumbering noisy.

If you’d rather keep the numeric free to change, consider:

  • Dropping assert SUCCESS_LEVEL == 25, and/or
  • Using SUCCESS_LEVEL instead of literal 25 in test_success_level_numeric.

125-139: Color customization test only asserts message presence; consider (optionally) asserting color config

test_success_color_customization currently just checks that the SUCCESS message appears, which is robust but doesn’t actually verify that set_colors updated anything.

If you want a stronger, still-reasonable check, you could optionally extend this test to introspect the formatter when colorlog is available, e.g. (guarded by a flag/skip):

  • After set_colors(...), find the console handler with a ColoredMultilineFormatter.
  • Assert that formatter.log_colors['SUCCESS'] == 'bold_green,bg_black'.

That would validate the color mapping without relying on terminal escape sequences, while keeping behavior when colorlog is missing unchanged (via a conditional or pytest.skip).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 86fecb7 and 6047f53.

📒 Files selected for processing (2)
  • tests/test_config.py (2 hunks)
  • tests/test_invest_parameters_deprecation.py (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
tests/test_config.py (1)
flixopt/config.py (6)
  • CONFIG (162-719)
  • MultilineFormatter (36-77)
  • Logging (189-483)
  • enable_console (283-357)
  • enable_file (360-411)
  • set_colors (427-483)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: test (3.13)
  • GitHub Check: test (3.11)
  • GitHub Check: test (3.10)
  • GitHub Check: test (3.12)
🔇 Additional comments (4)
tests/test_invest_parameters_deprecation.py (1)

125-132: Good coverage of “old + new” conflict paths (warning + ValueError).

Using pytest.warns(DeprecationWarning, ...) wrapped around pytest.raises(ValueError, ...) nicely asserts that a deprecation warning is emitted in addition to the conflict error for each parameter pair. This is a robust, idiomatic pattern in pytest and matches the intended behavior change.

Also applies to: 135-143, 146-153, 166-174

tests/test_config.py (3)

8-8: SUCCESS_LEVEL import and basic SUCCESS logging usage look correct

Using the exported SUCCESS_LEVEL constant and logger.log(SUCCESS_LEVEL, ...) in test_custom_success_level aligns with the new logging API and ensures the test is tied to the public symbol instead of any monkey-patched method. No issues here.

Also applies to: 75-80


81-96: Good coverage of SUCCESS as an effective minimum log level

test_success_level_as_minimum correctly exercises the threshold behavior: INFO suppressed, SUCCESS logged, WARNING logged. This accurately reflects the logger level semantics with a custom level at 25 and will guard against regressions in the string-to-level mapping for "SUCCESS".


110-123: SUCCESS file logging behavior is well exercised

test_success_file_logging nicely validates that file logging respects the SUCCESS threshold (INFO filtered, SUCCESS persisted) and that the RotatingFileHandler writes what you expect. The structure is clear and should be stable.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
flixopt/config.py (1)

722-738: Optional: mention SUCCESS in deprecated helper docstring

change_logging_level() ultimately calls CONFIG.Logging.enable_console(), which now supports the custom SUCCESS level via the string 'SUCCESS'. The docstring’s Args description still only lists the standard levels; if you keep this helper around until removal, consider updating the text to mention SUCCESS as well for consistency with the rest of the logging docs.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6047f53 and 6dbeef3.

📒 Files selected for processing (2)
  • CHANGELOG.md (1 hunks)
  • flixopt/config.py (8 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: test (3.11)
  • GitHub Check: test (3.10)
  • GitHub Check: test (3.13)
  • GitHub Check: test (3.12)
🔇 Additional comments (7)
CHANGELOG.md (1)

58-66: SUCCESS level and coloring entry matches implementation

The Unreleased notes correctly describe SUCCESS_LEVEL and its usage via logger.log(SUCCESS_LEVEL, ...), and the “logger coloring improved” line aligns with the formatter changes in flixopt/config.py. No changes needed here.

flixopt/config.py (6)

9-24: Typing imports and public SUCCESS_LEVEL export are consistent

Using TYPE_CHECKING with TextIO and from __future__ import annotations keeps runtime imports light while preserving good type information. Adding SUCCESS_LEVEL to __all__ matches how it’s used elsewhere and cleanly exposes the new level as part of the public API.


80-125: Colored multiline formatter spacing change looks correct

The updated ColoredMultilineFormatter.format() keeps the visual structure aligned with MultilineFormatter while adding per-level coloring. The indentation and box borders (┌─, , └─) are consistent between single- and multi-line branches, and there’s no impact on logging semantics.


220-257: SUCCESS level documentation and examples are accurate

The new “Log Levels” subsection and examples correctly describe SUCCESS as level 25 between INFO and WARNING and demonstrate the intended usage via SUCCESS_LEVEL and logger.log(...). The color customization snippet also matches the behavior of set_colors.


283-323: SUCCESS handling in enable_console is robust

Extending enable_console to accept 'SUCCESS' (case/whitespace-insensitive) and map it to SUCCESS_LEVEL, while leaving numeric levels unchanged, cleanly integrates the custom level without altering existing behavior for standard levels.


360-401: enable_file SUCCESS support mirrors console behavior

The same 'SUCCESS'SUCCESS_LEVEL mapping in enable_file, combined with the existing handler reset and formatter setup, ensures file logging supports the custom level in a predictable way and remains symmetric with console configuration.


545-550: Narrowing default_engine to Literal improves type safety

Typing CONFIG.Plotting.default_engine as Literal['plotly', 'matplotlib'] matches the documented options and helps catch invalid assignments at type-check time without changing runtime behavior.

@FBumann FBumann merged commit ea341ad into main Nov 23, 2025
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants