diff --git a/pymathics/graph/boxes.py b/pymathics/graph/boxes.py index 4284c78..15bb926 100644 --- a/pymathics/graph/boxes.py +++ b/pymathics/graph/boxes.py @@ -8,51 +8,47 @@ import base64 import tempfile - - from typing import Tuple from mathics.core.element import BaseElement, BoxElementMixin - from pymathics.graph.format import png_format_graph, svg_format_graph no_doc = True + class GraphBox(BoxElementMixin): def __init__(self, G, **options): self.G = G self.options = options - def boxes_to_b64text( - self, elements: Tuple[BaseElement] = None, **options - ) -> Tuple[bytes, Tuple[int, int]]: + def to_b64text(self, **options) -> Tuple[bytes, Tuple[int, int]]: """ Produces a base64 png representation and a tuple with the size of the pillow image associated to the object. """ - contents, size = self.boxes_to_png(elements, **options) + contents, size = self.to_png(**options) encoded = base64.b64encode(contents) encoded = b"data:image/png;base64," + encoded return encoded, size - def boxes_to_png(self, elements=None, **options) -> Tuple[bytes, Tuple[int, int]]: + def to_png(self, **options) -> Tuple[bytes, Tuple[int, int]]: """ returns a tuple with the set of bytes with a png representation of the image and the scaled size. """ return png_format_graph(self.G, **self.options), (800, 600) - def boxes_to_svg(self, elements=None, **options): + def to_svg(self, **options): return svg_format_graph(self.G, **self.options), (400, 300) - def boxes_to_tex(self, elements=None, **options) -> str: + def to_tex(self, **options) -> str: """ Store the associated image as a png file and return a LaTeX command for including it. """ - data, size = self.boxes_to_png(elements, **options) + data, size = self.to_png(elements, **options) res = 100 # pixels/cm width_str, height_str = (str(n / res).strip() for n in size) head = rf"\includegraphics[width={width_str}cm,height={height_str}cm]" @@ -69,11 +65,11 @@ def boxes_to_tex(self, elements=None, **options) -> str: return head + "{" + format(path) + "}" - def boxes_to_text(self, elements=None, **options): + def to_text(self, **options): return "-Graph-" - def boxes_to_mathml(self, elements=None, **options): - encoded, size = self.boxes_to_b64text(elements, **options) + def to_mathml(self, **options): + encoded, size = self.to_b64text(**options) decoded = encoded.decode("utf8") # see https://tools.ietf.org/html/rfc2397 return f'' diff --git a/pymathics/graph/format.py b/pymathics/graph/format.py index edbe44e..a9af6bb 100644 --- a/pymathics/graph/format.py +++ b/pymathics/graph/format.py @@ -115,7 +115,6 @@ def get_png_graph() -> BytesIO: def hierarchy_pos( G, root=None, width=1.0, vert_gap=0.2, vert_loc=0, leaf_vs_root_factor=0.5 ): - """Position nodes in tree layout. The root is at the top. Based on Joel's answer at https://stackoverflow.com/a/29597209/2966723, diff --git a/pyproject.toml b/pyproject.toml index 5946038..6d33f86 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,11 +1,10 @@ [build-system] requires = [ "setuptools", # CVE-2024-38335 recommends this - "Mathics3>9.0.0", + "mathics-core >= 9.0.1", "Mathics3-Module-Base", "networkx>=3.0.0", "matplotlib", - "Mathics3-Module-Base", ] build-backend = "setuptools.build_meta" diff --git a/test/helper.py b/test/helper.py index 2a33cfa..65c419c 100644 --- a/test/helper.py +++ b/test/helper.py @@ -12,9 +12,7 @@ # Set up a Mathics session with definitions. # For consistency set the character encoding ASCII which is # the lowest common denominator available on all systems. -session = MathicsSession( - character_encoding="ASCII" -) +session = MathicsSession(character_encoding="ASCII") def reset_session(add_builtin=True, catch_interrupt=False): @@ -115,7 +113,7 @@ def check_evaluation( assert ( expected_len == got_len ), f"expected {expected_len}; got {got_len}. Messages: {outs}" - for (out, msg) in zip(outs, msgs): + for out, msg in zip(outs, msgs): if out != msg: print(f"out:<<{out}>>") print(" and ") diff --git a/test/test_fixme.py b/test/test_fixme.py index adc9e71..d6413ad 100644 --- a/test/test_fixme.py +++ b/test/test_fixme.py @@ -5,77 +5,78 @@ from test.helper import check_evaluation, evaluate, evaluate_value import pytest + def setup_module(module): """Load pymathics.graph""" assert evaluate_value('LoadModule["pymathics.graph"]') == "pymathics.graph" evaluate("SortList[list_] := Sort[Map[Sort, list]]") - @pytest.mark.skip("Wrong result. Investigate me.") def test_EdgeList(): check_evaluation( - "EdgeList[{1 -> 2, 2 <-> 3}]", - "{DirectedEdge[1, 2], UndirectedEdge[2, 3]}" - ) + "EdgeList[{1 -> 2, 2 <-> 3}]", "{DirectedEdge[1, 2], UndirectedEdge[2, 3]}" + ) - @pytest.mark.skip("Wrong result. Investigate me.") def test_FindShortestPath(): - check_evaluation( - ( - "g = Graph[{1 -> 2, 2 -> 3, 1 -> 3}, EdgeWeight -> {0.5, a, 3}];" - "a = 0.5; FindShortestPath[g, 1, 3]'"), - "{1, 2, 3}") - check_evaluation("a = 10; FindShortestPath[g, 1, 3]", "{1, 3}") - check_evaluation("a = .;", "Null") - - + check_evaluation( + ( + "g = Graph[{1 -> 2, 2 -> 3, 1 -> 3}, EdgeWeight -> {0.5, a, 3}];" + "a = 0.5; FindShortestPath[g, 1, 3]'" + ), + "{1, 2, 3}", + ) + check_evaluation("a = 10; FindShortestPath[g, 1, 3]", "{1, 3}") + check_evaluation("a = .;", "Null") @pytest.mark.skip("This finds d<->a in the position 4 instead 2.") def test_EdgeIndex(): - check_evaluation("EdgeIndex[{c <-> d, d <-> a, a -> e}, d <-> a]", - "2") + check_evaluation("EdgeIndex[{c <-> d, d <-> a, a -> e}, d <-> a]", "2") + - @pytest.mark.parametrize( ("str_expr", "str_expect"), [ ( - ("g = Graph[{1 -> 2, 2 -> 3}, DirectedEdges -> True];" - "EdgeCount[g, _DirectedEdge]"), - "2" + ( + "g = Graph[{1 -> 2, 2 -> 3}, DirectedEdges -> True];" + "EdgeCount[g, _DirectedEdge]" + ), + "2", ), ( ( "g = Graph[{1 -> 2, 2 -> 3}, DirectedEdges -> False];" - "EdgeCount[g, _DirectedEdge]"), - "0" + "EdgeCount[g, _DirectedEdge]" + ), + "0", ), - ("EdgeCount[g, _UndirectedEdge]","2") - ] + ("EdgeCount[g, _UndirectedEdge]", "2"), + ], ) @pytest.mark.skip("This finds d<->a in the position 4 instead 2.") def test_edgecount(str_expr, str_expect): check_evaluation(str_expr, str_expect) - + @pytest.mark.skip("This finds d<->a in the position 4 instead 2.") def test_EdgeIndex(): - check_evaluation("EdgeIndex[{c <-> d, d <-> a, a -> e}, d <-> a]", - "2") + check_evaluation("EdgeIndex[{c <-> d, d <-> a, a -> e}, d <-> a]", "2") + @pytest.mark.skip("This is not properly evaluated. Investigate me") def test_HITSCentrality(): - check_evaluation("g = Graph[{a -> d, b -> c, d -> c, d -> a, e -> c}]; HITSCentrality[g]", - "{{0.292893, 0., 0., 0.707107, 0.}, {0., 1., 0.707107, 0., 0.707107}}") + check_evaluation( + "g = Graph[{a -> d, b -> c, d -> c, d -> a, e -> c}]; HITSCentrality[g]", + "{{0.292893, 0., 0., 0.707107, 0.}, {0., 1., 0.707107, 0., 0.707107}}", + ) + @pytest.mark.skip("Investigate me.") def test_EdgeRules(): check_evaluation( - "EdgeRules[{1 <-> 2, 2 -> 3, 3 <-> 4}]", - "{1 -> 2, 2 -> 3, 3 -> 4}" + "EdgeRules[{1 <-> 2, 2 -> 3, 3 <-> 4}]", "{1 -> 2, 2 -> 3, 3 -> 4}" ) -