Skip to content

Commit 754ca27

Browse files
authored
Merge pull request #90 from petercorke/feat/edge-unicode-arrows
feat(edge): show ↔ and → between the ends of an edge
2 parents 17b8470 + bd045d7 commit 754ca27

4 files changed

Lines changed: 47 additions & 34 deletions

File tree

‎examples/roads.ipynb‎

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -187,35 +187,35 @@
187187
"name": "stdout",
188188
"output_type": "stream",
189189
"text": [
190-
"Edge{[Camooweal] -- [Mount Isa], cost=188}\n",
191-
"Edge{[Mount Isa] -- [Cloncurry], cost=118}\n",
192-
"Edge{[Cloncurry] -- [Hughenden], cost=401}\n",
193-
"Edge{[Cloncurry] -- [Winton], cost=350}\n",
194-
"Edge{[Hughenden] -- [Charters Towers], cost=248}\n",
195-
"Edge{[Charters Towers] -- [Townsville], cost=135}\n",
196-
"Edge{[Townsville] -- [Mackay], cost=388}\n",
197-
"Edge{[Mackay] -- [Rockhampton], cost=334}\n",
198-
"Edge{[Mackay] -- [Emerald], cost=384}\n",
199-
"Edge{[Rockhampton] -- [Brisbane], cost=682}\n",
200-
"Edge{[Rockhampton] -- [Emerald], cost=270}\n",
201-
"Edge{[Brisbane] -- [Roma], cost=482}\n",
202-
"Edge{[Roma] -- [Charleville], cost=266}\n",
203-
"Edge{[Charleville] -- [Blackall], cost=305}\n",
204-
"Edge{[Blackall] -- [Barcaldine], cost=106}\n",
205-
"Edge{[Blackall] -- [Windorah], cost=530}\n",
206-
"Edge{[Barcaldine] -- [Emerald], cost=307}\n",
207-
"Edge{[Barcaldine] -- [Hughenden], cost=500}\n",
208-
"Edge{[Barcaldine] -- [Longreach], cost=106}\n",
209-
"Edge{[Longreach] -- [Windorah], cost=311}\n",
210-
"Edge{[Longreach] -- [Winton], cost=180}\n",
211-
"Edge{[Winton] -- [Hughenden], cost=216}\n",
212-
"Edge{[Winton] -- [Boulia], cost=363}\n",
213-
"Edge{[Winton] -- [Windorah], cost=487}\n",
214-
"Edge{[Boulia] -- [Mount Isa], cost=304}\n",
215-
"Edge{[Boulia] -- [Bedourie], cost=194}\n",
216-
"Edge{[Bedourie] -- [Birdsville], cost=193}\n",
217-
"Edge{[Birdsville] -- [Windorah], cost=380}\n",
218-
"Edge{[Bedourie] -- [Windorah], cost=411}\n"
190+
"Edge{[Camooweal] ↔ [Mount Isa], cost=188}\n",
191+
"Edge{[Mount Isa] ↔ [Cloncurry], cost=118}\n",
192+
"Edge{[Cloncurry] ↔ [Hughenden], cost=401}\n",
193+
"Edge{[Cloncurry] ↔ [Winton], cost=350}\n",
194+
"Edge{[Hughenden] ↔ [Charters Towers], cost=248}\n",
195+
"Edge{[Charters Towers] ↔ [Townsville], cost=135}\n",
196+
"Edge{[Townsville] ↔ [Mackay], cost=388}\n",
197+
"Edge{[Mackay] ↔ [Rockhampton], cost=334}\n",
198+
"Edge{[Mackay] ↔ [Emerald], cost=384}\n",
199+
"Edge{[Rockhampton] ↔ [Brisbane], cost=682}\n",
200+
"Edge{[Rockhampton] ↔ [Emerald], cost=270}\n",
201+
"Edge{[Brisbane] ↔ [Roma], cost=482}\n",
202+
"Edge{[Roma] ↔ [Charleville], cost=266}\n",
203+
"Edge{[Charleville] ↔ [Blackall], cost=305}\n",
204+
"Edge{[Blackall] ↔ [Barcaldine], cost=106}\n",
205+
"Edge{[Blackall] ↔ [Windorah], cost=530}\n",
206+
"Edge{[Barcaldine] ↔ [Emerald], cost=307}\n",
207+
"Edge{[Barcaldine] ↔ [Hughenden], cost=500}\n",
208+
"Edge{[Barcaldine] ↔ [Longreach], cost=106}\n",
209+
"Edge{[Longreach] ↔ [Windorah], cost=311}\n",
210+
"Edge{[Longreach] ↔ [Winton], cost=180}\n",
211+
"Edge{[Winton] ↔ [Hughenden], cost=216}\n",
212+
"Edge{[Winton] ↔ [Boulia], cost=363}\n",
213+
"Edge{[Winton] ↔ [Windorah], cost=487}\n",
214+
"Edge{[Boulia] ↔ [Mount Isa], cost=304}\n",
215+
"Edge{[Boulia] ↔ [Bedourie], cost=194}\n",
216+
"Edge{[Bedourie] ↔ [Birdsville], cost=193}\n",
217+
"Edge{[Birdsville] ↔ [Windorah], cost=380}\n",
218+
"Edge{[Bedourie] ↔ [Windorah], cost=411}\n"
219219
]
220220
}
221221
],

‎src/pgraph/PGraph.py‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4265,6 +4265,9 @@ def __str__(self) -> str:
42654265
:return: endpoints, cost and optional data
42664266
:rtype: str
42674267
4268+
The endpoints are separated by ``→`` if the edge is in a directed graph
4269+
and by ``↔`` otherwise.
4270+
42684271
.. runblock:: pycon
42694272
42704273
>>> from pgraph import Vertex, Edge
@@ -4273,10 +4276,15 @@ def __str__(self) -> str:
42734276
>>> e = Edge(v1, v2, cost=5.0, data="A to B")
42744277
>>> str(e)
42754278
4279+
.. versionchanged:: 1.1
4280+
The separator was ``--`` or ``->``. Output redirected to a file or pipe
4281+
under a legacy Windows code page (cp1252) can raise
4282+
``UnicodeEncodeError``; set ``PYTHONUTF8=1`` to avoid it.
4283+
42764284
:seealso: :meth:`__repr__`
42774285
"""
42784286
graph = self.v1._graph if self.v1 is not None else None
4279-
arrow = "->" if graph is not None and graph.directed else "--"
4287+
arrow = "→" if graph is not None and graph.directed else "↔"
42804288
cost_str = "None" if self.cost is None else f"{self.cost:.4g}"
42814289
s = f"{self.__class__.__name__}{{{self.v1} {arrow} {self.v2}, cost={cost_str}}}"
42824290
if self.data is not None:

‎tests/test_graph.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def test_show_lists_vertices_and_edges(self):
8181
" b at [3 4] component=0",
8282
" c at [5 6] component=1",
8383
"edges:",
84-
" Edge{[a] -- [b], cost=2.5}",
84+
" Edge{[a] ↔ [b], cost=2.5}",
8585
],
8686
)
8787

‎tests/test_unified_graph.py‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,14 +251,19 @@ def test_other_names_in_the_module_are_errors(self):
251251

252252
class TestEdgeArrow(unittest.TestCase):
253253
def test_arrow_follows_the_graph(self):
254-
for flag, arrow in ((False, "--"), (True, "->")):
254+
for flag, expected in (
255+
(False, "Edge{[a] ↔ [b], cost=3}"),
256+
(True, "Edge{[a] → [b], cost=3}"),
257+
):
255258
g = Graph(directed=flag)
256259
a, b = g.add_vertex(name="a"), g.add_vertex(name="b")
257-
self.assertIn(arrow, str(g.add_edge(a, b)))
260+
e = g.add_edge(a, b, cost=3)
261+
self.assertEqual(str(e), expected)
262+
self.assertEqual(repr(e), expected)
258263

259264
def test_a_standalone_edge_has_no_arrow_to_show(self):
260265
e = Edge(Vertex(name="a"), Vertex(name="b"), cost=1)
261-
self.assertIn("--", str(e))
266+
self.assertEqual(str(e), "Edge{[a] ↔ [b], cost=1}")
262267

263268

264269
if __name__ == "__main__":

0 commit comments

Comments
 (0)