Skip to content

feat: provide mechanism to link between report items (snakemake.report_href, see docs)#3224

Merged
johanneskoester merged 6 commits intomainfrom
feat/report_href
Feb 18, 2025
Merged

feat: provide mechanism to link between report items (snakemake.report_href, see docs)#3224
johanneskoester merged 6 commits intomainfrom
feat/report_href

Conversation

@johanneskoester
Copy link
Copy Markdown
Contributor

@johanneskoester johanneskoester commented Dec 6, 2024

QC

  • The PR contains a test case for the changes or the changes are already covered by an existing test case.
  • The documentation (docs/) is updated to reflect the changes or this is not necessary (e.g. if the change does neither modify the language nor the behavior or functionalities of Snakemake).

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced reporting capabilities with new directives and methods for generating comprehensive HTML reports.
    • Introduced dynamic linking in reports and the ability to include file labels and categories.
    • Added new HTML report generation functionality with example workflows.
    • New functionality to manage report hyperlinks, improving navigation within reports.
  • Bug Fixes

    • Improved error handling and user feedback during report generation.
  • Tests

    • Added new tests for report generation functionality to ensure reliability.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Dec 6, 2024

📝 Walkthrough
📝 Walkthrough

Walkthrough

The pull request introduces significant enhancements to the Snakemake reporting framework. Key modifications include the addition of new methods and directives for generating reports, improved handling of file paths, and the introduction of dynamic linking capabilities. Documentation has been updated to reflect these changes, including examples and usage instructions. New HTML files and a test case have been added to validate the functionality of the report generation features, ensuring comprehensive coverage of the new capabilities.

Changes

File Change Summary
docs/snakefiles/reporting.rst Structural and content modifications; added new directives and methods for report generation; clarified report rendering process.
snakemake/common/init.py Added get_report_id method to generate SHA256 hash for paths.
snakemake/report/init.py Updated FileRecord class to include parent_path; modified methods for file registration and handling.
snakemake/report/html_reporter/template/components/app.js Added renderTrigger state property to App class for dynamic re-rendering.
snakemake/report/html_reporter/template/components/content.js Updated ContentDisplay class to ensure iframe re-renders based on renderTrigger.
snakemake/script/init.py Introduced ReportHref class for managing report hyperlinks; added report_href method in Snakemake.
tests/test_report_href/Snakefile Added new rule a for generating reports with specified inputs and outputs.
tests/test_report_href/expected-results/test2.html Created new HTML file with hyperlinks for testing report generation.
tests/test_report_href/subdir/subdir/test3.html Created new HTML file with basic structure.
tests/test_report_href/test.html Created new HTML file with basic structure and script for URL parameter handling.
tests/test_report_href/test_script.py Implemented a script to generate an HTML report with links using snakemake.report_href.
tests/tests.py Added new test function test_report_href() to validate report generation functionality.

Possibly related PRs

Suggested reviewers

  • tedil

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@johanneskoester johanneskoester changed the title Feat/report_href feat: provide mechanism to link between report items (snakemake.report_href, see docs) Dec 6, 2024
Copy link
Copy Markdown
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: 4

🧹 Outside diff range and nitpick comments (4)
tests/test_report_href/test_script.py (1)

3-3: Suppress static analysis warnings for snakemake being undefined

Static analysis tools may flag snakemake as undefined because it's injected by Snakemake at runtime. To improve code clarity and suppress these warnings, consider adding a type hint for snakemake.

Add the following at the top of your script:

from snakemake.script import Snakemake

snakemake: Snakemake
🧰 Tools
🪛 Ruff (0.8.0)

3-3: Undefined name snakemake

(F821)

snakemake/report/html_reporter/template/components/content.js (1)

68-68: Ensure consistent re-rendering without unnecessary unmounting

Using renderTrigger as a key for the iframe works with the updated incremental counter, but it's generally better to control re-renders through state or props changes. If the content changes are based on contentPath, consider using it directly as the key.

Modify the iframe element to use contentPath as the key:

 return e(
     "iframe",
-    { src: this.props.app.state.contentPath, className: "w-full h-screen", key: `${this.props.app.state.renderTrigger}` }
+    { src: this.props.app.state.contentPath, className: "w-full h-screen", key: this.props.app.state.contentPath }
 );
tests/tests.py (2)

258-260: Add docstring to explain test purpose.

Consider adding a docstring to explain what aspect of the report href functionality is being tested. This helps other developers understand the test's purpose and requirements.

 def test_report_href():
+    """Test the functionality of generating reports with hyperlinks using snakemake.report_href()."""
     run(dpath("test_report_href"))

260-261: Remove extra empty line.

There are two consecutive empty lines where one would be sufficient according to PEP 8.

 def test_report_href():
     run(dpath("test_report_href"))
-

 def test_report_zip():
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 45cb082 and 5180134.

📒 Files selected for processing (12)
  • docs/snakefiles/reporting.rst (4 hunks)
  • snakemake/common/__init__.py (2 hunks)
  • snakemake/report/__init__.py (7 hunks)
  • snakemake/report/html_reporter/template/components/app.js (2 hunks)
  • snakemake/report/html_reporter/template/components/content.js (1 hunks)
  • snakemake/script/__init__.py (4 hunks)
  • tests/test_report_href/Snakefile (1 hunks)
  • tests/test_report_href/expected-results/test2.html (1 hunks)
  • tests/test_report_href/subdir/subdir/test3.html (1 hunks)
  • tests/test_report_href/test.html (1 hunks)
  • tests/test_report_href/test_script.py (1 hunks)
  • tests/tests.py (1 hunks)
✅ Files skipped from review due to trivial changes (3)
  • tests/test_report_href/subdir/subdir/test3.html
  • tests/test_report_href/expected-results/test2.html
  • tests/test_report_href/test.html
🧰 Additional context used
📓 Path-based instructions (5)
tests/test_report_href/test_script.py (1)

Pattern **/*.py: Do not try to improve formatting.
Do not suggest type annotations for functions that are defined inside of functions or methods.
Do not suggest type annotation of the self argument of methods.
Do not suggest type annotation of the cls argument of classmethods.
Do not suggest return type annotation if a function or method does not contain a return statement.

tests/tests.py (1)

Pattern **/*.py: Do not try to improve formatting.
Do not suggest type annotations for functions that are defined inside of functions or methods.
Do not suggest type annotation of the self argument of methods.
Do not suggest type annotation of the cls argument of classmethods.
Do not suggest return type annotation if a function or method does not contain a return statement.

snakemake/common/__init__.py (1)

Pattern **/*.py: Do not try to improve formatting.
Do not suggest type annotations for functions that are defined inside of functions or methods.
Do not suggest type annotation of the self argument of methods.
Do not suggest type annotation of the cls argument of classmethods.
Do not suggest return type annotation if a function or method does not contain a return statement.

snakemake/script/__init__.py (1)

Pattern **/*.py: Do not try to improve formatting.
Do not suggest type annotations for functions that are defined inside of functions or methods.
Do not suggest type annotation of the self argument of methods.
Do not suggest type annotation of the cls argument of classmethods.
Do not suggest return type annotation if a function or method does not contain a return statement.

snakemake/report/__init__.py (1)

Pattern **/*.py: Do not try to improve formatting.
Do not suggest type annotations for functions that are defined inside of functions or methods.
Do not suggest type annotation of the self argument of methods.
Do not suggest type annotation of the cls argument of classmethods.
Do not suggest return type annotation if a function or method does not contain a return statement.

🪛 Ruff (0.8.0)
tests/test_report_href/test_script.py

3-3: Undefined name snakemake

(F821)


11-11: Undefined name snakemake

(F821)


12-12: Undefined name snakemake

(F821)

snakemake/script/__init__.py

90-93: Use ternary operator anchor = f"#{urllib.parse.quote(self._anchor)}" if self._anchor else "" instead of if-else-block

Replace if-else-block with anchor = f"#{urllib.parse.quote(self._anchor)}" if self._anchor else ""

(SIM108)

🔇 Additional comments (8)
tests/test_report_href/Snakefile (1)

1-13: Rule a is correctly defined

The rule a is properly configured with inputs, outputs, and script. The use of report functions and the pattern matching in inputs are appropriate.

snakemake/report/__init__.py (3)

Line range hint 360-443: LGTM: FileRecord class changes look good.

The addition of parent_path and the modified filename property correctly handle relative paths for files within directories.


Line range hint 545-565: LGTM: register_file function signature update.

The addition of the parent_path parameter and its handling in the FileRecord creation is implemented correctly.

🧰 Tools
🪛 Ruff (0.8.0)

551-551: Function definition does not bind loop variable job

(B023)


613-632: Improved error handling for pattern matching.

Good addition of the found_something flag to warn users when no files match the given patterns.

docs/snakefiles/reporting.rst (2)

Line range hint 134-194: Well-documented linking functionality.

The documentation clearly explains the new linking capabilities and provides good examples.


196-238: Comprehensive examples for advanced linking features.

Good coverage of child_path, url_args, and anchor functionality with clear examples.

snakemake/common/__init__.py (2)

20-20: LGTM!

Clean addition of the Union type import, required for type hinting in the new get_report_id function.


56-60: LGTM! Clean and focused implementation.

The function:

  • Properly handles both string and Path objects
  • Uses a cryptographically secure hash function (SHA256)
  • Has appropriate type hints
  • Follows the single responsibility principle

Let's verify the usage of this function in the reporting framework:

✅ Verification successful

Function is properly integrated into the reporting framework

The verification shows that get_report_id is correctly used in the reporting framework:

  • Imported and used in snakemake/report/__init__.py to generate unique IDs for reports
  • Also integrated in snakemake/script/__init__.py for script identification
  • Both usages align with the function's purpose of generating unique identifiers from paths
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of get_report_id in the reporting framework
# Expected: Function should be used in report-related files for generating IDs

# Search for imports of get_report_id
rg "from snakemake.common import .*get_report_id" -A 2

# Search for direct usage of get_report_id
rg "get_report_id\(" -A 2

Length of output: 1086

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Dec 6, 2024

Copy link
Copy Markdown
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

🧹 Outside diff range and nitpick comments (1)
snakemake/script/__init__.py (1)

52-71: Consider adding input validation.

The initialization looks good, but consider adding validation for:

  • path to ensure it's a valid report path
  • url_args to ensure values are strings or can be converted to strings
 def __init__(
     self,
     path: Union[str, Path],
     parent: Optional[ReportHrefType] = None,
     url_args: Optional[Dict[str, str]] = None,
     anchor: Optional[str] = None,
 ):
+    if not isinstance(path, (str, Path)):
+        raise TypeError(f"path must be str or Path, got {type(path)}")
     self._parent = parent
     if parent is None:
         self._id = get_report_id(path)
     else:
         self._id = parent._id
     # ensure that path is a url compatible string
     self._path = path if isinstance(path, str) else str(path.as_posix())
     self._url_args = (
-        {key: value for key, value in url_args.items()} if url_args else {}
+        {key: str(value) for key, value in url_args.items()} if url_args else {}
     )
     self._anchor = anchor
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 5180134 and 19f28b8.

📒 Files selected for processing (1)
  • snakemake/script/__init__.py (4 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
snakemake/script/__init__.py (1)

Pattern **/*.py: Do not try to improve formatting.
Do not suggest type annotations for functions that are defined inside of functions or methods.
Do not suggest type annotation of the self argument of methods.
Do not suggest type annotation of the cls argument of classmethods.
Do not suggest return type annotation if a function or method does not contain a return statement.

🪛 Ruff (0.8.0)
snakemake/script/__init__.py

93-96: Use ternary operator anchor = f"#{urllib.parse.quote(self._anchor)}" if self._anchor else "" instead of if-else-block

Replace if-else-block with anchor = f"#{urllib.parse.quote(self._anchor)}" if self._anchor else ""

(SIM108)

🔇 Additional comments (5)
snakemake/script/__init__.py (5)

19-22: LGTM: Import changes are appropriate.

The added imports are necessary for the new functionality and follow Python's import style guide.


48-49: LGTM: Good compatibility solution.

The use of TypeVar for Python <3.11 compatibility is a good solution, addressing the previous review comment about Self type usage.


72-81: LGTM: Helper methods are well-designed.

The methods for creating child paths and modifying URL arguments/anchors are well-designed and maintain immutability by returning new instances.


129-137: LGTM: Well-documented method.

The report_href method is well-documented and follows the single responsibility principle. The docstring clearly explains its purpose and usage.


83-97: ⚠️ Potential issue

Avoid double URL encoding.

The values in self._url_args are already URL-encoded during initialization. Applying urllib.parse.quote again in the fmt_arg function results in double encoding.

Apply this diff to fix the issue:

 def fmt_arg(key, value):
-    return f"{key}={urllib.parse.quote(str(value))}"
+    return f"{key}={str(value)}"

Also, the same issue exists with anchor encoding:

 if self._anchor:
-    anchor = f"#{urllib.parse.quote(self._anchor)}"
+    anchor = f"#{self._anchor}"
 else:
     anchor = ""
🧰 Tools
🪛 Ruff (0.8.0)

93-96: Use ternary operator anchor = f"#{urllib.parse.quote(self._anchor)}" if self._anchor else "" instead of if-else-block

Replace if-else-block with anchor = f"#{urllib.parse.quote(self._anchor)}" if self._anchor else ""

(SIM108)

@johanneskoester johanneskoester merged commit a024e60 into main Feb 18, 2025
@johanneskoester johanneskoester deleted the feat/report_href branch February 18, 2025 15:29
johanneskoester pushed a commit that referenced this pull request Feb 27, 2025
🤖 I have created a release *beep* *boop*
---


##
[8.29.0](v8.28.0...v8.29.0)
(2025-02-27)


### Features

* provide mechanism to link between report items (snakemake.report_href,
see docs) ([#3224](#3224))
([a024e60](a024e60))
* toggles for binary labels in report
([#3296](#3296))
([7690998](7690998))


### Bug Fixes

* add missing [@conda](https://github.com/conda) annotations
([#3298](#3298))
([0b541cc](0b541cc))
* properly handle remote storage when waiting for pipes
([#3317](#3317))
([9f7e092](9f7e092))
* provide proper error messages if output file preparation (pipe, mkdir)
fails ([#3309](#3309))
([77ef176](77ef176))
* record file extension (e.g. .tsv) in between workflow cache records in
order to avoid that files of the wrong format are erroneously returned
by the cache. This will lead to some cache misses. But avoiding errors
induced by the previous behavior of ignoring file extensions when
seeking for cache records is more important.
([#3314](#3314))
([4912f00](4912f00))
* sort results lexicographically by labels in their order of appearance
([#3293](#3293))
([a19a0ac](a19a0ac))


### Documentation

* update best practices
([7270eb3](7270eb3))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
kjohnsen pushed a commit to kjohnsen/snakemake that referenced this pull request Dec 15, 2025
…t_href, see docs) (snakemake#3224)

<!--Add a description of your PR here-->

### QC
<!-- Make sure that you can tick the boxes below. -->

* [x] The PR contains a test case for the changes or the changes are
already covered by an existing test case.
* [x] The documentation (`docs/`) is updated to reflect the changes or
this is not necessary (e.g. if the change does neither modify the
language nor the behavior or functionalities of Snakemake).


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Release Notes

- **New Features**
- Enhanced reporting capabilities with new directives and methods for
generating comprehensive HTML reports.
- Introduced dynamic linking in reports and the ability to include file
labels and categories.
- Added new HTML report generation functionality with example workflows.
- New functionality to manage report hyperlinks, improving navigation
within reports.

- **Bug Fixes**
	- Improved error handling and user feedback during report generation.

- **Tests**
- Added new tests for report generation functionality to ensure
reliability.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
kjohnsen pushed a commit to kjohnsen/snakemake that referenced this pull request Dec 15, 2025
🤖 I have created a release *beep* *boop*
---


##
[8.29.0](snakemake/snakemake@v8.28.0...v8.29.0)
(2025-02-27)


### Features

* provide mechanism to link between report items (snakemake.report_href,
see docs) ([snakemake#3224](snakemake#3224))
([a024e60](snakemake@a024e60))
* toggles for binary labels in report
([snakemake#3296](snakemake#3296))
([7690998](snakemake@7690998))


### Bug Fixes

* add missing [@conda](https://github.com/conda) annotations
([snakemake#3298](snakemake#3298))
([0b541cc](snakemake@0b541cc))
* properly handle remote storage when waiting for pipes
([snakemake#3317](snakemake#3317))
([9f7e092](snakemake@9f7e092))
* provide proper error messages if output file preparation (pipe, mkdir)
fails ([snakemake#3309](snakemake#3309))
([77ef176](snakemake@77ef176))
* record file extension (e.g. .tsv) in between workflow cache records in
order to avoid that files of the wrong format are erroneously returned
by the cache. This will lead to some cache misses. But avoiding errors
induced by the previous behavior of ignoring file extensions when
seeking for cache records is more important.
([snakemake#3314](snakemake#3314))
([4912f00](snakemake@4912f00))
* sort results lexicographically by labels in their order of appearance
([snakemake#3293](snakemake#3293))
([a19a0ac](snakemake@a19a0ac))


### Documentation

* update best practices
([7270eb3](snakemake@7270eb3))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
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.

1 participant