From 31e538c3a13b2b3c3d88d3fded8442a71d7fb585 Mon Sep 17 00:00:00 2001 From: Luis Kress Date: Sun, 16 Mar 2025 22:13:07 +0100 Subject: [PATCH 1/7] Add the metadata interface to the reporter class --- snakemake_interface_report_plugins/interfaces.py | 7 +++++++ snakemake_interface_report_plugins/reporter.py | 3 +++ 2 files changed, 10 insertions(+) diff --git a/snakemake_interface_report_plugins/interfaces.py b/snakemake_interface_report_plugins/interfaces.py index 6bd309e..524a9b6 100644 --- a/snakemake_interface_report_plugins/interfaces.py +++ b/snakemake_interface_report_plugins/interfaces.py @@ -25,6 +25,13 @@ def is_other(self) -> bool: ... def id(self) -> str: ... +class MetadataRecordInterface(ABC): + + @property + @abstractmethod + def parse_yte(self) -> dict: ... + + class RuleRecordInterface(ABC): @property @abstractmethod diff --git a/snakemake_interface_report_plugins/reporter.py b/snakemake_interface_report_plugins/reporter.py index a7282be..fe78c94 100644 --- a/snakemake_interface_report_plugins/reporter.py +++ b/snakemake_interface_report_plugins/reporter.py @@ -11,6 +11,7 @@ ConfigFileRecordInterface, JobRecordInterface, RuleRecordInterface, + MetadataRecordInterface, ) from snakemake_interface_report_plugins.settings import ReportSettingsBase from snakemake_interface_report_plugins.interfaces import DAGReportInterface @@ -27,6 +28,7 @@ def __init__( jobs: List[JobRecordInterface], settings: ReportSettingsBase, workflow_description: str, + metadata: MetadataRecordInterface, dag: DAGReportInterface, ): self.rules = rules @@ -35,6 +37,7 @@ def __init__( self.configfiles = configfiles self.settings = settings self.workflow_description = workflow_description + self.metadata = metadata self.dag = dag self.__post_init__() From cb009713676b2408a363d76a3a27eb55cf4bb2e2 Mon Sep 17 00:00:00 2001 From: Luis Kress Date: Fri, 25 Apr 2025 20:42:12 +0200 Subject: [PATCH 2/7] Remove MetadataRecordInterface --- snakemake_interface_report_plugins/interfaces.py | 7 ------- snakemake_interface_report_plugins/reporter.py | 7 ++++--- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/snakemake_interface_report_plugins/interfaces.py b/snakemake_interface_report_plugins/interfaces.py index 524a9b6..6bd309e 100644 --- a/snakemake_interface_report_plugins/interfaces.py +++ b/snakemake_interface_report_plugins/interfaces.py @@ -25,13 +25,6 @@ def is_other(self) -> bool: ... def id(self) -> str: ... -class MetadataRecordInterface(ABC): - - @property - @abstractmethod - def parse_yte(self) -> dict: ... - - class RuleRecordInterface(ABC): @property @abstractmethod diff --git a/snakemake_interface_report_plugins/reporter.py b/snakemake_interface_report_plugins/reporter.py index fe78c94..3f14a4a 100644 --- a/snakemake_interface_report_plugins/reporter.py +++ b/snakemake_interface_report_plugins/reporter.py @@ -11,7 +11,6 @@ ConfigFileRecordInterface, JobRecordInterface, RuleRecordInterface, - MetadataRecordInterface, ) from snakemake_interface_report_plugins.settings import ReportSettingsBase from snakemake_interface_report_plugins.interfaces import DAGReportInterface @@ -28,8 +27,8 @@ def __init__( jobs: List[JobRecordInterface], settings: ReportSettingsBase, workflow_description: str, - metadata: MetadataRecordInterface, dag: DAGReportInterface, + metadata: dict = None, ): self.rules = rules self.jobs = jobs @@ -37,8 +36,10 @@ def __init__( self.configfiles = configfiles self.settings = settings self.workflow_description = workflow_description - self.metadata = metadata self.dag = dag + self.metadata = {} + if metadata: + self.metadata = metadata self.__post_init__() From 592243d4070c612b97632fe4d56bf86fd25f6425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20K=C3=B6ster?= Date: Mon, 28 Apr 2025 10:22:14 +0200 Subject: [PATCH 3/7] Update reporter.py --- snakemake_interface_report_plugins/reporter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/snakemake_interface_report_plugins/reporter.py b/snakemake_interface_report_plugins/reporter.py index 3f14a4a..dd3b455 100644 --- a/snakemake_interface_report_plugins/reporter.py +++ b/snakemake_interface_report_plugins/reporter.py @@ -5,7 +5,7 @@ from abc import ABC, abstractmethod -from typing import List, Mapping +from typing import List, Mapping, Dict, Any from snakemake_interface_report_plugins.interfaces import ( CategoryInterface, ConfigFileRecordInterface, @@ -28,7 +28,7 @@ def __init__( settings: ReportSettingsBase, workflow_description: str, dag: DAGReportInterface, - metadata: dict = None, + metadata: Dict[Any, Any] = None, ): self.rules = rules self.jobs = jobs From 0370982709726ed4ff4fbcb6bd99f709a9587210 Mon Sep 17 00:00:00 2001 From: Luis Kress Date: Fri, 11 Jul 2025 20:25:08 +0200 Subject: [PATCH 4/7] refactor: Check that report metadate is a single level dict --- .../reporter.py | 39 ++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/snakemake_interface_report_plugins/reporter.py b/snakemake_interface_report_plugins/reporter.py index dd3b455..deb8117 100644 --- a/snakemake_interface_report_plugins/reporter.py +++ b/snakemake_interface_report_plugins/reporter.py @@ -5,7 +5,7 @@ from abc import ABC, abstractmethod -from typing import List, Mapping, Dict, Any +from typing import List, Mapping, Dict, Optional, Union from snakemake_interface_report_plugins.interfaces import ( CategoryInterface, ConfigFileRecordInterface, @@ -28,7 +28,9 @@ def __init__( settings: ReportSettingsBase, workflow_description: str, dag: DAGReportInterface, - metadata: Dict[Any, Any] = None, + metadata: Optional[ + Dict[str, Union[str, int, float, List[str], List[int], List[float]]] + ] = {}, ): self.rules = rules self.jobs = jobs @@ -37,9 +39,14 @@ def __init__( self.settings = settings self.workflow_description = workflow_description self.dag = dag - self.metadata = {} - if metadata: - self.metadata = metadata + + # ensure that metadata is a key value dictionary + if not validate_flat_dict(metadata): + raise TypeError( + "Metadata must be single level dict[str, str | int | float | list[str] | list[int] | list[float]]]" + ) + + self.metadata = metadata self.__post_init__() @@ -48,3 +55,25 @@ def __post_init__(self): @abstractmethod def render(self): ... + + +def is_valid_flat_value(value) -> bool: + if isinstance(value, (str, int, float)): + return True + elif isinstance(value, list): + return all(isinstance(item, (str, int, float)) for item in value) + else: + return False + + +def validate_flat_dict(metadata: dict) -> bool: + if not isinstance(metadata, dict): + return False + + for k, v in metadata.items(): + if not isinstance(k, str): + return False + if not is_valid_flat_value(v): + return False + + return True From e487225c7b6c41dc87a103f14097e548a7c714ba Mon Sep 17 00:00:00 2001 From: Luis Kress Date: Fri, 11 Jul 2025 20:32:23 +0200 Subject: [PATCH 5/7] Format with black --- snakemake_interface_report_plugins/reporter.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/snakemake_interface_report_plugins/reporter.py b/snakemake_interface_report_plugins/reporter.py index deb8117..0c6eead 100644 --- a/snakemake_interface_report_plugins/reporter.py +++ b/snakemake_interface_report_plugins/reporter.py @@ -43,7 +43,10 @@ def __init__( # ensure that metadata is a key value dictionary if not validate_flat_dict(metadata): raise TypeError( - "Metadata must be single level dict[str, str | int | float | list[str] | list[int] | list[float]]]" + ( + "Metadata must be single level " + "dict[str, str | int | float | list[str] | list[int] | list[float]]]" + ) ) self.metadata = metadata From 214535a06c06799c3aa70799d5867b9cb7b2e8ef Mon Sep 17 00:00:00 2001 From: Luis Kress Date: Fri, 11 Jul 2025 20:35:28 +0200 Subject: [PATCH 6/7] Break too long line in reporter.py --- snakemake_interface_report_plugins/reporter.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/snakemake_interface_report_plugins/reporter.py b/snakemake_interface_report_plugins/reporter.py index 0c6eead..9280755 100644 --- a/snakemake_interface_report_plugins/reporter.py +++ b/snakemake_interface_report_plugins/reporter.py @@ -45,7 +45,8 @@ def __init__( raise TypeError( ( "Metadata must be single level " - "dict[str, str | int | float | list[str] | list[int] | list[float]]]" + "dict[str, str | int | float | " + "list[str] | list[int] | list[float]]]" ) ) From 09e170aa95c5ab3b9b34dee74ab242bf411d1885 Mon Sep 17 00:00:00 2001 From: Luis Kress Date: Wed, 23 Jul 2025 21:22:05 +0200 Subject: [PATCH 7/7] Remove metadata dictionary validation --- .../reporter.py | 35 +------------------ 1 file changed, 1 insertion(+), 34 deletions(-) diff --git a/snakemake_interface_report_plugins/reporter.py b/snakemake_interface_report_plugins/reporter.py index 9280755..14103bd 100644 --- a/snakemake_interface_report_plugins/reporter.py +++ b/snakemake_interface_report_plugins/reporter.py @@ -30,7 +30,7 @@ def __init__( dag: DAGReportInterface, metadata: Optional[ Dict[str, Union[str, int, float, List[str], List[int], List[float]]] - ] = {}, + ] = None, ): self.rules = rules self.jobs = jobs @@ -39,17 +39,6 @@ def __init__( self.settings = settings self.workflow_description = workflow_description self.dag = dag - - # ensure that metadata is a key value dictionary - if not validate_flat_dict(metadata): - raise TypeError( - ( - "Metadata must be single level " - "dict[str, str | int | float | " - "list[str] | list[int] | list[float]]]" - ) - ) - self.metadata = metadata self.__post_init__() @@ -59,25 +48,3 @@ def __post_init__(self): @abstractmethod def render(self): ... - - -def is_valid_flat_value(value) -> bool: - if isinstance(value, (str, int, float)): - return True - elif isinstance(value, list): - return all(isinstance(item, (str, int, float)) for item in value) - else: - return False - - -def validate_flat_dict(metadata: dict) -> bool: - if not isinstance(metadata, dict): - return False - - for k, v in metadata.items(): - if not isinstance(k, str): - return False - if not is_valid_flat_value(v): - return False - - return True