From de6b4906416ee0a9e6e6f1a4211600f9767a64fa Mon Sep 17 00:00:00 2001 From: rocky Date: Wed, 4 Feb 2026 13:03:41 -0500 Subject: [PATCH 1/3] box attribute vs option separation for MathMLForm --- mathics/builtin/box/layout.py | 7 +++++ mathics/format/render/mathml.py | 46 +++++++++------------------------ 2 files changed, 19 insertions(+), 34 deletions(-) diff --git a/mathics/builtin/box/layout.py b/mathics/builtin/box/layout.py index d198db8b2..d3b7a075b 100644 --- a/mathics/builtin/box/layout.py +++ b/mathics/builtin/box/layout.py @@ -390,6 +390,13 @@ class RowBox(BoxExpression): summary_text = "horizontal arrange of boxes" + def __init__(self, *args, **kwargs): + super().__init__(args, kwargs) + + # TODO Describe why inside row and inside list are needed. + self.inside_row = False + self.inside_list = False + def __repr__(self): return f"RowBox[{self.elements[0].__repr__()}]" diff --git a/mathics/format/render/mathml.py b/mathics/format/render/mathml.py index 70c641e4c..ce1cbacba 100644 --- a/mathics/format/render/mathml.py +++ b/mathics/format/render/mathml.py @@ -2,7 +2,7 @@ """ Mathics3 Graphics3D box rendering to MathML strings. -MathML formatting is usually initiated in Mathics via MathMLForm[]. +MathML rendering is usually initiated via MathMLForm[]. """ import base64 @@ -169,9 +169,6 @@ def pane_box(box: PaneBox, **options): def fractionbox(box: FractionBox, **options) -> str: - _options = box.box_options.copy() - _options.update(options) - options = _options return "%s %s" % ( lookup_conversion_method(box.num, "mathml")(box.num, **options), lookup_conversion_method(box.den, "mathml")(box.den, **options), @@ -204,15 +201,17 @@ def boxes_to_mathml(box, **options): raise BoxConstructError joined_attrs = " ".join(f'{name}="{value}"' for name, value in attrs.items()) result = f"\n" - new_box_options = box_options.copy() - new_box_options["inside_list"] = True for row in items: result += "" if isinstance(row, tuple): for item in row: - result += f"{boxes_to_mathml(item, **new_box_options)}" + item.inside_list = True + result += ( + f"{boxes_to_mathml(item, **options)}" + ) else: - result += f"{boxes_to_mathml(row, **new_box_options)}" + row.inside_list = True + result += f"{boxes_to_mathml(row, **options)}" result += "\n" result += "" # print(f"gridbox: {result}") @@ -223,9 +222,6 @@ def boxes_to_mathml(box, **options): def sqrtbox(box: SqrtBox, **options): - _options = box.box_options.copy() - _options.update(options) - options = _options if box.index: return " %s %s " % ( lookup_conversion_method(box.radicand, "mathml")(box.radicand, **options), @@ -241,9 +237,6 @@ def sqrtbox(box: SqrtBox, **options): def subscriptbox(box: SubscriptBox, **options): - _options = box.box_options.copy() - _options.update(options) - options = _options return "%s %s" % ( lookup_conversion_method(box.base, "mathml")(box.base, **options), lookup_conversion_method(box.subindex, "mathml")(box.subindex, **options), @@ -254,9 +247,6 @@ def subscriptbox(box: SubscriptBox, **options): def superscriptbox(box: SuperscriptBox, **options): - _options = box.box_options.copy() - _options.update(options) - options = _options return "%s %s" % ( lookup_conversion_method(box.base, "mathml")(box.base, **options), lookup_conversion_method(box.superindex, "mathml")(box.superindex, **options), @@ -267,10 +257,7 @@ def superscriptbox(box: SuperscriptBox, **options): def subsuperscriptbox(box: SubsuperscriptBox, **options): - _options = box.box_options.copy() - _options.update(options) - options = _options - options["inside_row"] = True + box.base.inside_row = box.subindex.inside_row = box.superindex.inside_row = True return "%s %s %s" % ( lookup_conversion_method(box.base, "mathml")(box.base, **options), lookup_conversion_method(box.subindex, "mathml")(box.subindex, **options), @@ -282,13 +269,8 @@ def subsuperscriptbox(box: SubsuperscriptBox, **options): def rowbox(box: RowBox, **options) -> str: - _options = box.box_options.copy() - _options.update(options) - options = _options result = [] - inside_row = options.get("inside_row") - # inside_list = options.get('inside_list') - options = options.copy() + inside_row = box.inside_row def is_list_interior(content): if all(element.get_string_value() == "," for element in content[1::2]): @@ -309,12 +291,11 @@ def is_list_interior(content): if not inside_row and is_list_interior(box.items): is_list_row = True - if is_list_row: - options["inside_list"] = True - else: - options["inside_row"] = True + nest_field = "inside_list" if is_list_row else "inside_row" for element in box.items: + if hasattr(element, nest_field): + setattr(element, nest_field, True) result.append(lookup_conversion_method(element, "mathml")(element, **options)) # print(f"mrow: {result}") @@ -326,9 +307,6 @@ def is_list_interior(content): def stylebox(box: StyleBox, **options) -> str: - _options = box.box_options.copy() - _options.update(options) - options = _options return lookup_conversion_method(box.boxes, "mathml")(box.boxes, **options) From 694b547d72b0d295095a8d7f0a5057e861e17b6d Mon Sep 17 00:00:00 2001 From: rocky Date: Wed, 4 Feb 2026 16:25:39 -0500 Subject: [PATCH 2/3] copy box.box_options options to children --- mathics/format/render/mathml.py | 47 ++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/mathics/format/render/mathml.py b/mathics/format/render/mathml.py index ce1cbacba..3e959974e 100644 --- a/mathics/format/render/mathml.py +++ b/mathics/format/render/mathml.py @@ -169,9 +169,11 @@ def pane_box(box: PaneBox, **options): def fractionbox(box: FractionBox, **options) -> str: + # Note: values set in `options` take precedence over `box_options` + child_options = {**options, **box.box_options} return "%s %s" % ( - 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), ) @@ -222,10 +224,14 @@ def boxes_to_mathml(box, **options): def sqrtbox(box: SqrtBox, **options): + # Note: values set in `options` take precedence over `box_options` + child_options = {**options, **box.box_options} if box.index: return " %s %s " % ( - lookup_conversion_method(box.radicand, "mathml")(box.radicand, **options), - lookup_conversion_method(box.index, "mathml")(box.index, **options), + lookup_conversion_method(box.radicand, "mathml")( + box.radicand, **child_options + ), + lookup_conversion_method(box.index, "mathml")(box.index, **child_options), ) return " %s " % lookup_conversion_method(box.radicand, "mathml")( @@ -237,9 +243,11 @@ def sqrtbox(box: SqrtBox, **options): def subscriptbox(box: SubscriptBox, **options): + # Note: values set in `options` take precedence over `box_options` + child_options = {**options, **box.box_options} return "%s %s" % ( - lookup_conversion_method(box.base, "mathml")(box.base, **options), - lookup_conversion_method(box.subindex, "mathml")(box.subindex, **options), + lookup_conversion_method(box.base, "mathml")(box.base, **child_options), + lookup_conversion_method(box.subindex, "mathml")(box.subindex, **child_options), ) @@ -247,9 +255,13 @@ def subscriptbox(box: SubscriptBox, **options): def superscriptbox(box: SuperscriptBox, **options): + # Note: values set in `options` take precedence over `box_options` + child_options = {**options, **box.box_options} return "%s %s" % ( - lookup_conversion_method(box.base, "mathml")(box.base, **options), - lookup_conversion_method(box.superindex, "mathml")(box.superindex, **options), + lookup_conversion_method(box.base, "mathml")(box.base, **child_options), + lookup_conversion_method(box.superindex, "mathml")( + box.superindex, **child_options + ), ) @@ -257,11 +269,15 @@ def superscriptbox(box: SuperscriptBox, **options): def subsuperscriptbox(box: SubsuperscriptBox, **options): + # Note: values set in `options` take precedence over `box_options` + child_options = {**box.box_options, **options} box.base.inside_row = box.subindex.inside_row = box.superindex.inside_row = True return "%s %s %s" % ( - 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), + lookup_conversion_method(box.base, "mathml")(box.base, **child_options), + lookup_conversion_method(box.subindex, "mathml")(box.subindex, **child_options), + lookup_conversion_method(box.superindex, "mathml")( + box.superindex, **child_options + ), ) @@ -269,6 +285,8 @@ def subsuperscriptbox(box: SubsuperscriptBox, **options): def rowbox(box: RowBox, **options) -> str: + # Note: values set in `options` take precedence over `box_options` + child_options = {**box.box_options, **options} result = [] inside_row = box.inside_row @@ -296,7 +314,9 @@ def is_list_interior(content): for element in box.items: if hasattr(element, nest_field): setattr(element, nest_field, True) - result.append(lookup_conversion_method(element, "mathml")(element, **options)) + result.append( + lookup_conversion_method(element, "mathml")(element, **child_options) + ) # print(f"mrow: {result}") @@ -307,7 +327,8 @@ def is_list_interior(content): def stylebox(box: StyleBox, **options) -> str: - return lookup_conversion_method(box.boxes, "mathml")(box.boxes, **options) + child_options = {**options, **box.box_options} + return lookup_conversion_method(box.boxes, "mathml")(box.boxes, **child_options) add_conversion_fn(StyleBox, stylebox) From dc4542dd9fd8891a949eccc93f22dffde4c339b2 Mon Sep 17 00:00:00 2001 From: rocky Date: Wed, 4 Feb 2026 19:34:26 -0500 Subject: [PATCH 3/3] Update module docstring comment. --- mathics/format/render/mathml.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mathics/format/render/mathml.py b/mathics/format/render/mathml.py index 3e959974e..c1ff6733c 100644 --- a/mathics/format/render/mathml.py +++ b/mathics/format/render/mathml.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ -Mathics3 Graphics3D box rendering to MathML strings. +Mathics3 Box rendering to MathML strings. MathML rendering is usually initiated via MathMLForm[]. """