Skip to content

feat: add logging#15

Open
cmeesters wants to merge 7 commits into
mainfrom
feat/add_logging
Open

feat: add logging#15
cmeesters wants to merge 7 commits into
mainfrom
feat/add_logging

Conversation

@cmeesters
Copy link
Copy Markdown
Member

@cmeesters cmeesters commented Mar 22, 2026

This interface needs support to inherit the Snakemake logger interface to report results of a report on the command line (or issue warnings ...)

Context:

The nanopub report plugin is the first plugin in the official repo base to use this interface. Upon publication of a nanopub, the nanopub URI is returned. It should be reported or - in case of an error - the error message. (Eventually, the plugin will support retracting faulty nanopubs, too. But this feature is not stable in the nanopub-py library.)

Changes made in the report interface plugin

  • added a LoggingReportInterface
  • added a JobRecordInterface - and allowing the software report to be imported and used

Observed outcome

  • The tutorial command now completes successfully with the nanopub reporter enabled.
  • In dry-run mode, the reporter again emits the signed nanopub TriG content to the terminal.
  • The abstract-class and constructor-mismatch tracebacks are resolved.

The new plugin will be tested extensively before publication of a release, yet this interface now supports issuing all necessary message.

Summary by CodeRabbit

  • New Features

    • Added logging support for report plugins and made reporters accept a logger.
    • Introduced execution mode options: default, subprocess, remote.
  • Refactor

    • Plugin record interfaces now provide empty default software listings when none are supplied.
  • Tests

    • Added tests ensuring reporters expose the provided logger and isolating the test plugin registry.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 22, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 75e6d740-18d2-42a3-9d41-f346c2efa447

📥 Commits

Reviewing files that changed from the base of the PR and between bb8c983 and 8a28506.

📒 Files selected for processing (1)
  • tests/tests.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/tests.py

📝 Walkthrough

Walkthrough

Provided concrete software properties on two record interfaces, added a LoggingReportInterface, made ReporterBase require and store a logger and declare get_exec_mode(), introduced an ExecMode enum, and added test helpers plus a unit test.

Changes

Cohort / File(s) Summary
Interface adjustments
snakemake_interface_report_plugins/interfaces.py
Made RuleRecordInterface.software and JobRecordInterface.software concrete properties returning an empty List[SoftwareReport] (removed abstract-only stub implementations).
New logging interface
snakemake_interface_report_plugins/logging.py
Added LoggingReportInterface ABC with info, error, debug, and warning abstract methods and exported alias LoggerReportInterface.
Reporter API
snakemake_interface_report_plugins/reporter.py
ReporterBase.__init__ now requires logger: LoggingReportInterface and stores it; added abstract get_exec_mode() -> ExecMode.
Settings / ExecMode
snakemake_interface_report_plugins/settings.py
Added ExecMode enum (extends SettingsEnumBase) with members DEFAULT, SUBPROCESS, and REMOTE.
Tests
tests/tests.py
Restricted test plugin registry to only html; added TestLogger(LoggingReportInterface), ReporterForTest(ReporterBase), and test_reporter_base_exposes_logger unit test.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'feat: add logging' is vague and generic, using non-descriptive terms that don't clearly convey what logging feature is being added or its purpose. Consider a more descriptive title such as 'feat: add LoggingReportInterface for logger injection' to better summarize the main changes in the pull request.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/add_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.

Copy link
Copy Markdown

@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.

Caution

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

⚠️ Outside diff range comments (2)
tests/tests.py (1)

1-83: ⚠️ Potential issue | 🟠 Major

CI blocker: Black check is failing for this test file.

black --check already reports this file as non-compliant; please run Black to unblock CI.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/tests.py` around lines 1 - 83, The test file containing TestRegistry,
TestLogger, ReporterForTest, and the test_reporter_base_exposes_logger function
is not Black-formatted; run Black (or apply Black formatting) on that test file
to fix import spacing/linewrapping and any style issues, then commit the
reformatted file so black --check passes in CI.
snakemake_interface_report_plugins/reporter.py (1)

23-33: ⚠️ Potential issue | 🟠 Major

Potentially breaking public interface change for third-party reporters.

The required logger parameter in __init__ (Line 29) and new abstract method get_exec_mode() (Lines 56-57) will break existing ReporterBase subclasses in external plugins that haven't been updated. Ensure release notes explicitly document this breaking change and provide migration guidance for downstream plugin maintainers.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@snakemake_interface_report_plugins/reporter.py` around lines 23 - 33, The
change adds a required logger parameter to ReporterBase.__init__ and a new
abstract method get_exec_mode(), which will break third-party ReporterBase
subclasses; to make this backward-compatible, make the logger parameter optional
(e.g., default to None) in __init__ and adapt any internal use to handle a
missing logger, and convert get_exec_mode() from an abstract method to a
concrete method on ReporterBase that returns a sensible default exec mode (or
provide a protected compatibility shim like _get_exec_mode() that calls
get_exec_mode() if overridden), while documenting the breaking change and
migration steps in the release notes for downstream plugin maintainers.
🧹 Nitpick comments (1)
tests/tests.py (1)

70-81: Use a minimal DAG stub instead of None for stronger contract coverage.

Passing dag=None on Line 80 bypasses the DAGReportInterface contract in this constructor test. A tiny stub object would make the test more robust against future ReporterBase changes.

Suggested test hardening
+class DummyDag:
+    def toposorted(self):
+        return []
+
+    `@property`
+    def dependencies(self):
+        return {}
+
 def test_reporter_base_exposes_logger():
     logger = TestLogger()
     reporter = ReporterForTest(
         rules={},
         results={},
         logger=logger,
         configfiles=[],
         jobs=[],
         settings=ReportSettingsBase(),
         workflow_description="",
-        dag=None,
+        dag=DummyDag(),
     )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/tests.py` around lines 70 - 81, Replace the sentinel None passed as dag
in test_reporter_base_exposes_logger with a minimal DAG stub that implements the
DAGReportInterface used by ReporterForTest so the constructor contract is
exercised; update the test to instantiate a tiny object (e.g., class or simple
dataclass) that provides the minimal attributes/methods the ReporterBase expects
and pass that instance to ReporterForTest instead of None to strengthen contract
coverage.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@snakemake_interface_report_plugins/reporter.py`:
- Around line 23-33: The change adds a required logger parameter to
ReporterBase.__init__ and a new abstract method get_exec_mode(), which will
break third-party ReporterBase subclasses; to make this backward-compatible,
make the logger parameter optional (e.g., default to None) in __init__ and adapt
any internal use to handle a missing logger, and convert get_exec_mode() from an
abstract method to a concrete method on ReporterBase that returns a sensible
default exec mode (or provide a protected compatibility shim like
_get_exec_mode() that calls get_exec_mode() if overridden), while documenting
the breaking change and migration steps in the release notes for downstream
plugin maintainers.

In `@tests/tests.py`:
- Around line 1-83: The test file containing TestRegistry, TestLogger,
ReporterForTest, and the test_reporter_base_exposes_logger function is not
Black-formatted; run Black (or apply Black formatting) on that test file to fix
import spacing/linewrapping and any style issues, then commit the reformatted
file so black --check passes in CI.

---

Nitpick comments:
In `@tests/tests.py`:
- Around line 70-81: Replace the sentinel None passed as dag in
test_reporter_base_exposes_logger with a minimal DAG stub that implements the
DAGReportInterface used by ReporterForTest so the constructor contract is
exercised; update the test to instantiate a tiny object (e.g., class or simple
dataclass) that provides the minimal attributes/methods the ReporterBase expects
and pass that instance to ReporterForTest instead of None to strengthen contract
coverage.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6d282bad-bd1b-498d-8828-88c34d5bfe63

📥 Commits

Reviewing files that changed from the base of the PR and between 12ce5cb and 2e46eb0.

📒 Files selected for processing (5)
  • snakemake_interface_report_plugins/interfaces.py
  • snakemake_interface_report_plugins/logging.py
  • snakemake_interface_report_plugins/reporter.py
  • snakemake_interface_report_plugins/settings.py
  • tests/tests.py


@abstractmethod
def render(self): ...
def get_exec_mode(self) -> ExecMode:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This I don't understand. How should the reporter implement that?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I thought it to be a formal requirement / necessity as the executor base classes in the interface module define this as well. So, this line stems from my template the executor interface plugin.

from abc import ABC, abstractmethod


class LoggingReportInterface(ABC):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this really needed, I think the logger is just a standard python logger nowadays, isn't it?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

no idea - honestly, I copied from the executor interface, and it defines the logger in the ReporterBase class. (Ok, the executor interface speaks of LoggerExecutorInterace in place of Logging...).

So, how can this functionality be inherited if not by defining this explicitly?

Comment on lines +107 to 109
def software(self) -> List[SoftwareReport]:
return []

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why this change?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

well spotted. I introduced this, experimentally, but don't need it anymore.

Comment thread snakemake_interface_report_plugins/interfaces.py
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