diff --git a/cwltool/cwlviewer.py b/cwltool/cwlviewer.py index 36166c485..92e494dde 100644 --- a/cwltool/cwlviewer.py +++ b/cwltool/cwlviewer.py @@ -99,8 +99,8 @@ def _set_inner_edges(self) -> None: self._dot_graph.add_node(n) self._dot_graph.add_edge( pydot.Edge( - str(inner_edge_row["source_step"]), - str(inner_edge_row["target_step"]), + pydot.quote_id_if_necessary(str(inner_edge_row["source_step"])), + pydot.quote_id_if_necessary(str(inner_edge_row["target_step"])), ) ) @@ -109,7 +109,6 @@ def _set_input_edges(self) -> None: inputs_subgraph = pydot.Subgraph(graph_name="cluster_inputs") self._dot_graph.add_subgraph(inputs_subgraph) inputs_subgraph.set("rank", "same") - inputs_subgraph.create_attribute_methods(["style"]) inputs_subgraph.set("style", "dashed") inputs_subgraph.set("label", "Workflow Inputs") @@ -129,14 +128,18 @@ def _set_input_edges(self) -> None: ) n.set_name(str(input_row["input"])) inputs_subgraph.add_node(n) - self._dot_graph.add_edge(pydot.Edge(str(input_row["input"]), str(input_row["step"]))) + self._dot_graph.add_edge( + pydot.Edge( + pydot.quote_id_if_necessary(str(input_row["input"])), + pydot.quote_id_if_necessary(str(input_row["step"])), + ) + ) def _set_output_edges(self) -> None: get_output_edges = _get_output_edges_query() outputs_graph = pydot.Subgraph(graph_name="cluster_outputs") self._dot_graph.add_subgraph(outputs_graph) outputs_graph.set("rank", "same") - outputs_graph.create_attribute_methods(["style"]) outputs_graph.set("style", "dashed") outputs_graph.set("label", "Workflow Outputs") outputs_graph.set("labelloc", "b") @@ -156,7 +159,12 @@ def _set_output_edges(self) -> None: ) n.set_name(str(output_edge_row["output"])) outputs_graph.add_node(n) - self._dot_graph.add_edge(pydot.Edge(output_edge_row["step"], output_edge_row["output"])) + self._dot_graph.add_edge( + pydot.Edge( + pydot.quote_id_if_necessary(output_edge_row["step"]), + pydot.quote_id_if_necessary(output_edge_row["output"]), + ) + ) def _get_root_graph_uri(self) -> rdflib.term.Identifier: get_root_query = _get_root_query() diff --git a/mypy-stubs/pydot.pyi b/mypy-stubs/pydot.pyi index bd0ab3147..ecf3a453b 100644 --- a/mypy-stubs/pydot.pyi +++ b/mypy-stubs/pydot.pyi @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Sequence, Union +from typing import Any, Dict, List, Optional, Sequence, Union PY3: Any str_type = str @@ -12,6 +12,7 @@ def is_windows() -> bool: ... def is_anaconda() -> bool: ... def get_executable_extension() -> str: ... def graph_from_dot_data(s: str) -> List["Dot"]: ... +def quote_id_if_necessary(s: str, unquoted_keywords: Optional[Sequence[str]] = None) -> str: ... class Common: def set_parent_graph(self, parent_graph: "Graph") -> None: ... @@ -21,7 +22,6 @@ class Common: def get_attributes(self) -> Dict[str, str]: ... def set_sequence(self, seq: str) -> None: ... def get_sequence(self) -> str: ... - def create_attribute_methods(self, obj_attributes: List[str]) -> None: ... class Error(Exception): value: Any diff --git a/requirements.txt b/requirements.txt index 621aa968a..8c36ccddb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,7 +7,7 @@ mypy-extensions psutil>=5.6.6 importlib_resources>=1.4;python_version<'3.9' coloredlogs -pydot>=1.4.1,<3 +pydot>=1.4.1 argcomplete>=1.12.0 pyparsing!=3.0.2 # breaks --print-dot (pydot) https://github.com/pyparsing/pyparsing/issues/319 cwl-utils>=0.32 diff --git a/setup.py b/setup.py index 960b26cc5..02a648095 100644 --- a/setup.py +++ b/setup.py @@ -156,7 +156,7 @@ def _find_package_data(base: str, globs: list[str], root: str = "cwltool") -> li "mypy-extensions", "psutil >= 5.6.6", "coloredlogs", - "pydot >= 1.4.1, <3", + "pydot >= 1.4.1", "argcomplete >= 1.12.0", "pyparsing != 3.0.2", # breaks --print-dot (pydot) https://github.com/pyparsing/pyparsing/issues/319 "cwl-utils >= 0.32", diff --git a/tests/test_context.py b/tests/test_context.py index 5f3666ce9..505dfd635 100644 --- a/tests/test_context.py +++ b/tests/test_context.py @@ -1,10 +1,10 @@ import logging import subprocess import sys +from collections.abc import MutableMapping from io import StringIO from pathlib import Path from typing import cast -from collections.abc import MutableMapping from cwltool.context import RuntimeContext from cwltool.factory import Factory