diff --git a/.github/workflows/development.yaml b/.github/workflows/development.yaml index b4f2363c..d565f51a 100644 --- a/.github/workflows/development.yaml +++ b/.github/workflows/development.yaml @@ -108,7 +108,8 @@ jobs: - name: Run style tests run: | flake8 --ignore=E203,E722,W503 datajoint \ - --count --max-complexity=62 --max-line-length=127 --statistics + --count --max-complexity=62 --max-line-length=127 --statistics \ + --per-file-ignores='datajoint/diagram.py:C901' black --required-version '24.2.0' --check -v datajoint tests tests_old codespell: name: Check for spelling errors diff --git a/CHANGELOG.md b/CHANGELOG.md index f05e514e..79ae622b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ## Release notes +### 0.14.3 -- TBD +- Fixed - Added encapsulating double quotes to comply with [DOT language](https://graphviz.org/doc/info/lang.html) - PR [#1177](https://github.com/datajoint/datajoint-python/pull/1177) + ### 0.14.2 -- Aug 19, 2024 - Added - Migrate nosetests to pytest - PR [#1142](https://github.com/datajoint/datajoint-python/pull/1142) - Added - Codespell GitHub Actions workflow diff --git a/datajoint/diagram.py b/datajoint/diagram.py index 65497fcf..7f47f746 100644 --- a/datajoint/diagram.py +++ b/datajoint/diagram.py @@ -300,6 +300,36 @@ def _make_graph(self): nx.relabel_nodes(graph, mapping, copy=False) return graph + @staticmethod + def _encapsulate_edge_attributes(graph): + """ + Modifies the `nx.Graph`'s edge attribute `attr_map` to be a string representation + of the attribute map, and encapsulates the string in double quotes. + Changes the graph in place. + + Implements workaround described in + https://github.com/pydot/pydot/issues/258#issuecomment-795798099 + """ + for u, v, *_, edgedata in graph.edges(data=True): + if "attr_map" in edgedata: + graph.edges[u, v]["attr_map"] = '"{0}"'.format(edgedata["attr_map"]) + + @staticmethod + def _encapsulate_node_names(graph): + """ + Modifies the `nx.Graph`'s node names string representations encapsulated in + double quotes. + Changes the graph in place. + + Implements workaround described in + https://github.com/datajoint/datajoint-python/pull/1176 + """ + nx.relabel_nodes( + graph, + {node: '"{0}"'.format(node) for node in graph.nodes()}, + copy=False, + ) + def make_dot(self): graph = self._make_graph() graph.nodes() @@ -368,6 +398,8 @@ def make_dot(self): for node, d in dict(graph.nodes(data=True)).items() } + self._encapsulate_node_names(graph) + self._encapsulate_edge_attributes(graph) dot = nx.drawing.nx_pydot.to_pydot(graph) for node in dot.get_nodes(): node.set_shape("circle") @@ -408,9 +440,14 @@ def make_dot(self): for edge in dot.get_edges(): # see https://graphviz.org/doc/info/attrs.html - src = edge.get_source().strip('"') - dest = edge.get_destination().strip('"') + src = edge.get_source() + dest = edge.get_destination() props = graph.get_edge_data(src, dest) + if props is None: + raise DataJointError( + "Could not find edge with source " + "'{}' and destination '{}'".format(src, dest) + ) edge.set_color("#00000040") edge.set_style("solid" if props["primary"] else "dashed") master_part = graph.nodes[dest][ diff --git a/datajoint/version.py b/datajoint/version.py index 61b9ccf2..6bcf0e20 100644 --- a/datajoint/version.py +++ b/datajoint/version.py @@ -1,3 +1,3 @@ -__version__ = "0.14.2" +__version__ = "0.14.3" assert len(__version__) <= 10 # The log table limits version to the 10 characters