From 04d4380e59cf274228be99ddb8065627dd771d15 Mon Sep 17 00:00:00 2001 From: rocky Date: Sun, 1 Feb 2026 09:28:56 -0500 Subject: [PATCH 1/7] adding box properties - first cut --- mathics/builtin/box/expression.py | 15 ++++++++ mathics/format/render/mathml.py | 61 +++++++++++++++++-------------- 2 files changed, 49 insertions(+), 27 deletions(-) diff --git a/mathics/builtin/box/expression.py b/mathics/builtin/box/expression.py index 476e5156d..9f4e7f7ae 100644 --- a/mathics/builtin/box/expression.py +++ b/mathics/builtin/box/expression.py @@ -79,8 +79,23 @@ def __new__(cls, *elements, **kwargs): # behaviour... if not hasattr(instance, "_elements"): instance._elements = None + return instance + def __init__(self, *elements, **kwargs): + # Box attributes + # Consider adding height and width + + # Consider using a typed dataclass rather dictionary + # A value -1 means the property has not been set + self.box_properties = { + "depth": 0, # nesting level. For demo purposes + "width": -1, + "height": -1, + } + + self.box_properties + def do_format(self, evaluation, format): return self diff --git a/mathics/format/render/mathml.py b/mathics/format/render/mathml.py index c3dc3f6a2..b73fc364a 100644 --- a/mathics/format/render/mathml.py +++ b/mathics/format/render/mathml.py @@ -1,12 +1,14 @@ # -*- coding: utf-8 -*- """ -Lower-level formatter of Mathics objects as MathML strings. +Lower-level formatter of Mathics3 into MathML strings. MathML formatting is usually initiated in Mathics via MathMLForm[]. -For readability, and following WMA MathML generated code, tags \ +Following WMA MathML generated text, and for readability, MathML tags containing sub-tags are split on several lines, one by -sub element, and indented according to the level of the part. \ +sub element, and indented according to nesting level. The +indentation step size is one space. + For example, the Box expression >> FractionBox[RowBox[{"a", "+", SuperscriptBox["b", "c"]}], "d"] @@ -178,7 +180,7 @@ def pane_box(self, **options): options["_indent_level"] = indent_level + 1 content = lookup_conversion_method(self.boxes, "mathml")(self.boxes, **options) - options = self.box_options + options = self.box_properties size = options.get("System`ImageSize", SymbolAutomatic).to_python() if size is SymbolAutomatic: width = "" @@ -215,7 +217,7 @@ def pane_box(self, **options): def fractionbox(self, **options) -> str: - _options = self.box_options.copy() + _options = self.box_properties.copy() _options.update(options) options = _options indent_level = options.get("_indent_level", 0) @@ -230,13 +232,13 @@ def fractionbox(self, **options) -> str: add_conversion_fn(FractionBox, fractionbox) -def gridbox(self, elements=None, **box_options) -> str: +def gridbox(self, elements=None, **box_properties) -> str: def boxes_to_mathml(box, **options): return lookup_conversion_method(box, "mathml")(box, **options) if not elements: elements = self._elements - evaluation = box_options.get("evaluation") + evaluation = box_properties.get("evaluation") items, options = self.get_array(elements, evaluation) num_fields = max(len(item) if isinstance(item, tuple) else 1 for item in items) @@ -255,18 +257,18 @@ def boxes_to_mathml(box, **options): indent_level = options.get("_indent_level", 0) indent_spaces = " " * indent_level result = f"{indent_spaces}\n" - new_box_options = box_options.copy() - new_box_options["inside_list"] = True - new_box_options["_indent_level"] = indent_level + 3 + new_box_properties = box_properties.copy() + new_box_properties["inside_list"] = True + new_box_properties["_indent_level"] = indent_level + 3 for row in items: result += f"{indent_spaces} " if isinstance(row, tuple): for item in row: - new_box_options["_indent_level"] = indent_level + 4 - result += f"\n{indent_spaces} \n{boxes_to_mathml(item, **new_box_options)}\n{indent_spaces} " + new_box_properties["_indent_level"] = indent_level + 4 + result += f"\n{indent_spaces} \n{boxes_to_mathml(item, **new_box_properties)}\n{indent_spaces} " else: - result += f"\n{indent_spaces} \n{boxes_to_mathml(row, **new_box_options)}\n{indent_spaces} " + result += f"\n{indent_spaces} \n{boxes_to_mathml(row, **new_box_properties)}\n{indent_spaces} " result += f"\n{indent_spaces} \n" result += f"{indent_spaces}" # print(f"gridbox: {result}") @@ -277,7 +279,7 @@ def boxes_to_mathml(box, **options): def sqrtbox(self, **options): - _options = self.box_options.copy() + _options = self.box_properties.copy() _options.update(options) options = _options indent_level = options.get("_indent_level", 0) @@ -300,7 +302,7 @@ def sqrtbox(self, **options): def subscriptbox(self, **options): - _options = self.box_options.copy() + _options = self.box_properties.copy() _options.update(options) options = _options indent_level = options.get("_indent_level", 0) @@ -316,7 +318,7 @@ def subscriptbox(self, **options): def superscriptbox(self, **options): - _options = self.box_options.copy() + _options = self.box_properties.copy() _options.update(options) options = _options indent_level = options.get("_indent_level", 0) @@ -333,7 +335,7 @@ def superscriptbox(self, **options): def subsuperscriptbox(self, **options): - _options = self.box_options.copy() + _options = self.box_properties.copy() _options.update(options) options = _options options["inside_row"] = True @@ -352,8 +354,8 @@ def subsuperscriptbox(self, **options): add_conversion_fn(SubsuperscriptBox, subsuperscriptbox) -def rowbox(self, **options) -> str: - _options = self.box_options.copy() +def rowbox(box: RowBox, **options) -> str: + _options = box.box_properties.copy() _options.update(options) options = _options result = [] @@ -368,16 +370,16 @@ def is_list_interior(content): is_list_row = False if ( - len(self.items) >= 3 - and self.items[0].get_string_value() == "{" - and self.items[2].get_string_value() == "}" - and self.items[1].has_form("RowBox", 1, None) + len(box.items) >= 3 + and box.items[0].get_string_value() == "{" + and box.items[2].get_string_value() == "}" + and box.items[1].has_form("RowBox", 1, None) ): - content = self.items[1].items + content = box.items[1].items if is_list_interior(content): is_list_row = True - if not inside_row and is_list_interior(self.items): + if not inside_row and is_list_interior(box.items): is_list_row = True if is_list_row: @@ -387,9 +389,14 @@ def is_list_interior(content): indent_level = options.get("_indent_level", 0) indent_spaces = " " * indent_level + next_depth = box.box_properties["depth"] + 1 options["_indent_level"] = indent_level + 1 - for element in self.items: + for element in box.items: + # Propagate properties down to box children. + # The below test could also be done via isinstance of of Box. + if hasattr(element, "box_properties"): + element.box_properties["depth"] = next_depth result.append(lookup_conversion_method(element, "mathml")(element, **options)) # print(f"mrow: {result}") @@ -400,7 +407,7 @@ def is_list_interior(content): def stylebox(self, **options) -> str: - _options = self.box_options.copy() + _options = self.box_properties.copy() _options.update(options) options = _options return lookup_conversion_method(self.boxes, "mathml")(self.boxes, **options) From e89e2ae3b783777879c290c9d4e34ad17203b3cf Mon Sep 17 00:00:00 2001 From: rocky Date: Sun, 1 Feb 2026 17:52:03 -0500 Subject: [PATCH 2/7] Remove some unused globals --- test/format/test_format.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/format/test_format.py b/test/format/test_format.py index ba469dafc..adf27bbc9 100644 --- a/test/format/test_format.py +++ b/test/format/test_format.py @@ -50,8 +50,6 @@ def load_tests(key): of the final formats ("text", "latex", "mathml") and produce two list: the first with the mandatory tests, and the other with "fragile" tests """ - global all_tests - global MATHML_STRICT def is_fragile(assert_msg: str) -> bool: """ From 1b19abb251d5cd7957a3f91cbfc3e30239cd9301 Mon Sep 17 00:00:00 2001 From: rocky Date: Sun, 1 Feb 2026 18:50:55 -0500 Subject: [PATCH 3/7] self -> box with appropriate type --- mathics/builtin/box/layout.py | 10 +++ mathics/format/render/mathml.py | 111 ++++++++++++++++---------------- 2 files changed, 64 insertions(+), 57 deletions(-) diff --git a/mathics/builtin/box/layout.py b/mathics/builtin/box/layout.py index 23423eb8d..2c546a443 100644 --- a/mathics/builtin/box/layout.py +++ b/mathics/builtin/box/layout.py @@ -409,6 +409,16 @@ class RowBox(BoxExpression): def __repr__(self): return f"RowBox[{self.elements[0].__repr__()}]" + def __init__(self, *args, **kwargs): + # indent level nesting level used in rendering MathML boxes + self.indent_level: int = 0 + + # Consider adding. + # self.width: int = 0 + + # Pass all arguments to the parent class. + super().__init__(*args, **kwargs) + @property def elements(self): if self._elements is None: diff --git a/mathics/format/render/mathml.py b/mathics/format/render/mathml.py index b73fc364a..7f9d1e3f6 100644 --- a/mathics/format/render/mathml.py +++ b/mathics/format/render/mathml.py @@ -91,14 +91,14 @@ def encode_mathml(text: str) -> str: } -def string(self, **options) -> str: - text = self.value +def string(string: String, **options) -> str: + text = string.value number_as_text = options.get("number_as_text", None) show_string_characters = ( options.get("System`ShowStringCharacters", None) is SymbolTrue ) - if isinstance(self, BoxElementMixin): + if isinstance(string, BoxElementMixin): if number_as_text is None: number_as_text = SymbolFalse @@ -148,9 +148,9 @@ def render(format, string): add_conversion_fn(String, string) -def interpretation_box(self, **options): - boxes = self.boxes - origin = self.expr +def interpretation_box(box: InterpretationBox, **options): + boxes = box.boxes + origin = box.expr if origin.has_form("InputForm", None): # InputForm produce outputs of the form # InterpretationBox[Style[_String, ...], origin_InputForm, opts___] @@ -174,13 +174,13 @@ def interpretation_box(self, **options): add_conversion_fn(InterpretationBox, interpretation_box) -def pane_box(self, **options): +def pane_box(box, **options): indent_level = options.get("_indent_level", 0) indent_spaces = " " * indent_level options["_indent_level"] = indent_level + 1 - content = lookup_conversion_method(self.boxes, "mathml")(self.boxes, **options) - options = self.box_properties + content = lookup_conversion_method(box.boxes, "mathml")(box.boxes, **options) + options = box.box_options size = options.get("System`ImageSize", SymbolAutomatic).to_python() if size is SymbolAutomatic: width = "" @@ -216,30 +216,30 @@ def pane_box(self, **options): add_conversion_fn(PaneBox, pane_box) -def fractionbox(self, **options) -> str: - _options = self.box_properties.copy() +def fractionbox(box: FractionBox, **options) -> str: + _options = box.box_options.copy() _options.update(options) options = _options indent_level = options.get("_indent_level", 0) indent_spaces = " " * indent_level options["_indent_level"] = indent_level + 1 return f"{indent_spaces}\n%s\n%s\n{indent_spaces}" % ( - lookup_conversion_method(self.num, "mathml")(self.num, **options), - lookup_conversion_method(self.den, "mathml")(self.den, **options), + lookup_conversion_method(box.num, "mathml")(box.num, **options), + lookup_conversion_method(box.den, "mathml")(box.den, **options), ) add_conversion_fn(FractionBox, fractionbox) -def gridbox(self, elements=None, **box_properties) -> str: +def gridbox(box: GridBox, elements=None, **box_options) -> str: def boxes_to_mathml(box, **options): return lookup_conversion_method(box, "mathml")(box, **options) if not elements: - elements = self._elements - evaluation = box_properties.get("evaluation") - items, options = self.get_array(elements, evaluation) + elements = box._elements + evaluation = box_options.get("evaluation") + items, options = box.get_array(elements, evaluation) num_fields = max(len(item) if isinstance(item, tuple) else 1 for item in items) attrs = {} @@ -257,18 +257,18 @@ def boxes_to_mathml(box, **options): indent_level = options.get("_indent_level", 0) indent_spaces = " " * indent_level result = f"{indent_spaces}\n" - new_box_properties = box_properties.copy() - new_box_properties["inside_list"] = True - new_box_properties["_indent_level"] = indent_level + 3 + new_box_options = box_options.copy() + new_box_options["inside_list"] = True + new_box_options["_indent_level"] = indent_level + 3 for row in items: result += f"{indent_spaces} " if isinstance(row, tuple): for item in row: - new_box_properties["_indent_level"] = indent_level + 4 - result += f"\n{indent_spaces} \n{boxes_to_mathml(item, **new_box_properties)}\n{indent_spaces} " + new_box_options["_indent_level"] = indent_level + 4 + result += f"\n{indent_spaces} \n{boxes_to_mathml(item, **new_box_options)}\n{indent_spaces} " else: - result += f"\n{indent_spaces} \n{boxes_to_mathml(row, **new_box_properties)}\n{indent_spaces} " + result += f"\n{indent_spaces} \n{boxes_to_mathml(row, **new_box_options)}\n{indent_spaces} " result += f"\n{indent_spaces} \n" result += f"{indent_spaces}" # print(f"gridbox: {result}") @@ -278,47 +278,47 @@ def boxes_to_mathml(box, **options): add_conversion_fn(GridBox, gridbox) -def sqrtbox(self, **options): - _options = self.box_properties.copy() +def sqrtbox(box: SqrtBox, **options): + _options = box.box_options.copy() _options.update(options) options = _options indent_level = options.get("_indent_level", 0) indent_spaces = " " * indent_level options["_indent_level"] = indent_level + 1 - if self.index: + if box.index: return f"{indent_spaces}\n%s\n%s\n{indent_spaces}" % ( - lookup_conversion_method(self.radicand, "mathml")(self.radicand, **options), - lookup_conversion_method(self.index, "mathml")(self.index, **options), + lookup_conversion_method(box.radicand, "mathml")(box.radicand, **options), + lookup_conversion_method(box.index, "mathml")(box.index, **options), ) return ( f"{indent_spaces}\n%s\n{indent_spaces}" - % lookup_conversion_method(self.radicand, "mathml")(self.radicand, **options) + % lookup_conversion_method(box.radicand, "mathml")(box.radicand, **options) ) add_conversion_fn(SqrtBox, sqrtbox) -def subscriptbox(self, **options): - _options = self.box_properties.copy() +def subscriptbox(box: SqrtBox, **options): + _options = box.box_options.copy() _options.update(options) options = _options indent_level = options.get("_indent_level", 0) indent_spaces = " " * indent_level options["_indent_level"] = indent_level + 1 return f"{indent_spaces}\n%s\n%s\n{indent_spaces}" % ( - lookup_conversion_method(self.base, "mathml")(self.base, **options), - lookup_conversion_method(self.subindex, "mathml")(self.subindex, **options), + lookup_conversion_method(box.base, "mathml")(box.base, **options), + lookup_conversion_method(box.subindex, "mathml")(box.subindex, **options), ) add_conversion_fn(SubscriptBox, subscriptbox) -def superscriptbox(self, **options): - _options = self.box_properties.copy() +def superscriptbox(box: SuperscriptBox, **options): + _options = box.box_options.copy() _options.update(options) options = _options indent_level = options.get("_indent_level", 0) @@ -326,16 +326,16 @@ def superscriptbox(self, **options): options["_indent_level"] = indent_level + 1 return f"{indent_spaces}\n%s\n%s\n{indent_spaces}" % ( - lookup_conversion_method(self.base, "mathml")(self.base, **options), - lookup_conversion_method(self.superindex, "mathml")(self.superindex, **options), + lookup_conversion_method(box.base, "mathml")(box.base, **options), + lookup_conversion_method(box.superindex, "mathml")(box.superindex, **options), ) add_conversion_fn(SuperscriptBox, superscriptbox) -def subsuperscriptbox(self, **options): - _options = self.box_properties.copy() +def subsuperscriptbox(box: SubscriptBox, **options): + _options = box.box_options.copy() _options.update(options) options = _options options["inside_row"] = True @@ -345,9 +345,9 @@ def subsuperscriptbox(self, **options): options["_indent_level"] = indent_level + 1 return f"{indent_spaces}\n%s\n%s\n%s\n{indent_spaces}" % ( - lookup_conversion_method(self.base, "mathml")(self.base, **options), - lookup_conversion_method(self.subindex, "mathml")(self.subindex, **options), - lookup_conversion_method(self.superindex, "mathml")(self.superindex, **options), + lookup_conversion_method(box.base, "mathml")(box.base, **options), + lookup_conversion_method(box.subindex, "mathml")(box.subindex, **options), + lookup_conversion_method(box.superindex, "mathml")(box.superindex, **options), ) @@ -355,7 +355,7 @@ def subsuperscriptbox(self, **options): def rowbox(box: RowBox, **options) -> str: - _options = box.box_properties.copy() + _options = box.box_options.copy() _options.update(options) options = _options result = [] @@ -389,14 +389,11 @@ def is_list_interior(content): indent_level = options.get("_indent_level", 0) indent_spaces = " " * indent_level - next_depth = box.box_properties["depth"] + 1 options["_indent_level"] = indent_level + 1 for element in box.items: # Propagate properties down to box children. # The below test could also be done via isinstance of of Box. - if hasattr(element, "box_properties"): - element.box_properties["depth"] = next_depth result.append(lookup_conversion_method(element, "mathml")(element, **options)) # print(f"mrow: {result}") @@ -406,20 +403,20 @@ def is_list_interior(content): add_conversion_fn(RowBox, rowbox) -def stylebox(self, **options) -> str: - _options = self.box_properties.copy() +def stylebox(box: StyleBox, **options) -> str: + _options = box.box_options.copy() _options.update(options) options = _options - return lookup_conversion_method(self.boxes, "mathml")(self.boxes, **options) + return lookup_conversion_method(box.boxes, "mathml")(box.boxes, **options) add_conversion_fn(StyleBox, stylebox) -def graphicsbox(self, elements=None, **options) -> str: +def graphicsbox(box: GraphicsBox, elements=None, **options) -> str: # FIXME: SVG is the only thing we can convert MathML into. # Handle other graphics formats. - svg_body = self.boxes_to_svg(elements, **options) + svg_body = box.boxes_to_svg(elements, **options) # mglyph, which is what we have been using, is bad because MathML standard changed. # metext does not work because the way in which we produce the svg images is also based on this outdated mglyph @@ -431,8 +428,8 @@ def graphicsbox(self, elements=None, **options) -> str: ) # print(svg_body) mathml = template % ( - int(self.width), - int(self.height), + int(box.width), + int(box.height), base64.b64encode(svg_body.encode("utf8")).decode("utf8"), ) indent_level = options.get("_indent_level", 0) @@ -446,9 +443,9 @@ def graphicsbox(self, elements=None, **options) -> str: add_conversion_fn(GraphicsBox, graphicsbox) -def graphics3dbox(self, elements=None, **options) -> str: +def graphics3dbox(box: Graphics3DBox, elements=None, **options) -> str: """Turn the Graphics3DBox into a MathML string""" - json_repr = self.boxes_to_json(elements, **options) + json_repr = box.boxes_to_json(elements, **options) mathml = f'' mathml = f"\n\n\n{mathml}\n\n\n" indent_level = options.get("_indent_level", 0) @@ -460,8 +457,8 @@ def graphics3dbox(self, elements=None, **options) -> str: add_conversion_fn(Graphics3DBox, graphics3dbox) -def tag_and_form_box(self, **options): - return lookup_conversion_method(self.boxes, "mathml")(self.boxes, **options) +def tag_and_form_box(box, **options): + return lookup_conversion_method(box.boxes, "mathml")(box.boxes, **options) add_conversion_fn(FormBox, tag_and_form_box) From 24cc06e29166c55dba00ce5b853cf6b61e4bf7ac Mon Sep 17 00:00:00 2001 From: rocky Date: Sun, 1 Feb 2026 20:02:23 -0500 Subject: [PATCH 4/7] Add more info to box_options --- mathics/format/render/mathml.py | 41 ++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/mathics/format/render/mathml.py b/mathics/format/render/mathml.py index 7f9d1e3f6..c059b9ad5 100644 --- a/mathics/format/render/mathml.py +++ b/mathics/format/render/mathml.py @@ -91,22 +91,27 @@ def encode_mathml(text: str) -> str: } -def string(string: String, **options) -> str: - text = string.value +# "s" is a String or What? +def string(s, **options) -> str: + text = s.value number_as_text = options.get("number_as_text", None) show_string_characters = ( options.get("System`ShowStringCharacters", None) is SymbolTrue ) - if isinstance(string, BoxElementMixin): + if isinstance(s, BoxElementMixin): if number_as_text is None: number_as_text = SymbolFalse - indent_level = options.get("_indent_level", 0) + if hasattr(s, "box_options"): + indent_level = s.box_options.get("indent_level", 0) + else: + indent_level = options.get("_indent_level", 0) + indent_spaces = " " * indent_level - def render(format, string): - encoded_text = encode_mathml(string) + def render(format, s): + encoded_text = encode_mathml(s) return indent_spaces + format % encoded_text if text.startswith('"') and text.endswith('"'): @@ -217,15 +222,25 @@ def pane_box(box, **options): def fractionbox(box: FractionBox, **options) -> str: - _options = box.box_options.copy() - _options.update(options) - options = _options - indent_level = options.get("_indent_level", 0) + indent_level = box.box_options.get("_indent_level", options.get("_indent_level", 0)) indent_spaces = " " * indent_level - options["_indent_level"] = indent_level + 1 + indent_level += 1 + has_nonbox_children = False + + for child_box in (box.num, box.den): + if hasattr(child_box, "box_options"): + child_box.box_options["_indent_level"] = indent_level + else: + has_nonbox_children = True + + if has_nonbox_children: + # non_boxed children have to get indent_level information passed down + # via a parameter. Here it is the "options" variable. (Which is a bad name). + child_options = {**options, "_indent_level": indent_level} + return f"{indent_spaces}\n%s\n%s\n{indent_spaces}" % ( - lookup_conversion_method(box.num, "mathml")(box.num, **options), - lookup_conversion_method(box.den, "mathml")(box.den, **options), + lookup_conversion_method(box.num, "mathml")(box.num, **child_options), + lookup_conversion_method(box.den, "mathml")(box.den, **child_options), ) From d416b4047c9dc62d1cd1b133fa036492e4fceb8e Mon Sep 17 00:00:00 2001 From: rocky Date: Sun, 1 Feb 2026 22:21:13 -0500 Subject: [PATCH 5/7] _indent_level -> indent_level Remove expression box_properties --- mathics/builtin/box/expression.py | 15 ----------- mathics/format/box/outputforms.py | 2 +- mathics/format/render/mathml.py | 42 +++++++++++++++---------------- 3 files changed, 22 insertions(+), 37 deletions(-) diff --git a/mathics/builtin/box/expression.py b/mathics/builtin/box/expression.py index 9f4e7f7ae..476e5156d 100644 --- a/mathics/builtin/box/expression.py +++ b/mathics/builtin/box/expression.py @@ -79,23 +79,8 @@ def __new__(cls, *elements, **kwargs): # behaviour... if not hasattr(instance, "_elements"): instance._elements = None - return instance - def __init__(self, *elements, **kwargs): - # Box attributes - # Consider adding height and width - - # Consider using a typed dataclass rather dictionary - # A value -1 means the property has not been set - self.box_properties = { - "depth": 0, # nesting level. For demo purposes - "width": -1, - "height": -1, - } - - self.box_properties - def do_format(self, evaluation, format): return self diff --git a/mathics/format/box/outputforms.py b/mathics/format/box/outputforms.py index a248d127f..09de275d9 100644 --- a/mathics/format/box/outputforms.py +++ b/mathics/format/box/outputforms.py @@ -30,7 +30,7 @@ def eval_mathmlform(expr: BaseElement, evaluation: Evaluation) -> BoxElementMixi boxes = format_element(expr, evaluation, SymbolTraditionalForm) try: - mathml = boxes.boxes_to_mathml(evaluation=evaluation, _indent_level=1) + mathml = boxes.boxes_to_mathml(evaluation=evaluation, indent_level=1) except BoxError: evaluation.message( "General", diff --git a/mathics/format/render/mathml.py b/mathics/format/render/mathml.py index c059b9ad5..a18411e5e 100644 --- a/mathics/format/render/mathml.py +++ b/mathics/format/render/mathml.py @@ -106,7 +106,7 @@ def string(s, **options) -> str: if hasattr(s, "box_options"): indent_level = s.box_options.get("indent_level", 0) else: - indent_level = options.get("_indent_level", 0) + indent_level = options.get("indent_level", 0) indent_spaces = " " * indent_level @@ -180,9 +180,9 @@ def interpretation_box(box: InterpretationBox, **options): def pane_box(box, **options): - indent_level = options.get("_indent_level", 0) + indent_level = options.get("indent_level", 0) indent_spaces = " " * indent_level - options["_indent_level"] = indent_level + 1 + options["indent_level"] = indent_level + 1 content = lookup_conversion_method(box.boxes, "mathml")(box.boxes, **options) options = box.box_options @@ -222,21 +222,21 @@ def pane_box(box, **options): def fractionbox(box: FractionBox, **options) -> str: - indent_level = box.box_options.get("_indent_level", options.get("_indent_level", 0)) + indent_level = box.box_options.get("indent_level", options.get("indent_level", 0)) indent_spaces = " " * indent_level indent_level += 1 has_nonbox_children = False for child_box in (box.num, box.den): if hasattr(child_box, "box_options"): - child_box.box_options["_indent_level"] = indent_level + child_box.box_options["indent_level"] = indent_level else: has_nonbox_children = True if has_nonbox_children: # non_boxed children have to get indent_level information passed down # via a parameter. Here it is the "options" variable. (Which is a bad name). - child_options = {**options, "_indent_level": indent_level} + child_options = {**options, "indent_level": indent_level} return f"{indent_spaces}\n%s\n%s\n{indent_spaces}" % ( lookup_conversion_method(box.num, "mathml")(box.num, **child_options), @@ -269,18 +269,18 @@ def boxes_to_mathml(box, **options): # invalid column alignment raise BoxConstructError joined_attrs = " ".join(f'{name}="{value}"' for name, value in attrs.items()) - indent_level = options.get("_indent_level", 0) + indent_level = options.get("indent_level", 0) indent_spaces = " " * indent_level result = f"{indent_spaces}\n" new_box_options = box_options.copy() new_box_options["inside_list"] = True - new_box_options["_indent_level"] = indent_level + 3 + new_box_options["indent_level"] = indent_level + 3 for row in items: result += f"{indent_spaces} " if isinstance(row, tuple): for item in row: - new_box_options["_indent_level"] = indent_level + 4 + new_box_options["indent_level"] = indent_level + 4 result += f"\n{indent_spaces} \n{boxes_to_mathml(item, **new_box_options)}\n{indent_spaces} " else: result += f"\n{indent_spaces} \n{boxes_to_mathml(row, **new_box_options)}\n{indent_spaces} " @@ -297,9 +297,9 @@ def sqrtbox(box: SqrtBox, **options): _options = box.box_options.copy() _options.update(options) options = _options - indent_level = options.get("_indent_level", 0) + indent_level = options.get("indent_level", 0) indent_spaces = " " * indent_level - options["_indent_level"] = indent_level + 1 + options["indent_level"] = indent_level + 1 if box.index: return f"{indent_spaces}\n%s\n%s\n{indent_spaces}" % ( @@ -320,9 +320,9 @@ def subscriptbox(box: SqrtBox, **options): _options = box.box_options.copy() _options.update(options) options = _options - indent_level = options.get("_indent_level", 0) + indent_level = options.get("indent_level", 0) indent_spaces = " " * indent_level - options["_indent_level"] = indent_level + 1 + options["indent_level"] = indent_level + 1 return f"{indent_spaces}\n%s\n%s\n{indent_spaces}" % ( lookup_conversion_method(box.base, "mathml")(box.base, **options), lookup_conversion_method(box.subindex, "mathml")(box.subindex, **options), @@ -336,9 +336,9 @@ def superscriptbox(box: SuperscriptBox, **options): _options = box.box_options.copy() _options.update(options) options = _options - indent_level = options.get("_indent_level", 0) + indent_level = options.get("indent_level", 0) indent_spaces = " " * indent_level - options["_indent_level"] = indent_level + 1 + options["indent_level"] = indent_level + 1 return f"{indent_spaces}\n%s\n%s\n{indent_spaces}" % ( lookup_conversion_method(box.base, "mathml")(box.base, **options), @@ -355,9 +355,9 @@ def subsuperscriptbox(box: SubscriptBox, **options): options = _options options["inside_row"] = True - indent_level = options.get("_indent_level", 0) + indent_level = options.get("indent_level", 0) indent_spaces = " " * indent_level - options["_indent_level"] = indent_level + 1 + options["indent_level"] = indent_level + 1 return f"{indent_spaces}\n%s\n%s\n%s\n{indent_spaces}" % ( lookup_conversion_method(box.base, "mathml")(box.base, **options), @@ -402,9 +402,9 @@ def is_list_interior(content): else: options["inside_row"] = True - indent_level = options.get("_indent_level", 0) + indent_level = options.get("indent_level", 0) indent_spaces = " " * indent_level - options["_indent_level"] = indent_level + 1 + options["indent_level"] = indent_level + 1 for element in box.items: # Propagate properties down to box children. @@ -447,7 +447,7 @@ def graphicsbox(box: GraphicsBox, elements=None, **options) -> str: int(box.height), base64.b64encode(svg_body.encode("utf8")).decode("utf8"), ) - indent_level = options.get("_indent_level", 0) + indent_level = options.get("indent_level", 0) if indent_level: mathml = " " * indent_level + mathml @@ -463,7 +463,7 @@ def graphics3dbox(box: Graphics3DBox, elements=None, **options) -> str: json_repr = box.boxes_to_json(elements, **options) mathml = f'' mathml = f"\n\n\n{mathml}\n\n\n" - indent_level = options.get("_indent_level", 0) + indent_level = options.get("indent_level", 0) if indent_level: mathml = " " * indent_level + mathml return mathml From 59bcdc23b0501841c83aa803faf26f7c3efb856b Mon Sep 17 00:00:00 2001 From: rocky Date: Mon, 2 Feb 2026 05:28:52 -0500 Subject: [PATCH 6/7] box_options -> box_attributes --- mathics/builtin/box/compilation.py | 2 +- mathics/builtin/box/layout.py | 62 +++++++++++++++--------------- mathics/format/render/latex.py | 30 +++++++-------- mathics/format/render/mathml.py | 42 ++++++++++---------- mathics/format/render/text.py | 24 ++++++------ 5 files changed, 82 insertions(+), 78 deletions(-) diff --git a/mathics/builtin/box/compilation.py b/mathics/builtin/box/compilation.py index ce2a2fe7a..4a45a9b1f 100644 --- a/mathics/builtin/box/compilation.py +++ b/mathics/builtin/box/compilation.py @@ -21,7 +21,7 @@ class CompiledCodeBox(BoxExpression): def init(self, *args, **kwargs): self._elements = args - self.box_options = kwargs + self.box_attributes = kwargs def boxes_to_text(self, elements=None, **options): if elements is None: diff --git a/mathics/builtin/box/layout.py b/mathics/builtin/box/layout.py index 2c546a443..e34b6c3d8 100644 --- a/mathics/builtin/box/layout.py +++ b/mathics/builtin/box/layout.py @@ -122,7 +122,7 @@ class FormBox(BoxExpression): summary_text = "wrap boxes with an association to a particular form" def init(self, *elems, **kwargs): - self.box_options = kwargs + self.box_attributes = kwargs self.form = elems[1] self.boxes = elems[0] assert isinstance(self.boxes, BoxElementMixin), f"{type(self.boxes)}" @@ -136,7 +136,7 @@ def elements(self): self.boxes, self.form, ), - self.box_options, + self.box_attributes, ) return self._elements @@ -178,7 +178,7 @@ def elements(self): self.num, self.den, ), - self.box_options, + self.box_attributes, ) return self._elements @@ -193,7 +193,7 @@ def eval(self, num, den, evaluation: Evaluation, options: dict): def init(self, num, den, **options): self.num = num self.den = den - self.box_options = options + self.box_attributes = options class GridBox(BoxExpression): @@ -228,11 +228,13 @@ class GridBox(BoxExpression): @property def elements(self): if self._elements is None: - self._elements = elements_to_expressions(self, self.items, self.box_options) + self._elements = elements_to_expressions( + self, self.items, self.box_attributes + ) return self._elements def init(self, *elems, **kwargs): - self.box_options = kwargs + self.box_attributes = kwargs self.items = elems self._elements = elems @@ -240,7 +242,7 @@ def get_array(self, elements, evaluation): if not elements: raise BoxConstructError - options = self.box_options + options = self.box_attributes expr = elements[0] if not expr.has_form("List", None): @@ -293,13 +295,13 @@ class InterpretationBox(BoxExpression): def __repr__(self): result = "InterpretationBox\n " + repr(self.boxes) - result += f"\n {self.box_options}" + result += f"\n {self.box_attributes}" return result def init(self, *expr, **options): self.boxes = expr[0] self.expr = expr[1] - self.box_options = options + self.box_attributes = options @property def elements(self): @@ -310,7 +312,7 @@ def elements(self): self.boxes, self.expr, ), - self.box_options, + self.box_attributes, ) return self._elements @@ -365,13 +367,13 @@ class PaneBox(BoxExpression): def elements(self): if self._elements is None: self._elements = elements_to_expressions( - self, (self.boxes,), self.box_options + self, (self.boxes,), self.box_attributes ) return self._elements def init(self, expr, **options): self.boxes = expr - self.box_options = options + self.box_attributes = options def eval_panebox1(self, expr, evaluation, options): "PaneBox[expr_String, OptionsPattern[]]" @@ -443,7 +445,7 @@ def eval_list(self, boxes, evaluation): def init(self, *items, **kwargs): # TODO: check that each element is an string or a BoxElementMixin - self.box_options = {} + self.box_attributes = {} if len(items) == 0: self.items = tuple() return @@ -519,13 +521,13 @@ def elements(self): if self._elements is None: index = self.index if index is None: - # self.box_options + # self.box_attributes self._elements = elements_to_expressions( - self, (self.radicand,), self.box_options + self, (self.radicand,), self.box_attributes ) else: self._elements = elements_to_expressions( - self, (self.radicand, index), self.box_options + self, (self.radicand, index), self.box_attributes ) return self._elements @@ -545,7 +547,7 @@ def eval(self, radicand, evaluation: Evaluation, options: dict): def init(self, radicand, index=None, **options): self.radicand = radicand self.index = index - self.box_options = options + self.box_attributes = options class StyleBox(BoxExpression): @@ -577,11 +579,11 @@ def elements(self): boxes = self.boxes if style: self._elements = elements_to_expressions( - self, (boxes, style), self.box_options + self, (boxes, style), self.box_attributes ) else: self._elements = elements_to_expressions( - self, (boxes,), self.box_options + self, (boxes,), self.box_attributes ) return self._elements @@ -606,10 +608,10 @@ def get_string_value(self) -> str: def init(self, boxes, style=None, **options): # This implementation supersedes Expression.process_style_box if isinstance(boxes, StyleBox): - options.update(boxes.box_options) + options.update(boxes.box_attributes) boxes = boxes.boxes self.style = style - self.box_options = options + self.box_attributes = options assert options is not None self.boxes = boxes assert isinstance( @@ -645,7 +647,7 @@ class SubscriptBox(BoxExpression): def elements(self): if self._elements is None: self._elements = elements_to_expressions( - self, (self.base, self.subindex), self.box_options + self, (self.base, self.subindex), self.box_attributes ) return self._elements @@ -658,7 +660,7 @@ def eval(self, a, b, evaluation: Evaluation, options: dict): return SubscriptBox(a_box, b_box, **options) def init(self, a, b, **options): - self.box_options = options.copy() + self.box_attributes = options.copy() if not (isinstance(a, BoxElementMixin) and isinstance(b, BoxElementMixin)): raise Exception((a, b), "are not boxes") self.base = a @@ -684,7 +686,7 @@ class SubsuperscriptBox(BoxExpression): @property def elements(self): if self._elements is None: - # self.box_options + # self.box_attributes self._elements = elements_to_expressions( ( self, @@ -692,7 +694,7 @@ def elements(self): self.subindex, self.superindex, ), - self.box_options, + self.box_attributes, ) return self._elements @@ -706,7 +708,7 @@ def eval(self, a, b, c, evaluation: Evaluation, options: dict): return SubsuperscriptBox(a_box, b_box, c_box, **options) def init(self, a, b, c, **options): - self.box_options = options.copy() + self.box_attributes = options.copy() if not all(isinstance(x, BoxElementMixin) for x in (a, b, c)): raise Exception((a, b, c), "are not boxes") self.base = a @@ -739,7 +741,7 @@ def elements(self): self.base, self.superindex, ), - self.box_options, + self.box_attributes, ) return self._elements @@ -752,7 +754,7 @@ def eval(self, a, b, evaluation: Evaluation, options: dict): return SuperscriptBox(a_box, b_box, **options) def init(self, a, b, **options): - self.box_options = options.copy() + self.box_attributes = options.copy() if not all(isinstance(x, BoxElementMixin) for x in (a, b)): raise Exception((a, b), "are not boxes") self.base = a @@ -776,7 +778,7 @@ class TagBox(BoxExpression): summary_text = "box tag with a head" def init(self, *elems, **kwargs): - self.box_options = kwargs + self.box_attributes = kwargs self.form = elems[1] self.boxes = elems[0] assert isinstance(self.boxes, BoxElementMixin), f"{type(self.boxes)}" @@ -790,7 +792,7 @@ def elements(self): self.boxes, self.form, ), - self.box_options, + self.box_attributes, ) return self._elements diff --git a/mathics/format/render/latex.py b/mathics/format/render/latex.py index 8cf27c403..a936ad587 100644 --- a/mathics/format/render/latex.py +++ b/mathics/format/render/latex.py @@ -174,7 +174,7 @@ def interpretation_box(self, **options): def pane_box(self, **options): content = lookup_conversion_method(self.boxes, "latex")(self.boxes, **options) - options = self.box_options + options = self.box_attributes size = options.get("System`ImageSize", SymbolAutomatic).to_python() if size == "System`Automatic": @@ -211,7 +211,7 @@ def pane_box(self, **options): def fractionbox(self, **options) -> str: - _options = self.box_options.copy() + _options = self.box_attributes.copy() _options.update(options) options = _options return "\\frac{%s}{%s}" % ( @@ -223,17 +223,17 @@ def fractionbox(self, **options) -> str: add_conversion_fn(FractionBox, fractionbox) -def gridbox(self, elements=None, **box_options) -> str: +def gridbox(self, elements=None, **box_attributes) -> str: def boxes_to_tex(box, **options): return lookup_conversion_method(box, "latex")(box, **options) if not elements: elements = self._elements - evaluation = box_options.get("evaluation") + evaluation = box_attributes.get("evaluation") items, options = self.get_array(elements, evaluation) - box_options.update(options) - box_options["inside_list"] = True - column_alignments = box_options["System`ColumnAlignments"].get_name() + box_attributes.update(options) + box_attributes["inside_list"] = True + column_alignments = box_attributes["System`ColumnAlignments"].get_name() try: column_alignments = { "System`Center": "c", @@ -251,12 +251,12 @@ def boxes_to_tex(box, **options): result = r"\begin{array}{%s} " % (column_alignments * column_count) for index, row in enumerate(items): if isinstance(row, tuple): - result += " & ".join(boxes_to_tex(item, **box_options) for item in row) + result += " & ".join(boxes_to_tex(item, **box_attributes) for item in row) else: result += r"\multicolumn{%s}{%s}{%s}" % ( str(column_count), column_alignments, - boxes_to_tex(row, **box_options), + boxes_to_tex(row, **box_attributes), ) if index != len(items) - 1: result += "\\\\ " @@ -268,7 +268,7 @@ def boxes_to_tex(box, **options): def sqrtbox(self, **options): - _options = self.box_options.copy() + _options = self.box_attributes.copy() _options.update(options) options = _options if self.index: @@ -285,7 +285,7 @@ def sqrtbox(self, **options): def superscriptbox(self, **options): - _options = self.box_options.copy() + _options = self.box_attributes.copy() _options.update(options) options = _options base_to_tex = lookup_conversion_method(self.base, "latex") @@ -315,7 +315,7 @@ def superscriptbox(self, **options): def subscriptbox(self, **options): - _options = self.box_options.copy() + _options = self.box_attributes.copy() _options.update(options) options = _options base_to_tex = lookup_conversion_method(self.base, "latex") @@ -330,7 +330,7 @@ def subscriptbox(self, **options): def subsuperscriptbox(self, **options): - _options = self.box_options.copy() + _options = self.box_attributes.copy() _options.update(options) options = _options base_to_tex = lookup_conversion_method(self.base, "latex") @@ -348,7 +348,7 @@ def subsuperscriptbox(self, **options): def rowbox(self, **options) -> str: - _options = self.box_options.copy() + _options = self.box_attributes.copy() _options.update(options) options = _options parts_str = [ @@ -382,7 +382,7 @@ def rowbox(self, **options) -> str: def stylebox(self, **options) -> str: - _options = self.box_options.copy() + _options = self.box_attributes.copy() _options.update(options) options = _options return lookup_conversion_method(self.boxes, "latex")(self.boxes, **options) diff --git a/mathics/format/render/mathml.py b/mathics/format/render/mathml.py index a18411e5e..968c19e8a 100644 --- a/mathics/format/render/mathml.py +++ b/mathics/format/render/mathml.py @@ -103,8 +103,8 @@ def string(s, **options) -> str: if number_as_text is None: number_as_text = SymbolFalse - if hasattr(s, "box_options"): - indent_level = s.box_options.get("indent_level", 0) + if hasattr(s, "box_attributes"): + indent_level = s.box_attributes.get("indent_level", 0) else: indent_level = options.get("indent_level", 0) @@ -185,7 +185,7 @@ def pane_box(box, **options): options["indent_level"] = indent_level + 1 content = lookup_conversion_method(box.boxes, "mathml")(box.boxes, **options) - options = box.box_options + options = box.box_attributes size = options.get("System`ImageSize", SymbolAutomatic).to_python() if size is SymbolAutomatic: width = "" @@ -222,14 +222,16 @@ def pane_box(box, **options): def fractionbox(box: FractionBox, **options) -> str: - indent_level = box.box_options.get("indent_level", options.get("indent_level", 0)) + indent_level = box.box_attributes.get( + "indent_level", options.get("indent_level", 0) + ) indent_spaces = " " * indent_level indent_level += 1 has_nonbox_children = False for child_box in (box.num, box.den): - if hasattr(child_box, "box_options"): - child_box.box_options["indent_level"] = indent_level + if hasattr(child_box, "box_attributes"): + child_box.box_attributes["indent_level"] = indent_level else: has_nonbox_children = True @@ -247,13 +249,13 @@ def fractionbox(box: FractionBox, **options) -> str: add_conversion_fn(FractionBox, fractionbox) -def gridbox(box: GridBox, elements=None, **box_options) -> str: +def gridbox(box: GridBox, elements=None, **box_attributes) -> str: def boxes_to_mathml(box, **options): return lookup_conversion_method(box, "mathml")(box, **options) if not elements: elements = box._elements - evaluation = box_options.get("evaluation") + evaluation = box_attributes.get("evaluation") items, options = box.get_array(elements, evaluation) num_fields = max(len(item) if isinstance(item, tuple) else 1 for item in items) @@ -272,18 +274,18 @@ def boxes_to_mathml(box, **options): indent_level = options.get("indent_level", 0) indent_spaces = " " * indent_level result = f"{indent_spaces}\n" - new_box_options = box_options.copy() - new_box_options["inside_list"] = True - new_box_options["indent_level"] = indent_level + 3 + new_box_attributes = box_attributes.copy() + new_box_attributes["inside_list"] = True + new_box_attributes["indent_level"] = indent_level + 3 for row in items: result += f"{indent_spaces} " if isinstance(row, tuple): for item in row: - new_box_options["indent_level"] = indent_level + 4 - result += f"\n{indent_spaces} \n{boxes_to_mathml(item, **new_box_options)}\n{indent_spaces} " + new_box_attributes["indent_level"] = indent_level + 4 + result += f"\n{indent_spaces} \n{boxes_to_mathml(item, **new_box_attributes)}\n{indent_spaces} " else: - result += f"\n{indent_spaces} \n{boxes_to_mathml(row, **new_box_options)}\n{indent_spaces} " + result += f"\n{indent_spaces} \n{boxes_to_mathml(row, **new_box_attributes)}\n{indent_spaces} " result += f"\n{indent_spaces} \n" result += f"{indent_spaces}" # print(f"gridbox: {result}") @@ -294,7 +296,7 @@ def boxes_to_mathml(box, **options): def sqrtbox(box: SqrtBox, **options): - _options = box.box_options.copy() + _options = box.box_attributes.copy() _options.update(options) options = _options indent_level = options.get("indent_level", 0) @@ -317,7 +319,7 @@ def sqrtbox(box: SqrtBox, **options): def subscriptbox(box: SqrtBox, **options): - _options = box.box_options.copy() + _options = box.box_attributes.copy() _options.update(options) options = _options indent_level = options.get("indent_level", 0) @@ -333,7 +335,7 @@ def subscriptbox(box: SqrtBox, **options): def superscriptbox(box: SuperscriptBox, **options): - _options = box.box_options.copy() + _options = box.box_attributes.copy() _options.update(options) options = _options indent_level = options.get("indent_level", 0) @@ -350,7 +352,7 @@ def superscriptbox(box: SuperscriptBox, **options): def subsuperscriptbox(box: SubscriptBox, **options): - _options = box.box_options.copy() + _options = box.box_attributes.copy() _options.update(options) options = _options options["inside_row"] = True @@ -370,7 +372,7 @@ def subsuperscriptbox(box: SubscriptBox, **options): def rowbox(box: RowBox, **options) -> str: - _options = box.box_options.copy() + _options = box.box_attributes.copy() _options.update(options) options = _options result = [] @@ -419,7 +421,7 @@ def is_list_interior(content): def stylebox(box: StyleBox, **options) -> str: - _options = box.box_options.copy() + _options = box.box_attributes.copy() _options.update(options) options = _options return lookup_conversion_method(box.boxes, "mathml")(box.boxes, **options) diff --git a/mathics/format/render/text.py b/mathics/format/render/text.py index 249a64dcb..fcd28dfc0 100644 --- a/mathics/format/render/text.py +++ b/mathics/format/render/text.py @@ -61,7 +61,7 @@ def pane_box(self, **options): def fractionbox(self, **options) -> str: - _options = self.box_options.copy() + _options = self.box_attributes.copy() _options.update(options) options = _options num_text = boxes_to_text(self.num, **options) @@ -77,13 +77,13 @@ def fractionbox(self, **options) -> str: add_conversion_fn(FractionBox, fractionbox) -def gridbox(self, elements=None, **box_options) -> str: +def gridbox(self, elements=None, **box_attributes) -> str: if not elements: elements = self.items - evaluation = box_options.get("evaluation", None) + evaluation = box_attributes.get("evaluation", None) items, options = self.get_array(elements, evaluation) - box_options.update(self.options) + box_attributes.update(self.options) if not items: return "" @@ -92,11 +92,11 @@ def gridbox(self, elements=None, **box_options) -> str: ( [ # TODO: check if this evaluation is necessary. - boxes_to_text(item, **box_options) + boxes_to_text(item, **box_attributes) for item in row ] if isinstance(row, tuple) - else boxes_to_text(row, **box_options) + else boxes_to_text(row, **box_attributes) ) for row in items ] @@ -111,7 +111,7 @@ def gridbox(self, elements=None, **box_options) -> str: def sqrtbox(self, **options) -> str: - _options = self.box_options.copy() + _options = self.box_attributes.copy() _options.update(options) options = _options if self.index: @@ -126,7 +126,7 @@ def sqrtbox(self, **options) -> str: def superscriptbox(self, **options) -> str: - _options = self.box_options.copy() + _options = self.box_attributes.copy() _options.update(options) options = _options no_parenthesize = True @@ -150,7 +150,7 @@ def superscriptbox(self, **options) -> str: def subscriptbox(self, **options) -> str: - _options = self.box_options.copy() + _options = self.box_attributes.copy() _options.update(options) options = _options return "Subscript[%s, %s]" % ( @@ -163,7 +163,7 @@ def subscriptbox(self, **options) -> str: def subsuperscriptbox(self, **options) -> str: - _options = self.box_options.copy() + _options = self.box_attributes.copy() _options.update(options) options = _options return "Subsuperscript[%s, %s, %s]" % ( @@ -177,7 +177,7 @@ def subsuperscriptbox(self, **options) -> str: def rowbox(self, elements=None, **options) -> str: - _options = self.box_options.copy() + _options = self.box_attributes.copy() _options.update(options) options = _options parts_str = [boxes_to_text(element, **options) for element in self.items] @@ -209,7 +209,7 @@ def rowbox(self, elements=None, **options) -> str: def stylebox(self, **options) -> str: options.pop("evaluation", None) - _options = self.box_options.copy() + _options = self.box_attributes.copy() _options.update(options) options = _options return boxes_to_text(self.boxes, **options) From 41293d4efce0c8c3524d1716018f4763ba45f469 Mon Sep 17 00:00:00 2001 From: rocky Date: Mon, 2 Feb 2026 05:35:38 -0500 Subject: [PATCH 7/7] Clean up type defintion on MathML string. --- mathics/format/render/mathml.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/mathics/format/render/mathml.py b/mathics/format/render/mathml.py index 968c19e8a..5a943e1d7 100644 --- a/mathics/format/render/mathml.py +++ b/mathics/format/render/mathml.py @@ -91,23 +91,17 @@ def encode_mathml(text: str) -> str: } -# "s" is a String or What? -def string(s, **options) -> str: +def string(s: String, **options) -> str: text = s.value number_as_text = options.get("number_as_text", None) show_string_characters = ( options.get("System`ShowStringCharacters", None) is SymbolTrue ) - if isinstance(s, BoxElementMixin): - if number_as_text is None: - number_as_text = SymbolFalse - - if hasattr(s, "box_attributes"): - indent_level = s.box_attributes.get("indent_level", 0) - else: - indent_level = options.get("indent_level", 0) + if number_as_text is None: + number_as_text = SymbolFalse + indent_level = options.get("indent_level", 0) indent_spaces = " " * indent_level def render(format, s):