diff --git a/examples/roads.ipynb b/examples/roads.ipynb index 081e72f..e640e4c 100644 --- a/examples/roads.ipynb +++ b/examples/roads.ipynb @@ -187,35 +187,35 @@ "name": "stdout", "output_type": "stream", "text": [ - "Edge{[Camooweal] -- [Mount Isa], cost=188}\n", - "Edge{[Mount Isa] -- [Cloncurry], cost=118}\n", - "Edge{[Cloncurry] -- [Hughenden], cost=401}\n", - "Edge{[Cloncurry] -- [Winton], cost=350}\n", - "Edge{[Hughenden] -- [Charters Towers], cost=248}\n", - "Edge{[Charters Towers] -- [Townsville], cost=135}\n", - "Edge{[Townsville] -- [Mackay], cost=388}\n", - "Edge{[Mackay] -- [Rockhampton], cost=334}\n", - "Edge{[Mackay] -- [Emerald], cost=384}\n", - "Edge{[Rockhampton] -- [Brisbane], cost=682}\n", - "Edge{[Rockhampton] -- [Emerald], cost=270}\n", - "Edge{[Brisbane] -- [Roma], cost=482}\n", - "Edge{[Roma] -- [Charleville], cost=266}\n", - "Edge{[Charleville] -- [Blackall], cost=305}\n", - "Edge{[Blackall] -- [Barcaldine], cost=106}\n", - "Edge{[Blackall] -- [Windorah], cost=530}\n", - "Edge{[Barcaldine] -- [Emerald], cost=307}\n", - "Edge{[Barcaldine] -- [Hughenden], cost=500}\n", - "Edge{[Barcaldine] -- [Longreach], cost=106}\n", - "Edge{[Longreach] -- [Windorah], cost=311}\n", - "Edge{[Longreach] -- [Winton], cost=180}\n", - "Edge{[Winton] -- [Hughenden], cost=216}\n", - "Edge{[Winton] -- [Boulia], cost=363}\n", - "Edge{[Winton] -- [Windorah], cost=487}\n", - "Edge{[Boulia] -- [Mount Isa], cost=304}\n", - "Edge{[Boulia] -- [Bedourie], cost=194}\n", - "Edge{[Bedourie] -- [Birdsville], cost=193}\n", - "Edge{[Birdsville] -- [Windorah], cost=380}\n", - "Edge{[Bedourie] -- [Windorah], cost=411}\n" + "Edge{[Camooweal] ↔ [Mount Isa], cost=188}\n", + "Edge{[Mount Isa] ↔ [Cloncurry], cost=118}\n", + "Edge{[Cloncurry] ↔ [Hughenden], cost=401}\n", + "Edge{[Cloncurry] ↔ [Winton], cost=350}\n", + "Edge{[Hughenden] ↔ [Charters Towers], cost=248}\n", + "Edge{[Charters Towers] ↔ [Townsville], cost=135}\n", + "Edge{[Townsville] ↔ [Mackay], cost=388}\n", + "Edge{[Mackay] ↔ [Rockhampton], cost=334}\n", + "Edge{[Mackay] ↔ [Emerald], cost=384}\n", + "Edge{[Rockhampton] ↔ [Brisbane], cost=682}\n", + "Edge{[Rockhampton] ↔ [Emerald], cost=270}\n", + "Edge{[Brisbane] ↔ [Roma], cost=482}\n", + "Edge{[Roma] ↔ [Charleville], cost=266}\n", + "Edge{[Charleville] ↔ [Blackall], cost=305}\n", + "Edge{[Blackall] ↔ [Barcaldine], cost=106}\n", + "Edge{[Blackall] ↔ [Windorah], cost=530}\n", + "Edge{[Barcaldine] ↔ [Emerald], cost=307}\n", + "Edge{[Barcaldine] ↔ [Hughenden], cost=500}\n", + "Edge{[Barcaldine] ↔ [Longreach], cost=106}\n", + "Edge{[Longreach] ↔ [Windorah], cost=311}\n", + "Edge{[Longreach] ↔ [Winton], cost=180}\n", + "Edge{[Winton] ↔ [Hughenden], cost=216}\n", + "Edge{[Winton] ↔ [Boulia], cost=363}\n", + "Edge{[Winton] ↔ [Windorah], cost=487}\n", + "Edge{[Boulia] ↔ [Mount Isa], cost=304}\n", + "Edge{[Boulia] ↔ [Bedourie], cost=194}\n", + "Edge{[Bedourie] ↔ [Birdsville], cost=193}\n", + "Edge{[Birdsville] ↔ [Windorah], cost=380}\n", + "Edge{[Bedourie] ↔ [Windorah], cost=411}\n" ] } ], diff --git a/src/pgraph/PGraph.py b/src/pgraph/PGraph.py index 8f9f6af..42bf33f 100644 --- a/src/pgraph/PGraph.py +++ b/src/pgraph/PGraph.py @@ -4265,6 +4265,9 @@ def __str__(self) -> str: :return: endpoints, cost and optional data :rtype: str + The endpoints are separated by ``→`` if the edge is in a directed graph + and by ``↔`` otherwise. + .. runblock:: pycon >>> from pgraph import Vertex, Edge @@ -4273,10 +4276,15 @@ def __str__(self) -> str: >>> e = Edge(v1, v2, cost=5.0, data="A to B") >>> str(e) + .. versionchanged:: 1.1 + The separator was ``--`` or ``->``. Output redirected to a file or pipe + under a legacy Windows code page (cp1252) can raise + ``UnicodeEncodeError``; set ``PYTHONUTF8=1`` to avoid it. + :seealso: :meth:`__repr__` """ graph = self.v1._graph if self.v1 is not None else None - arrow = "->" if graph is not None and graph.directed else "--" + arrow = "→" if graph is not None and graph.directed else "↔" cost_str = "None" if self.cost is None else f"{self.cost:.4g}" s = f"{self.__class__.__name__}{{{self.v1} {arrow} {self.v2}, cost={cost_str}}}" if self.data is not None: diff --git a/tests/test_graph.py b/tests/test_graph.py index a534e39..f5a716d 100644 --- a/tests/test_graph.py +++ b/tests/test_graph.py @@ -81,7 +81,7 @@ def test_show_lists_vertices_and_edges(self): " b at [3 4] component=0", " c at [5 6] component=1", "edges:", - " Edge{[a] -- [b], cost=2.5}", + " Edge{[a] ↔ [b], cost=2.5}", ], ) diff --git a/tests/test_unified_graph.py b/tests/test_unified_graph.py index 72016c7..4b2acdf 100644 --- a/tests/test_unified_graph.py +++ b/tests/test_unified_graph.py @@ -251,14 +251,19 @@ def test_other_names_in_the_module_are_errors(self): class TestEdgeArrow(unittest.TestCase): def test_arrow_follows_the_graph(self): - for flag, arrow in ((False, "--"), (True, "->")): + for flag, expected in ( + (False, "Edge{[a] ↔ [b], cost=3}"), + (True, "Edge{[a] → [b], cost=3}"), + ): g = Graph(directed=flag) a, b = g.add_vertex(name="a"), g.add_vertex(name="b") - self.assertIn(arrow, str(g.add_edge(a, b))) + e = g.add_edge(a, b, cost=3) + self.assertEqual(str(e), expected) + self.assertEqual(repr(e), expected) def test_a_standalone_edge_has_no_arrow_to_show(self): e = Edge(Vertex(name="a"), Vertex(name="b"), cost=1) - self.assertIn("--", str(e)) + self.assertEqual(str(e), "Edge{[a] ↔ [b], cost=1}") if __name__ == "__main__":