From 45c302b6c929b2d698b25186a27f99d2f12d837c Mon Sep 17 00:00:00 2001 From: Juan Mauricio Matera Date: Thu, 4 Dec 2025 10:09:58 -0300 Subject: [PATCH 01/15] adding `evaluate_without_side_effects` for helping compile expressions. --- mathics/builtin/assignments/assignment.py | 5 ++-- mathics/builtin/attributes.py | 5 +++- mathics/builtin/procedural.py | 14 +++++++---- mathics/builtin/scoping.py | 12 ++++++---- mathics/core/builtin.py | 13 ++++++++++ mathics/core/convert/function.py | 29 +++++++++++++++++++++++ mathics/core/definitions.py | 6 +++++ mathics/eval/drawing/plot_compile.py | 3 ++- 8 files changed, 73 insertions(+), 14 deletions(-) diff --git a/mathics/builtin/assignments/assignment.py b/mathics/builtin/assignments/assignment.py index cc85e83ca..f7aaae725 100644 --- a/mathics/builtin/assignments/assignment.py +++ b/mathics/builtin/assignments/assignment.py @@ -134,7 +134,7 @@ class Set(InfixOperator): "setraw": "Cannot assign to raw object `1`.", "shape": "Lists `1` and `2` are not the same shape.", } - + has_side_effects = True summary_text = "assign a value" def eval(self, lhs, rhs, evaluation): @@ -258,7 +258,7 @@ class TagSet(Builtin): """ attributes = A_HOLD_ALL | A_PROTECTED | A_SEQUENCE_HOLD - + has_side_effects = True messages = { "tagnfd": "Tag `1` not found or too deep for an assigned rule.", } @@ -353,6 +353,7 @@ class UpSet(InfixOperator): """ attributes = A_HOLD_FIRST | A_PROTECTED | A_SEQUENCE_HOLD + has_side_effects = True grouping = "Right" summary_text = ( diff --git a/mathics/builtin/attributes.py b/mathics/builtin/attributes.py index a4dc27382..2bdfc40d3 100644 --- a/mathics/builtin/attributes.py +++ b/mathics/builtin/attributes.py @@ -126,6 +126,7 @@ class ClearAttributes(Builtin): """ attributes = A_HOLD_FIRST | A_PROTECTED + has_side_effects = True summary_text = "clear the attributes of a symbol" def eval(self, symbols, attributes, evaluation): @@ -526,6 +527,7 @@ class Protect(Builtin): """ attributes = A_HOLD_ALL | A_PROTECTED + has_side_effects = True summary_text = "protect a symbol against redefinitions" def eval(self, symbols, evaluation): @@ -696,7 +698,7 @@ class SetAttributes(Builtin): """ attributes = A_HOLD_FIRST | A_PROTECTED - + has_side_effects = True messages = { "unknownattr": f"`1` should be one of {', '.join(attribute_string_to_number.keys())}" } @@ -752,6 +754,7 @@ class Unprotect(Builtin): """ attributes = A_HOLD_ALL | A_PROTECTED + has_side_effects = True summary_text = "remove protection against redefinitions" def eval(self, symbols, evaluation): diff --git a/mathics/builtin/procedural.py b/mathics/builtin/procedural.py index 6d4841c88..4d0efefcf 100644 --- a/mathics/builtin/procedural.py +++ b/mathics/builtin/procedural.py @@ -219,7 +219,7 @@ class CompoundExpression(InfixOperator): """ attributes = A_HOLD_ALL | A_PROTECTED | A_READ_PROTECTED - + has_side_effects = True summary_text = "execute expressions in sequence" def eval(self, expr, evaluation): @@ -346,6 +346,7 @@ class For(Builtin): """ attributes = A_HOLD_REST | A_PROTECTED + has_side_effects = True rules = { "For[start_, test_, incr_]": "For[start, test, incr, Null]", } @@ -486,6 +487,7 @@ class Interrupt(Builtin): | a = $Aborted """ + has_side_effects = True # Set checking that the no arguments are allowed. # eval_error = Builtin.generic_argument_error @@ -511,6 +513,7 @@ class Pause(Builtin): >> Pause[0.5] """ + has_side_effects = True messages = { "numnm": ( "Non-negative machine-sized number expected at " "position 1 in `1`." @@ -563,7 +566,7 @@ class Return(Builtin): rules = { "Return[]": "Return[Null]", } - + has_side_effects = True summary_text = "return from a function" def eval(self, expr, evaluation: Evaluation): # pylint: disable=unused-argument @@ -604,7 +607,7 @@ class Switch(Builtin): summary_text = "switch based on a value, with patterns allowed" attributes = A_HOLD_REST | A_PROTECTED - + has_side_effects = True messages = { "argct": ( "Switch called with `2` arguments. " @@ -659,7 +662,7 @@ class Throw(Builtin): # Set checking that the number of arguments required is one or two. WMA uses 1..3. eval_error = Builtin.generic_argument_error expected_args = (1, 2) - + has_side_effects = True messages = { "nocatch": "Uncaught `1` returned to top level.", } @@ -714,6 +717,7 @@ class Which(SympyFunction): """ attributes = A_HOLD_ALL | A_PROTECTED + has_side_effects = True summary_text = "test which of a sequence of conditions are true" def eval(self, items, evaluation): @@ -773,7 +777,7 @@ class While(Builtin): # Set checking that the number of arguments required is one. eval_error = Builtin.generic_argument_error expected_args = (1, 2) - + has_side_effects = True rules = { "While[test_]": "While[test, Null]", } diff --git a/mathics/builtin/scoping.py b/mathics/builtin/scoping.py index 6063788ca..2d7202a5f 100644 --- a/mathics/builtin/scoping.py +++ b/mathics/builtin/scoping.py @@ -99,6 +99,7 @@ class Begin(Builtin): ## = Global`test` """ + has_side_effects = True rules = { "Begin[context_String]": """ Unprotect[System`Private`$ContextStack]; @@ -128,7 +129,7 @@ class BeginPackage(Builtin): ## >> BeginPackage["test`"] ## = test` """ - + has_side_effects = True messages = {"unimpl": "The second argument to BeginPackage is not yet implemented."} rules = { @@ -187,7 +188,7 @@ class Block(Builtin): """ attributes = A_HOLD_ALL | A_PROTECTED - + has_side_effects = True messages = { "lvsym": ( "Local variable specification contains `1`, " @@ -351,6 +352,7 @@ class End(Builtin): """ + has_side_effects = True messages = { "noctx": "No previous context defined.", } @@ -385,7 +387,7 @@ class EndPackage(Builtin): After 'EndPackage', the values of '\$Context' and '\$ContextPath' at the \ time of the 'BeginPackage' call are restored, with the new package\'s context prepended to '\$ContextPath'. """ - + has_side_effects = True messages = { "noctx": "No previous context defined.", } @@ -450,7 +452,7 @@ class Module(Builtin): """ attributes = A_HOLD_ALL | A_PROTECTED - + has_side_effects = True messages = { "lvsym": ( "Local variable specification contains `1`, " @@ -710,7 +712,7 @@ class With(Builtin): """ attributes = A_HOLD_ALL | A_PROTECTED - + has_side_effects = True messages = { "lvsym": ( "Local variable specification contains `1`, " diff --git a/mathics/core/builtin.py b/mathics/core/builtin.py index f91e4ea76..ad371d499 100644 --- a/mathics/core/builtin.py +++ b/mathics/core/builtin.py @@ -207,6 +207,11 @@ def eval_with_options(x, evaluation: Evaluation, options: dict): expected_args: Union[int, Tuple[int, int], range] = -1 formats: Dict[str, Any] = {} + + # If the symbol include rules involving loops, + # setting values, or creating/changing contexts. + has_side_effects: bool = False + messages: Dict[str, Any] = {} name: Optional[str] = None options: Dict[str, Any] = {} @@ -434,6 +439,13 @@ def contextify_form_name(f): else: definitions.builtin[name] = definition + # If the definition has side effects, store it in a + # dictionary. + if self.has_side_effects: + from mathics.core.definitions import SIDE_EFFECT_BUILTINS + + SIDE_EFFECT_BUILTINS[name] = definition + makeboxes_def = definitions.builtin["System`MakeBoxes"] for rule in box_rules: makeboxes_def.add_rule(rule) @@ -1024,6 +1036,7 @@ def get_name(cls, short=False) -> str: class IterationFunction(Builtin, ABC): attributes = A_HOLD_ALL | A_PROTECTED allow_loopcontrol = False + has_side_effects = True throw_iterb = True def get_result(self, elements, is_uniform=False) -> Expression: diff --git a/mathics/core/convert/function.py b/mathics/core/convert/function.py index 0250b04c6..62f0b4e0a 100644 --- a/mathics/core/convert/function.py +++ b/mathics/core/convert/function.py @@ -2,6 +2,8 @@ from typing import Callable, Optional, Tuple +from mathics.core.definitions import SIDE_EFFECT_BUILTINS, Definition +from mathics.core.element import BaseElement from mathics.core.evaluation import Evaluation from mathics.core.expression import Expression, from_python from mathics.core.symbols import Symbol, SymbolFalse, SymbolTrue @@ -44,6 +46,32 @@ def __init__(self, var): self.var = var +def evaluate_without_side_effects( + expr: BaseElement, evaluation: Evaluation +) -> BaseElement: + """ + Evaluate an expression leaving unevaluated subexpressions + related with side-effects (assignments, loops). + """ + definitions = evaluation.definitions + # Temporarily remove the builtin definitions + # of symbols with side effects + for name, defin in SIDE_EFFECT_BUILTINS.items(): + # Change the definition by a temporal definition setting + # just the name and the attributes. + definitions.builtin[name] = Definition( + name, attributes=defin.attributes, builtin=defin.builtin + ) + definitions.clear_cache(name) + try: + result = expr.evaluate(evaluation) + finally: + # Restore the definitions + for name, defin in SIDE_EFFECT_BUILTINS.items(): + definitions.builtin[name] = defin + return result + + def expression_to_callable( expr: Expression, args: Optional[list] = None, @@ -56,6 +84,7 @@ def expression_to_callable( args: a list of CompileArg elements evaluation: an Evaluation object used if the llvm compilation fails """ + expr = evaluate_without_side_effects(expr, evaluation) try: cfunc = _compile(expr, args) if (use_llvm and args is not None) else None except CompileError: diff --git a/mathics/core/definitions.py b/mathics/core/definitions.py index b66f6e735..87f0bdeb9 100644 --- a/mathics/core/definitions.py +++ b/mathics/core/definitions.py @@ -121,6 +121,12 @@ def __repr__(self) -> str: return repr_str +# Dictionary of builtin definitions involving side effects +# like setting values, changing contexts or running loops: + +SIDE_EFFECT_BUILTINS: Dict[str, Definition] = {} + + class Definitions: """The state of one instance of the Mathics3 interpreter is stored in this object. diff --git a/mathics/eval/drawing/plot_compile.py b/mathics/eval/drawing/plot_compile.py index 1cfaf2066..09f2a6c62 100644 --- a/mathics/eval/drawing/plot_compile.py +++ b/mathics/eval/drawing/plot_compile.py @@ -18,6 +18,7 @@ import scipy import sympy +from mathics.core.convert.function import evaluate_without_side_effects from mathics.core.convert.sympy import SympyExpression from mathics.core.symbols import strip_context from mathics.core.util import print_expression_tree, print_sympy_tree @@ -54,7 +55,7 @@ def plot_compile(evaluation, expr, names, debug=0): # because some functions are not themselves sympy-enabled # if they always get rewritten to one that is. try: - new_expr = expr.evaluate(evaluation) + new_expr = eval_without_side_effects(expr, evaluation) if new_expr: expr = new_expr except Exception: From 36837e4cdf71b74ed281530012f7139fac0a3d20 Mon Sep 17 00:00:00 2001 From: Juan Mauricio Matera Date: Thu, 4 Dec 2025 11:02:16 -0300 Subject: [PATCH 02/15] mypy fix. typo in function call. remove has_side_effects for `Which` --- mathics/builtin/procedural.py | 1 - mathics/core/convert/function.py | 11 ++++++----- mathics/eval/drawing/plot_compile.py | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mathics/builtin/procedural.py b/mathics/builtin/procedural.py index 4d0efefcf..fc0e6e712 100644 --- a/mathics/builtin/procedural.py +++ b/mathics/builtin/procedural.py @@ -717,7 +717,6 @@ class Which(SympyFunction): """ attributes = A_HOLD_ALL | A_PROTECTED - has_side_effects = True summary_text = "test which of a sequence of conditions are true" def eval(self, items, evaluation): diff --git a/mathics/core/convert/function.py b/mathics/core/convert/function.py index 62f0b4e0a..94887381b 100644 --- a/mathics/core/convert/function.py +++ b/mathics/core/convert/function.py @@ -3,7 +3,7 @@ from typing import Callable, Optional, Tuple from mathics.core.definitions import SIDE_EFFECT_BUILTINS, Definition -from mathics.core.element import BaseElement +from mathics.core.element import BaseElement, EvalMixin from mathics.core.evaluation import Evaluation from mathics.core.expression import Expression, from_python from mathics.core.symbols import Symbol, SymbolFalse, SymbolTrue @@ -47,8 +47,8 @@ def __init__(self, var): def evaluate_without_side_effects( - expr: BaseElement, evaluation: Evaluation -) -> BaseElement: + expr: Expression, evaluation: Evaluation +) -> Expression: """ Evaluate an expression leaving unevaluated subexpressions related with side-effects (assignments, loops). @@ -69,7 +69,7 @@ def evaluate_without_side_effects( # Restore the definitions for name, defin in SIDE_EFFECT_BUILTINS.items(): definitions.builtin[name] = defin - return result + return result if result is not None else expr def expression_to_callable( @@ -84,7 +84,8 @@ def expression_to_callable( args: a list of CompileArg elements evaluation: an Evaluation object used if the llvm compilation fails """ - expr = evaluate_without_side_effects(expr, evaluation) + if evaluation is not None: + expr = evaluate_without_side_effects(expr, evaluation) try: cfunc = _compile(expr, args) if (use_llvm and args is not None) else None except CompileError: diff --git a/mathics/eval/drawing/plot_compile.py b/mathics/eval/drawing/plot_compile.py index 09f2a6c62..2eac8d579 100644 --- a/mathics/eval/drawing/plot_compile.py +++ b/mathics/eval/drawing/plot_compile.py @@ -55,7 +55,7 @@ def plot_compile(evaluation, expr, names, debug=0): # because some functions are not themselves sympy-enabled # if they always get rewritten to one that is. try: - new_expr = eval_without_side_effects(expr, evaluation) + new_expr = evaluate_without_side_effects(expr, evaluation) if new_expr: expr = new_expr except Exception: From 969a2322aea91e7c6d8f796697a775017c8166e2 Mon Sep 17 00:00:00 2001 From: Juan Mauricio Matera Date: Thu, 4 Dec 2025 11:49:16 -0300 Subject: [PATCH 03/15] improve implementation of pythonized code. Fix test case --- mathics/builtin/compilation.py | 4 ++-- mathics/core/convert/function.py | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/mathics/builtin/compilation.py b/mathics/builtin/compilation.py index 09b56fa3e..fbf3ed20b 100644 --- a/mathics/builtin/compilation.py +++ b/mathics/builtin/compilation.py @@ -65,9 +65,9 @@ class Compile(Builtin): >> cf[3.5, 2] = 2.18888 - Loops and variable assignments are supported usinv Python builtin "compile" function: + Loops and variable assignments are supported using Python builtin "compile" function: >> Compile[{{a, _Integer}, {b, _Integer}}, While[b != 0, {a, b} = {b, Mod[a, b]}]; a] (* GCD of a, b *) - = CompiledFunction[{a, b}, a, -PythonizedCode-] + = CompiledFunction[{a, b}, While[b != 0, {a, b} = {b, Mod[a, b]}] ; a, -PythonizedCode-] """ attributes = A_HOLD_ALL | A_PROTECTED diff --git a/mathics/core/convert/function.py b/mathics/core/convert/function.py index 94887381b..09e9e9e4c 100644 --- a/mathics/core/convert/function.py +++ b/mathics/core/convert/function.py @@ -69,6 +69,7 @@ def evaluate_without_side_effects( # Restore the definitions for name, defin in SIDE_EFFECT_BUILTINS.items(): definitions.builtin[name] = defin + definitions.clear_cache(name) return result if result is not None else expr @@ -86,6 +87,7 @@ def expression_to_callable( """ if evaluation is not None: expr = evaluate_without_side_effects(expr, evaluation) + try: cfunc = _compile(expr, args) if (use_llvm and args is not None) else None except CompileError: @@ -97,11 +99,11 @@ def expression_to_callable( try: def _pythonized_mathics_expr(*x): - inner_evaluation = Evaluation(definitions=evaluation.definitions) - x_mathics = (from_python(u) for u in x[: len(args)]) - vars = dict(list(zip([a.name for a in args], x_mathics))) - pyexpr = expr.replace_vars(vars) - pyexpr = eval_N(pyexpr, inner_evaluation) + from mathics.eval.scoping import dynamic_scoping + + vars = {a.name: from_python(u) for a, u in zip(args, x[: len(args)])} + pyexpr = dynamic_scoping(lambda ev: expr.evaluate(ev), vars, evaluation) + pyexpr = eval_N(pyexpr, evaluation) res = pyexpr.to_python() return res From abe1bbd31532c15fb22e1a03fb9e57380f93356c Mon Sep 17 00:00:00 2001 From: Juan Mauricio Matera Date: Thu, 4 Dec 2025 13:21:47 -0300 Subject: [PATCH 04/15] improve doctest. use a fresh evaluation object for the compiled function --- mathics/builtin/compilation.py | 32 ++++++++++++++++++++++++++++---- mathics/core/convert/function.py | 7 +++++-- mathics/eval/scoping.py | 1 + 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/mathics/builtin/compilation.py b/mathics/builtin/compilation.py index fbf3ed20b..df342e24f 100644 --- a/mathics/builtin/compilation.py +++ b/mathics/builtin/compilation.py @@ -12,7 +12,12 @@ from mathics.builtin.box.compilation import CompiledCodeBox from mathics.core.atoms import Integer, String -from mathics.core.attributes import A_HOLD_ALL, A_PROTECTED +from mathics.core.attributes import ( + A_HOLD_ALL, + A_N_HOLD_ALL, + A_PROTECTED, + A_READ_PROTECTED, +) from mathics.core.builtin import Builtin from mathics.core.convert.expression import to_mathics_list from mathics.core.convert.function import ( @@ -66,8 +71,10 @@ class Compile(Builtin): = 2.18888 Loops and variable assignments are supported using Python builtin "compile" function: - >> Compile[{{a, _Integer}, {b, _Integer}}, While[b != 0, {a, b} = {b, Mod[a, b]}]; a] (* GCD of a, b *) - = CompiledFunction[{a, b}, While[b != 0, {a, b} = {b, Mod[a, b]}] ; a, -PythonizedCode-] + >> gdc = Compile[{{a, _Integer}, {b, _Integer}}, Module[{x=a, y=b}, While[y != 0, {x, y} = {y, Mod[x, y]}]; x]] (* GCD of a, b *) + = CompiledFunction[{a, b}, Module[{x = a, y = b}, While[y != 0, {x, y} = {y, Mod[x, y]}] ; x], -PythonizedCode-] + >> gdc[18, 81] + = 9. """ attributes = A_HOLD_ALL | A_PROTECTED @@ -167,7 +174,23 @@ def to_sympy(self, *args, **kwargs): raise NotImplementedError def __hash__(self): - return hash(("CompiledCode", ctypes.addressof(self.cfunc))) # XXX hack + cfunc = self.cfunc + if cfunc is None: + hash( + ( + "CompiledCode", + None, + ) + ) # XXX hack + try: + return hash(("CompiledCode", ctypes.addressof(cfunc))) # XXX hack + except TypeError: + return hash( + ( + "Pythonized-function", + cfunc, + ) + ) def atom_to_boxes(self, f, evaluation: Evaluation): return CompiledCodeBox(String(self.__str__()), evaluation=evaluation) @@ -191,6 +214,7 @@ class CompiledFunction(Builtin): """ + attributes = A_HOLD_ALL | A_PROTECTED | A_N_HOLD_ALL | A_READ_PROTECTED messages = {"argerr": "Invalid argument `1` should be Integer, Real or boolean."} summary_text = "A CompiledFunction object." diff --git a/mathics/core/convert/function.py b/mathics/core/convert/function.py index 09e9e9e4c..de282d2f2 100644 --- a/mathics/core/convert/function.py +++ b/mathics/core/convert/function.py @@ -101,9 +101,12 @@ def expression_to_callable( def _pythonized_mathics_expr(*x): from mathics.eval.scoping import dynamic_scoping + inner_evaluation = Evaluation(definitions=evaluation.definitions) vars = {a.name: from_python(u) for a, u in zip(args, x[: len(args)])} - pyexpr = dynamic_scoping(lambda ev: expr.evaluate(ev), vars, evaluation) - pyexpr = eval_N(pyexpr, evaluation) + pyexpr = dynamic_scoping( + lambda ev: expr.evaluate(ev), vars, inner_evaluation + ) + pyexpr = eval_N(pyexpr, inner_evaluation) res = pyexpr.to_python() return res diff --git a/mathics/eval/scoping.py b/mathics/eval/scoping.py index 6579c24de..eba2bb63b 100644 --- a/mathics/eval/scoping.py +++ b/mathics/eval/scoping.py @@ -16,6 +16,7 @@ def dynamic_scoping(func, vars, evaluation: Evaluation): and evaluates func(evaluation) """ original_definitions = {} + for var_name, new_def in vars.items(): assert fully_qualified_symbol_name(var_name) original_definitions[var_name] = evaluation.definitions.get_user_definition( From 66c6c6a4463e83162c1447f2ba8dbdcabf6998ef Mon Sep 17 00:00:00 2001 From: Juan Mauricio Matera Date: Thu, 4 Dec 2025 13:35:23 -0300 Subject: [PATCH 05/15] another fix on doctests --- mathics/builtin/compilation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mathics/builtin/compilation.py b/mathics/builtin/compilation.py index df342e24f..1bd493f2e 100644 --- a/mathics/builtin/compilation.py +++ b/mathics/builtin/compilation.py @@ -206,7 +206,7 @@ class CompiledFunction(Builtin): >> sqr = Compile[{x}, x x] - = CompiledFunction[{x}, x ^ 2, ...] + = CompiledFunction[{x}, x x, ...] >> Head[sqr] = CompiledFunction >> sqr[2] From d4696d01064847b3e5bdbf83da7b7da1568f1bcc Mon Sep 17 00:00:00 2001 From: Juan Mauricio Matera Date: Sun, 14 Dec 2025 01:02:36 -0300 Subject: [PATCH 06/15] add test --- test/core/convert/test_function.py | 32 ++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 test/core/convert/test_function.py diff --git a/test/core/convert/test_function.py b/test/core/convert/test_function.py new file mode 100644 index 000000000..6c9f7d6bd --- /dev/null +++ b/test/core/convert/test_function.py @@ -0,0 +1,32 @@ +""" +Conversion from expressions to functions +""" + +from test.helper import check_evaluation, session + +from mathics.core.convert.function import evaluate_without_side_effects + + +def test_evaluate_without_side_effects(): + session.reset() + session.evaluate( + """ + F[x_]:=G[x]; + G[x_]:=(a=2^2*x;Do[a=x+2^2,{3}];a); + Q[x_]:=(a=2^2*x); + """ + ) + expr = session.parse("F[x]") + # Notice that since `CompoundExpression` has the attribute "HoldAll", + # subelements are not evaluated (`2^2`->`2^2`) + expect = session.parse("(a=2^2*x; Do[a=x+2^2,{3}];a)") + result = evaluate_without_side_effects(expr, session.evaluation) + assert result.sameQ(expect) + + expr = session.parse("Q[x]") + # If the head of the expression does not have the attribute "HoldAll", + # subelements are evaluated (`2^2`->`4`) + expect = session.parse("a=4*x") + result = evaluate_without_side_effects(expr, session.evaluation) + + assert result.sameQ(expect) From 0102928b2aee8d0de3818a839c84990cba78857a Mon Sep 17 00:00:00 2001 From: Juan Mauricio Matera Date: Sun, 14 Dec 2025 22:37:56 -0300 Subject: [PATCH 07/15] black --- mathics/core/convert/function.py | 3 ++- mathics/core/convert/lambdify.py | 8 ++++---- mathics/core/definitions.py | 2 +- test/core/convert/test_function.py | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/mathics/core/convert/function.py b/mathics/core/convert/function.py index 34e988740..42668f2f0 100644 --- a/mathics/core/convert/function.py +++ b/mathics/core/convert/function.py @@ -5,7 +5,6 @@ from mathics.core.definitions import SIDE_EFFECT_BUILTINS, Definition -from mathics.core.element import BaseElement, EvalMixin from mathics.core.evaluation import Evaluation from mathics.core.expression import Expression, from_python from mathics.core.symbols import Symbol, SymbolFalse, SymbolTrue @@ -193,6 +192,8 @@ def expression_to_callable_and_args( expr: A Mathics Expression object vars: a list of Symbols or Mathics Lists of the form {Symbol, Type} """ + from mathics.core.convert.lambdify import LambdifyCompileError, lambdify_compile + args = collect_args(vars) # If vectorize is requested, first, try to lambdify the expression: diff --git a/mathics/core/convert/lambdify.py b/mathics/core/convert/lambdify.py index 9a633a15e..8b6c27284 100644 --- a/mathics/core/convert/lambdify.py +++ b/mathics/core/convert/lambdify.py @@ -42,7 +42,7 @@ def hyppfq(p, q, x): # mappings = [dict(AdditionalMappings.__dict__), "numpy"] -class CompileError(Exception): +class LambdifyCompileError(Exception): pass @@ -85,9 +85,9 @@ def lambdify_compile(evaluation, expr, names, debug=0): print("post-eval", expr) # Ask the expr Expression to generate a sympy expression and handle errors - sympy_expr = expr.to_sympy(raise_on_error=CompileError) + sympy_expr = expr.to_sympy(raise_on_error=LambdifyCompileError) if isinstance(sympy_expr, SympyExpression): - raise CompileError(f"{expr.head}.to_sympy returns invalid sympy expr.") + raise LambdifyCompileError(f"{expr.head}.to_sympy returns invalid sympy expr.") # Strip symbols in sympy expression of context. subs = { @@ -110,7 +110,7 @@ def lambdify_compile(evaluation, expr, names, debug=0): symbols, sympy_expr, modules=["numpy", "scipy"] ) except Exception as oops: - raise CompileError(f"error compiling sympy expr {sympy_expr}: {oops}") + raise LambdifyCompileError(f"error compiling sympy expr {sympy_expr}: {oops}") if debug >= 2: print("=== compiled python") diff --git a/mathics/core/definitions.py b/mathics/core/definitions.py index 87f0bdeb9..413e80d98 100644 --- a/mathics/core/definitions.py +++ b/mathics/core/definitions.py @@ -1099,7 +1099,7 @@ def load_builtin_definitions( mathics3_builtins_modules, ) from mathics.eval.files_io.files import get_file_time - from mathics.eval.pymathics import PyMathicsLoadException, load_pymathics_module + from mathics.eval.pymathics import load_pymathics_module from mathics.session import autoload_files loaded = False diff --git a/test/core/convert/test_function.py b/test/core/convert/test_function.py index 6c9f7d6bd..37a9df658 100644 --- a/test/core/convert/test_function.py +++ b/test/core/convert/test_function.py @@ -2,7 +2,7 @@ Conversion from expressions to functions """ -from test.helper import check_evaluation, session +from test.helper import session from mathics.core.convert.function import evaluate_without_side_effects From 64d7790a51fa7797185589b0027ed3321a5ddbba Mon Sep 17 00:00:00 2001 From: Juan Mauricio Matera Date: Sun, 14 Dec 2025 23:01:04 -0300 Subject: [PATCH 08/15] merge --- mathics/core/convert/function.py | 9 ++++++--- mathics/core/convert/lambdify.py | 8 ++++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/mathics/core/convert/function.py b/mathics/core/convert/function.py index 42668f2f0..d75b3e301 100644 --- a/mathics/core/convert/function.py +++ b/mathics/core/convert/function.py @@ -78,7 +78,7 @@ def evaluate_without_side_effects( return result if result is not None else expr -def expression_to_callable( +def expression_to_llvm( expr: Expression, args: Optional[list] = None, evaluation: Optional[Evaluation] = None, @@ -192,7 +192,10 @@ def expression_to_callable_and_args( expr: A Mathics Expression object vars: a list of Symbols or Mathics Lists of the form {Symbol, Type} """ - from mathics.core.convert.lambdify import LambdifyCompileError, lambdify_compile + from mathics.core.convert.lambdify import ( + CompileError as LambdifyCompileError, + lambdify_compile, + ) args = collect_args(vars) @@ -222,7 +225,7 @@ def expression_to_callable_and_args( for compile_arg in args ] ) - cfunc = expression_to_callable(expr, llvm_args, evaluation) + cfunc = expression_to_llvm(expr, llvm_args, evaluation) if cfunc is not None: if vectorize: cfunc = numpy.vectorize(cfunc) diff --git a/mathics/core/convert/lambdify.py b/mathics/core/convert/lambdify.py index 8b6c27284..9a633a15e 100644 --- a/mathics/core/convert/lambdify.py +++ b/mathics/core/convert/lambdify.py @@ -42,7 +42,7 @@ def hyppfq(p, q, x): # mappings = [dict(AdditionalMappings.__dict__), "numpy"] -class LambdifyCompileError(Exception): +class CompileError(Exception): pass @@ -85,9 +85,9 @@ def lambdify_compile(evaluation, expr, names, debug=0): print("post-eval", expr) # Ask the expr Expression to generate a sympy expression and handle errors - sympy_expr = expr.to_sympy(raise_on_error=LambdifyCompileError) + sympy_expr = expr.to_sympy(raise_on_error=CompileError) if isinstance(sympy_expr, SympyExpression): - raise LambdifyCompileError(f"{expr.head}.to_sympy returns invalid sympy expr.") + raise CompileError(f"{expr.head}.to_sympy returns invalid sympy expr.") # Strip symbols in sympy expression of context. subs = { @@ -110,7 +110,7 @@ def lambdify_compile(evaluation, expr, names, debug=0): symbols, sympy_expr, modules=["numpy", "scipy"] ) except Exception as oops: - raise LambdifyCompileError(f"error compiling sympy expr {sympy_expr}: {oops}") + raise CompileError(f"error compiling sympy expr {sympy_expr}: {oops}") if debug >= 2: print("=== compiled python") From 8f50b4e33af05d64fe8c1823a795bee4ab30f0d0 Mon Sep 17 00:00:00 2001 From: Juan Mauricio Matera Date: Mon, 15 Dec 2025 00:03:34 -0300 Subject: [PATCH 09/15] black --- mathics/builtin/box/__init__.py | 1 + mathics/builtin/compilation.py | 2 -- mathics/builtin/directories/__init__.py | 1 + mathics/builtin/drawing/graphics3d.py | 9 ++++----- mathics/builtin/exp_structure/size_and_sig.py | 1 + mathics/builtin/file_operations/__init__.py | 1 + mathics/builtin/files_io/__init__.py | 1 + mathics/builtin/image/base.py | 1 + mathics/builtin/image/composition.py | 1 + mathics/builtin/image/pixel.py | 1 + mathics/builtin/image/structure.py | 1 + mathics/builtin/image/test.py | 1 + mathics/builtin/list/math.py | 1 + mathics/builtin/procedural.py | 1 + mathics/builtin/scoping.py | 2 ++ mathics/builtin/specialfns/orthogonal.py | 1 - mathics/builtin/statistics/base.py | 1 + mathics/builtin/string/__init__.py | 1 + mathics/builtin/string/patterns.py | 3 +++ mathics/builtin/symbolic_history/__init__.py | 1 + mathics/builtin/testing_expressions/expression_tests.py | 1 + .../builtin/testing_expressions/numerical_properties.py | 1 + mathics/core/convert/function.py | 2 +- mathics/core/convert/regex.py | 1 + 24 files changed, 28 insertions(+), 9 deletions(-) diff --git a/mathics/builtin/box/__init__.py b/mathics/builtin/box/__init__.py index 5d2777e44..8275c12be 100644 --- a/mathics/builtin/box/__init__.py +++ b/mathics/builtin/box/__init__.py @@ -6,5 +6,6 @@ Boxing information like bounding-box width and size makes it easier for formatters to do layout without having to know the intricacies of what is inside the box. """ + # Docs are not yet ready for prime time. Maybe after release 6.0.0. no_doc = True diff --git a/mathics/builtin/compilation.py b/mathics/builtin/compilation.py index d21b56b39..1d7b4255c 100644 --- a/mathics/builtin/compilation.py +++ b/mathics/builtin/compilation.py @@ -200,7 +200,6 @@ def __hash__(self): ) ) - def atom_to_boxes(self, f, evaluation: Evaluation): return CompiledCodeBox(String(self.__str__()), evaluation=evaluation) @@ -223,7 +222,6 @@ class CompiledFunction(Builtin): """ - attributes = A_HOLD_ALL | A_PROTECTED | A_N_HOLD_ALL | A_READ_PROTECTED messages = { "argerr": "Invalid argument `1` should be Integer, Real, Complex or boolean.", diff --git a/mathics/builtin/directories/__init__.py b/mathics/builtin/directories/__init__.py index b7bf1f9e4..a17fc9441 100644 --- a/mathics/builtin/directories/__init__.py +++ b/mathics/builtin/directories/__init__.py @@ -1,6 +1,7 @@ """ Directories and Directory Operations """ + # Note: everything in this module is not loaded if environment # variable ENABLE_FILES_MODULE is False. Here we do not want to # include any built-in commands that can write to the filesytesm. diff --git a/mathics/builtin/drawing/graphics3d.py b/mathics/builtin/drawing/graphics3d.py index 5caa0b1c3..52daa2dc3 100644 --- a/mathics/builtin/drawing/graphics3d.py +++ b/mathics/builtin/drawing/graphics3d.py @@ -107,6 +107,7 @@ class Graphics3D(Graphics): . draw(((1,1,-1)--(1,1,1)), rgb(0.4, 0.4, 0.4)+linewidth(1)); . \end{asy} """ + summary_text = "a three-dimensional graphics image wrapper" options = Graphics.options.copy() options.update( @@ -172,11 +173,9 @@ class Graphics3DElements(_GraphicsElements): def __init__(self, content, evaluation, neg_y=False): super(Graphics3DElements, self).__init__(content, evaluation) self.neg_y = neg_y - self.xmin = ( - self.ymin - ) = ( - self.pixel_width - ) = self.pixel_height = self.extent_width = self.extent_height = None + self.xmin = self.ymin = self.pixel_width = self.pixel_height = ( + self.extent_width + ) = self.extent_height = None self.view_width = None self.content = content diff --git a/mathics/builtin/exp_structure/size_and_sig.py b/mathics/builtin/exp_structure/size_and_sig.py index b06cede7f..075499752 100644 --- a/mathics/builtin/exp_structure/size_and_sig.py +++ b/mathics/builtin/exp_structure/size_and_sig.py @@ -1,6 +1,7 @@ """ Expression Sizes and Signatures """ + import hashlib import platform import zlib diff --git a/mathics/builtin/file_operations/__init__.py b/mathics/builtin/file_operations/__init__.py index c69d15343..5d05c229f 100644 --- a/mathics/builtin/file_operations/__init__.py +++ b/mathics/builtin/file_operations/__init__.py @@ -1,6 +1,7 @@ """ File Operations """ + # Note: everything in this module is not loaded if environment # variable ENABLE_FILES_MODULE is False. Here we do not want to # include any built-in commands that can write to the filesytesm. diff --git a/mathics/builtin/files_io/__init__.py b/mathics/builtin/files_io/__init__.py index 82b851411..c06a44c84 100644 --- a/mathics/builtin/files_io/__init__.py +++ b/mathics/builtin/files_io/__init__.py @@ -2,6 +2,7 @@ Input/Output, Files, and Filesystem """ + # Note: everything in this module is not loaded if environment # variable ENABLE_FILES_MODULE is False. Here we do not want to # include any built-in commands that can write to the filesystem. diff --git a/mathics/builtin/image/base.py b/mathics/builtin/image/base.py index 2d8ce7756..6274f7e27 100644 --- a/mathics/builtin/image/base.py +++ b/mathics/builtin/image/base.py @@ -1,6 +1,7 @@ """ Base classes for Image Manipulation """ + from typing import Tuple import numpy diff --git a/mathics/builtin/image/composition.py b/mathics/builtin/image/composition.py index b5051425e..7aedb542f 100644 --- a/mathics/builtin/image/composition.py +++ b/mathics/builtin/image/composition.py @@ -1,6 +1,7 @@ """ Image Compositions """ + import os.path as osp from collections import defaultdict diff --git a/mathics/builtin/image/pixel.py b/mathics/builtin/image/pixel.py index b7b58573b..1fdd330fa 100644 --- a/mathics/builtin/image/pixel.py +++ b/mathics/builtin/image/pixel.py @@ -1,6 +1,7 @@ """ Pixel Operations """ + import numpy from mathics.builtin.image.base import Image diff --git a/mathics/builtin/image/structure.py b/mathics/builtin/image/structure.py index 95cd65548..fe9faaa91 100644 --- a/mathics/builtin/image/structure.py +++ b/mathics/builtin/image/structure.py @@ -1,6 +1,7 @@ """ Operations on Image Structure """ + import numpy from mathics.builtin.image.base import Image diff --git a/mathics/builtin/image/test.py b/mathics/builtin/image/test.py index 62945df64..f5b60d53d 100644 --- a/mathics/builtin/image/test.py +++ b/mathics/builtin/image/test.py @@ -1,6 +1,7 @@ """ Image testing """ + from mathics.builtin.image.base import Image, skimage_requires from mathics.core.builtin import Test diff --git a/mathics/builtin/list/math.py b/mathics/builtin/list/math.py index 8f1d84c10..b6a27a711 100644 --- a/mathics/builtin/list/math.py +++ b/mathics/builtin/list/math.py @@ -1,6 +1,7 @@ """ Math & Counting Operations on Lists """ + import heapq from mathics.core.builtin import Builtin, CountableInteger, NegativeIntegerException diff --git a/mathics/builtin/procedural.py b/mathics/builtin/procedural.py index fc0e6e712..be420bfbd 100644 --- a/mathics/builtin/procedural.py +++ b/mathics/builtin/procedural.py @@ -487,6 +487,7 @@ class Interrupt(Builtin): | a = $Aborted """ + has_side_effects = True # Set checking that the no arguments are allowed. diff --git a/mathics/builtin/scoping.py b/mathics/builtin/scoping.py index 2d7202a5f..1b50f9aeb 100644 --- a/mathics/builtin/scoping.py +++ b/mathics/builtin/scoping.py @@ -129,6 +129,7 @@ class BeginPackage(Builtin): ## >> BeginPackage["test`"] ## = test` """ + has_side_effects = True messages = {"unimpl": "The second argument to BeginPackage is not yet implemented."} @@ -387,6 +388,7 @@ class EndPackage(Builtin): After 'EndPackage', the values of '\$Context' and '\$ContextPath' at the \ time of the 'BeginPackage' call are restored, with the new package\'s context prepended to '\$ContextPath'. """ + has_side_effects = True messages = { "noctx": "No previous context defined.", diff --git a/mathics/builtin/specialfns/orthogonal.py b/mathics/builtin/specialfns/orthogonal.py index 4925a2f09..ef0354a48 100644 --- a/mathics/builtin/specialfns/orthogonal.py +++ b/mathics/builtin/specialfns/orthogonal.py @@ -6,7 +6,6 @@ https://dlmf.nist.gov/18.3. """ - from mathics.core.atoms import Integer0 from mathics.core.builtin import MPMathFunction diff --git a/mathics/builtin/statistics/base.py b/mathics/builtin/statistics/base.py index 8ab72cd74..baf0c94c1 100644 --- a/mathics/builtin/statistics/base.py +++ b/mathics/builtin/statistics/base.py @@ -1,6 +1,7 @@ """ Base classes for Descriptive Statistics """ + from mathics.core.builtin import Builtin from mathics.core.expression import Expression from mathics.core.list import ListExpression diff --git a/mathics/builtin/string/__init__.py b/mathics/builtin/string/__init__.py index d9abdaad9..c49df12e1 100644 --- a/mathics/builtin/string/__init__.py +++ b/mathics/builtin/string/__init__.py @@ -2,4 +2,5 @@ Strings and Characters """ + # FIXME: Redo. This is a Tech note, not a Guide Section. diff --git a/mathics/builtin/string/patterns.py b/mathics/builtin/string/patterns.py index 648caf6ce..92bf302db 100644 --- a/mathics/builtin/string/patterns.py +++ b/mathics/builtin/string/patterns.py @@ -57,6 +57,7 @@ class EndOfLine(Builtin): . def, . hij} """ + summary_text = "a string pattern matching EOF" @@ -146,6 +147,7 @@ class StartOfString(Builtin): = cba . abb """ + summary_text = "start of a whole string" @@ -312,4 +314,5 @@ class WordCharacter(Builtin): >> StringMatchQ["$b;123", WordCharacter..] = False """ + summary_text = "letter or digit" diff --git a/mathics/builtin/symbolic_history/__init__.py b/mathics/builtin/symbolic_history/__init__.py index afc5a13bd..b8c63d722 100644 --- a/mathics/builtin/symbolic_history/__init__.py +++ b/mathics/builtin/symbolic_history/__init__.py @@ -3,4 +3,5 @@ In order to debug and understand program execution, the execution history can be saved. """ + sort_order = "mathics.builtin.symbolic-execution-history" diff --git a/mathics/builtin/testing_expressions/expression_tests.py b/mathics/builtin/testing_expressions/expression_tests.py index bee098e46..7cead39ee 100644 --- a/mathics/builtin/testing_expressions/expression_tests.py +++ b/mathics/builtin/testing_expressions/expression_tests.py @@ -1,6 +1,7 @@ """ Expression Tests """ + from mathics.core.atoms import Integer0, Integer1, IntegerM1 from mathics.core.builtin import Builtin, PatternError, Test from mathics.core.evaluation import Evaluation diff --git a/mathics/builtin/testing_expressions/numerical_properties.py b/mathics/builtin/testing_expressions/numerical_properties.py index 0cb3fd8a7..7c9356822 100644 --- a/mathics/builtin/testing_expressions/numerical_properties.py +++ b/mathics/builtin/testing_expressions/numerical_properties.py @@ -1,6 +1,7 @@ """ Numerical Properties """ + from itertools import combinations import sympy diff --git a/mathics/core/convert/function.py b/mathics/core/convert/function.py index d75b3e301..5d249f784 100644 --- a/mathics/core/convert/function.py +++ b/mathics/core/convert/function.py @@ -196,7 +196,7 @@ def expression_to_callable_and_args( CompileError as LambdifyCompileError, lambdify_compile, ) - + args = collect_args(vars) # If vectorize is requested, first, try to lambdify the expression: diff --git a/mathics/core/convert/regex.py b/mathics/core/convert/regex.py index 0e468961e..2987f3e27 100644 --- a/mathics/core/convert/regex.py +++ b/mathics/core/convert/regex.py @@ -1,6 +1,7 @@ """ Convert expressions to Python regular expressions """ + import re from binascii import hexlify from typing import Callable, Optional From dc91eedc94203fb026300aff5406768e58600aab Mon Sep 17 00:00:00 2001 From: Juan Mauricio Matera Date: Mon, 15 Dec 2025 00:05:41 -0300 Subject: [PATCH 10/15] isort --- mathics/builtin/compilation.py | 1 - mathics/core/convert/function.py | 1 - mathics/core/convert/lambdify.py | 2 -- 3 files changed, 4 deletions(-) diff --git a/mathics/builtin/compilation.py b/mathics/builtin/compilation.py index 1d7b4255c..ac8ad3aca 100644 --- a/mathics/builtin/compilation.py +++ b/mathics/builtin/compilation.py @@ -18,7 +18,6 @@ A_PROTECTED, A_READ_PROTECTED, ) - from mathics.core.builtin import Builtin from mathics.core.convert.expression import to_mathics_list from mathics.core.convert.function import ( diff --git a/mathics/core/convert/function.py b/mathics/core/convert/function.py index 5d249f784..c64b028c8 100644 --- a/mathics/core/convert/function.py +++ b/mathics/core/convert/function.py @@ -3,7 +3,6 @@ import numpy - from mathics.core.definitions import SIDE_EFFECT_BUILTINS, Definition from mathics.core.evaluation import Evaluation from mathics.core.expression import Expression, from_python diff --git a/mathics/core/convert/lambdify.py b/mathics/core/convert/lambdify.py index 9a633a15e..82db5a109 100644 --- a/mathics/core/convert/lambdify.py +++ b/mathics/core/convert/lambdify.py @@ -18,11 +18,9 @@ import scipy import sympy - from mathics.core.convert.function import evaluate_without_side_effects from mathics.core.convert.sympy import SympyExpression from mathics.core.symbols import strip_context, sympy_strip_context - from mathics.core.util import print_expression_tree, print_sympy_tree From af8fb0a2b695922b3add9fe6168357773a732c66 Mon Sep 17 00:00:00 2001 From: Juan Mauricio Matera Date: Mon, 15 Dec 2025 00:06:53 -0300 Subject: [PATCH 11/15] more black --- test/builtin/test-optimization.py | 1 + test/core/test_pattern.py | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/test/builtin/test-optimization.py b/test/builtin/test-optimization.py index 8d2d68d32..66e0ace34 100644 --- a/test/builtin/test-optimization.py +++ b/test/builtin/test-optimization.py @@ -7,6 +7,7 @@ """ + from test.helper import check_evaluation import pytest diff --git a/test/core/test_pattern.py b/test/core/test_pattern.py index 75997b493..46847a2ce 100644 --- a/test/core/test_pattern.py +++ b/test/core/test_pattern.py @@ -5,7 +5,6 @@ expressions. """ - from test.helper import check_evaluation, session import pytest From 88d07dae5543eaf86e0ae478d64a451cef1533f0 Mon Sep 17 00:00:00 2001 From: Juan Mauricio Matera Date: Mon, 15 Dec 2025 07:46:17 -0300 Subject: [PATCH 12/15] black --- mathics/doc/gather.py | 6 +++--- mathics/eval/assignments/assign_binaryop.py | 1 + mathics/eval/drawing/util.py | 2 -- mathics/eval/scoping.py | 1 + mathics/eval/strings.py | 1 + mathics/format/text.py | 16 +++++++++------- 6 files changed, 15 insertions(+), 12 deletions(-) diff --git a/mathics/doc/gather.py b/mathics/doc/gather.py index 7da4ed0e1..319c82dbe 100644 --- a/mathics/doc/gather.py +++ b/mathics/doc/gather.py @@ -357,7 +357,7 @@ def sorted_modules(modules) -> list: exists, or the module's name if not.""" return sorted( modules, - key=lambda module: module.sort_order - if hasattr(module, "sort_order") - else module.__name__, + key=lambda module: ( + module.sort_order if hasattr(module, "sort_order") else module.__name__ + ), ) diff --git a/mathics/eval/assignments/assign_binaryop.py b/mathics/eval/assignments/assign_binaryop.py index 318e187c7..9b3be0565 100644 --- a/mathics/eval/assignments/assign_binaryop.py +++ b/mathics/eval/assignments/assign_binaryop.py @@ -2,6 +2,7 @@ evaluation functions associated with the mathics.builtin.assign_binary_op module. """ + from mathics.core.evaluation import Evaluation from mathics.core.expression import Expression from mathics.core.systemsymbols import SymbolSet diff --git a/mathics/eval/drawing/util.py b/mathics/eval/drawing/util.py index d6e5c8ec4..99ab780bb 100644 --- a/mathics/eval/drawing/util.py +++ b/mathics/eval/drawing/util.py @@ -2,7 +2,6 @@ Common utilities for plotting """ - from mathics.core.atoms import NumericArray from mathics.core.convert.expression import to_expression, to_mathics_list from mathics.core.expression import Expression @@ -23,7 +22,6 @@ # TODO: this will be extended with support for GraphicsComplex in a # subsequent PR, which may involve a little more refactoring class GraphicsGenerator: - """ Support for generating Graphics and Graphics3D expressions """ diff --git a/mathics/eval/scoping.py b/mathics/eval/scoping.py index eba2bb63b..bc63393f6 100644 --- a/mathics/eval/scoping.py +++ b/mathics/eval/scoping.py @@ -1,6 +1,7 @@ """ Evaluation module corresponding to builtin functions in mathics.builtins.scoping. """ + import re from mathics.core.atoms import String diff --git a/mathics/eval/strings.py b/mathics/eval/strings.py index 96a73a2c4..c17b84e3e 100644 --- a/mathics/eval/strings.py +++ b/mathics/eval/strings.py @@ -1,6 +1,7 @@ """ String-related evaluation functions. """ + import re from mathics.core.atoms import Integer1, Integer3, String diff --git a/mathics/format/text.py b/mathics/format/text.py index 422ce940a..0f51b5eb8 100644 --- a/mathics/format/text.py +++ b/mathics/format/text.py @@ -72,13 +72,15 @@ def gridbox(self, elements=None, **box_options) -> str: widths = [0] cells = [ - [ - # TODO: check if this evaluation is necessary. - boxes_to_text(item, **box_options).splitlines() - for item in row - ] - if isinstance(row, tuple) - else [boxes_to_text(row, **box_options).splitlines()] + ( + [ + # TODO: check if this evaluation is necessary. + boxes_to_text(item, **box_options).splitlines() + for item in row + ] + if isinstance(row, tuple) + else [boxes_to_text(row, **box_options).splitlines()] + ) for row in items ] From a95b65f463939cd20a8881ac5b77bffb51088bae Mon Sep 17 00:00:00 2001 From: Juan Mauricio Matera Date: Mon, 15 Dec 2025 07:55:40 -0300 Subject: [PATCH 13/15] revert trivial changes --- mathics/builtin/directories/__init__.py | 1 - mathics/builtin/exp_structure/size_and_sig.py | 1 - mathics/builtin/file_operations/__init__.py | 1 - mathics/builtin/files_io/__init__.py | 1 - mathics/builtin/image/base.py | 1 - mathics/builtin/image/composition.py | 1 - mathics/builtin/image/pixel.py | 1 - mathics/builtin/image/structure.py | 1 - mathics/builtin/image/test.py | 1 - mathics/builtin/list/math.py | 1 - mathics/builtin/specialfns/orthogonal.py | 1 + mathics/builtin/statistics/base.py | 1 - mathics/builtin/string/__init__.py | 1 - mathics/builtin/string/patterns.py | 3 --- mathics/builtin/symbolic_history/__init__.py | 1 - mathics/builtin/testing_expressions/expression_tests.py | 1 - mathics/builtin/testing_expressions/numerical_properties.py | 1 - mathics/core/convert/regex.py | 1 - mathics/eval/assignments/assign_binaryop.py | 1 - mathics/eval/drawing/util.py | 2 ++ mathics/eval/scoping.py | 2 -- mathics/eval/strings.py | 1 - 22 files changed, 3 insertions(+), 23 deletions(-) diff --git a/mathics/builtin/directories/__init__.py b/mathics/builtin/directories/__init__.py index a17fc9441..b7bf1f9e4 100644 --- a/mathics/builtin/directories/__init__.py +++ b/mathics/builtin/directories/__init__.py @@ -1,7 +1,6 @@ """ Directories and Directory Operations """ - # Note: everything in this module is not loaded if environment # variable ENABLE_FILES_MODULE is False. Here we do not want to # include any built-in commands that can write to the filesytesm. diff --git a/mathics/builtin/exp_structure/size_and_sig.py b/mathics/builtin/exp_structure/size_and_sig.py index 075499752..b06cede7f 100644 --- a/mathics/builtin/exp_structure/size_and_sig.py +++ b/mathics/builtin/exp_structure/size_and_sig.py @@ -1,7 +1,6 @@ """ Expression Sizes and Signatures """ - import hashlib import platform import zlib diff --git a/mathics/builtin/file_operations/__init__.py b/mathics/builtin/file_operations/__init__.py index 5d05c229f..c69d15343 100644 --- a/mathics/builtin/file_operations/__init__.py +++ b/mathics/builtin/file_operations/__init__.py @@ -1,7 +1,6 @@ """ File Operations """ - # Note: everything in this module is not loaded if environment # variable ENABLE_FILES_MODULE is False. Here we do not want to # include any built-in commands that can write to the filesytesm. diff --git a/mathics/builtin/files_io/__init__.py b/mathics/builtin/files_io/__init__.py index c06a44c84..82b851411 100644 --- a/mathics/builtin/files_io/__init__.py +++ b/mathics/builtin/files_io/__init__.py @@ -2,7 +2,6 @@ Input/Output, Files, and Filesystem """ - # Note: everything in this module is not loaded if environment # variable ENABLE_FILES_MODULE is False. Here we do not want to # include any built-in commands that can write to the filesystem. diff --git a/mathics/builtin/image/base.py b/mathics/builtin/image/base.py index 6274f7e27..2d8ce7756 100644 --- a/mathics/builtin/image/base.py +++ b/mathics/builtin/image/base.py @@ -1,7 +1,6 @@ """ Base classes for Image Manipulation """ - from typing import Tuple import numpy diff --git a/mathics/builtin/image/composition.py b/mathics/builtin/image/composition.py index 7aedb542f..b5051425e 100644 --- a/mathics/builtin/image/composition.py +++ b/mathics/builtin/image/composition.py @@ -1,7 +1,6 @@ """ Image Compositions """ - import os.path as osp from collections import defaultdict diff --git a/mathics/builtin/image/pixel.py b/mathics/builtin/image/pixel.py index 1fdd330fa..b7b58573b 100644 --- a/mathics/builtin/image/pixel.py +++ b/mathics/builtin/image/pixel.py @@ -1,7 +1,6 @@ """ Pixel Operations """ - import numpy from mathics.builtin.image.base import Image diff --git a/mathics/builtin/image/structure.py b/mathics/builtin/image/structure.py index fe9faaa91..95cd65548 100644 --- a/mathics/builtin/image/structure.py +++ b/mathics/builtin/image/structure.py @@ -1,7 +1,6 @@ """ Operations on Image Structure """ - import numpy from mathics.builtin.image.base import Image diff --git a/mathics/builtin/image/test.py b/mathics/builtin/image/test.py index f5b60d53d..62945df64 100644 --- a/mathics/builtin/image/test.py +++ b/mathics/builtin/image/test.py @@ -1,7 +1,6 @@ """ Image testing """ - from mathics.builtin.image.base import Image, skimage_requires from mathics.core.builtin import Test diff --git a/mathics/builtin/list/math.py b/mathics/builtin/list/math.py index b6a27a711..8f1d84c10 100644 --- a/mathics/builtin/list/math.py +++ b/mathics/builtin/list/math.py @@ -1,7 +1,6 @@ """ Math & Counting Operations on Lists """ - import heapq from mathics.core.builtin import Builtin, CountableInteger, NegativeIntegerException diff --git a/mathics/builtin/specialfns/orthogonal.py b/mathics/builtin/specialfns/orthogonal.py index ef0354a48..4925a2f09 100644 --- a/mathics/builtin/specialfns/orthogonal.py +++ b/mathics/builtin/specialfns/orthogonal.py @@ -6,6 +6,7 @@ https://dlmf.nist.gov/18.3. """ + from mathics.core.atoms import Integer0 from mathics.core.builtin import MPMathFunction diff --git a/mathics/builtin/statistics/base.py b/mathics/builtin/statistics/base.py index baf0c94c1..8ab72cd74 100644 --- a/mathics/builtin/statistics/base.py +++ b/mathics/builtin/statistics/base.py @@ -1,7 +1,6 @@ """ Base classes for Descriptive Statistics """ - from mathics.core.builtin import Builtin from mathics.core.expression import Expression from mathics.core.list import ListExpression diff --git a/mathics/builtin/string/__init__.py b/mathics/builtin/string/__init__.py index c49df12e1..d9abdaad9 100644 --- a/mathics/builtin/string/__init__.py +++ b/mathics/builtin/string/__init__.py @@ -2,5 +2,4 @@ Strings and Characters """ - # FIXME: Redo. This is a Tech note, not a Guide Section. diff --git a/mathics/builtin/string/patterns.py b/mathics/builtin/string/patterns.py index 92bf302db..648caf6ce 100644 --- a/mathics/builtin/string/patterns.py +++ b/mathics/builtin/string/patterns.py @@ -57,7 +57,6 @@ class EndOfLine(Builtin): . def, . hij} """ - summary_text = "a string pattern matching EOF" @@ -147,7 +146,6 @@ class StartOfString(Builtin): = cba . abb """ - summary_text = "start of a whole string" @@ -314,5 +312,4 @@ class WordCharacter(Builtin): >> StringMatchQ["$b;123", WordCharacter..] = False """ - summary_text = "letter or digit" diff --git a/mathics/builtin/symbolic_history/__init__.py b/mathics/builtin/symbolic_history/__init__.py index b8c63d722..afc5a13bd 100644 --- a/mathics/builtin/symbolic_history/__init__.py +++ b/mathics/builtin/symbolic_history/__init__.py @@ -3,5 +3,4 @@ In order to debug and understand program execution, the execution history can be saved. """ - sort_order = "mathics.builtin.symbolic-execution-history" diff --git a/mathics/builtin/testing_expressions/expression_tests.py b/mathics/builtin/testing_expressions/expression_tests.py index 7cead39ee..bee098e46 100644 --- a/mathics/builtin/testing_expressions/expression_tests.py +++ b/mathics/builtin/testing_expressions/expression_tests.py @@ -1,7 +1,6 @@ """ Expression Tests """ - from mathics.core.atoms import Integer0, Integer1, IntegerM1 from mathics.core.builtin import Builtin, PatternError, Test from mathics.core.evaluation import Evaluation diff --git a/mathics/builtin/testing_expressions/numerical_properties.py b/mathics/builtin/testing_expressions/numerical_properties.py index 7c9356822..0cb3fd8a7 100644 --- a/mathics/builtin/testing_expressions/numerical_properties.py +++ b/mathics/builtin/testing_expressions/numerical_properties.py @@ -1,7 +1,6 @@ """ Numerical Properties """ - from itertools import combinations import sympy diff --git a/mathics/core/convert/regex.py b/mathics/core/convert/regex.py index 2987f3e27..0e468961e 100644 --- a/mathics/core/convert/regex.py +++ b/mathics/core/convert/regex.py @@ -1,7 +1,6 @@ """ Convert expressions to Python regular expressions """ - import re from binascii import hexlify from typing import Callable, Optional diff --git a/mathics/eval/assignments/assign_binaryop.py b/mathics/eval/assignments/assign_binaryop.py index 9b3be0565..318e187c7 100644 --- a/mathics/eval/assignments/assign_binaryop.py +++ b/mathics/eval/assignments/assign_binaryop.py @@ -2,7 +2,6 @@ evaluation functions associated with the mathics.builtin.assign_binary_op module. """ - from mathics.core.evaluation import Evaluation from mathics.core.expression import Expression from mathics.core.systemsymbols import SymbolSet diff --git a/mathics/eval/drawing/util.py b/mathics/eval/drawing/util.py index 99ab780bb..d6e5c8ec4 100644 --- a/mathics/eval/drawing/util.py +++ b/mathics/eval/drawing/util.py @@ -2,6 +2,7 @@ Common utilities for plotting """ + from mathics.core.atoms import NumericArray from mathics.core.convert.expression import to_expression, to_mathics_list from mathics.core.expression import Expression @@ -22,6 +23,7 @@ # TODO: this will be extended with support for GraphicsComplex in a # subsequent PR, which may involve a little more refactoring class GraphicsGenerator: + """ Support for generating Graphics and Graphics3D expressions """ diff --git a/mathics/eval/scoping.py b/mathics/eval/scoping.py index bc63393f6..6579c24de 100644 --- a/mathics/eval/scoping.py +++ b/mathics/eval/scoping.py @@ -1,7 +1,6 @@ """ Evaluation module corresponding to builtin functions in mathics.builtins.scoping. """ - import re from mathics.core.atoms import String @@ -17,7 +16,6 @@ def dynamic_scoping(func, vars, evaluation: Evaluation): and evaluates func(evaluation) """ original_definitions = {} - for var_name, new_def in vars.items(): assert fully_qualified_symbol_name(var_name) original_definitions[var_name] = evaluation.definitions.get_user_definition( diff --git a/mathics/eval/strings.py b/mathics/eval/strings.py index c17b84e3e..96a73a2c4 100644 --- a/mathics/eval/strings.py +++ b/mathics/eval/strings.py @@ -1,7 +1,6 @@ """ String-related evaluation functions. """ - import re from mathics.core.atoms import Integer1, Integer3, String From 2ebd8efcc9fed5b57a2e674964494d11a2a5d736 Mon Sep 17 00:00:00 2001 From: Juan Mauricio Matera Date: Mon, 15 Dec 2025 08:04:56 -0300 Subject: [PATCH 14/15] restore graphics3d.py --- mathics/builtin/drawing/graphics3d.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mathics/builtin/drawing/graphics3d.py b/mathics/builtin/drawing/graphics3d.py index 52daa2dc3..5caa0b1c3 100644 --- a/mathics/builtin/drawing/graphics3d.py +++ b/mathics/builtin/drawing/graphics3d.py @@ -107,7 +107,6 @@ class Graphics3D(Graphics): . draw(((1,1,-1)--(1,1,1)), rgb(0.4, 0.4, 0.4)+linewidth(1)); . \end{asy} """ - summary_text = "a three-dimensional graphics image wrapper" options = Graphics.options.copy() options.update( @@ -173,9 +172,11 @@ class Graphics3DElements(_GraphicsElements): def __init__(self, content, evaluation, neg_y=False): super(Graphics3DElements, self).__init__(content, evaluation) self.neg_y = neg_y - self.xmin = self.ymin = self.pixel_width = self.pixel_height = ( - self.extent_width - ) = self.extent_height = None + self.xmin = ( + self.ymin + ) = ( + self.pixel_width + ) = self.pixel_height = self.extent_width = self.extent_height = None self.view_width = None self.content = content From 1e1e02bc13a37bc0f44f2e244095cab09f2d00d6 Mon Sep 17 00:00:00 2001 From: Juan Mauricio Matera Date: Mon, 15 Dec 2025 08:06:32 -0300 Subject: [PATCH 15/15] more on restoring trivial changes --- mathics/builtin/box/__init__.py | 1 - mathics/doc/gather.py | 6 +++--- mathics/format/text.py | 16 +++++++--------- test/builtin/test-optimization.py | 1 - test/core/test_pattern.py | 1 + 5 files changed, 11 insertions(+), 14 deletions(-) diff --git a/mathics/builtin/box/__init__.py b/mathics/builtin/box/__init__.py index 8275c12be..5d2777e44 100644 --- a/mathics/builtin/box/__init__.py +++ b/mathics/builtin/box/__init__.py @@ -6,6 +6,5 @@ Boxing information like bounding-box width and size makes it easier for formatters to do layout without having to know the intricacies of what is inside the box. """ - # Docs are not yet ready for prime time. Maybe after release 6.0.0. no_doc = True diff --git a/mathics/doc/gather.py b/mathics/doc/gather.py index 319c82dbe..7da4ed0e1 100644 --- a/mathics/doc/gather.py +++ b/mathics/doc/gather.py @@ -357,7 +357,7 @@ def sorted_modules(modules) -> list: exists, or the module's name if not.""" return sorted( modules, - key=lambda module: ( - module.sort_order if hasattr(module, "sort_order") else module.__name__ - ), + key=lambda module: module.sort_order + if hasattr(module, "sort_order") + else module.__name__, ) diff --git a/mathics/format/text.py b/mathics/format/text.py index 0f51b5eb8..422ce940a 100644 --- a/mathics/format/text.py +++ b/mathics/format/text.py @@ -72,15 +72,13 @@ def gridbox(self, elements=None, **box_options) -> str: widths = [0] cells = [ - ( - [ - # TODO: check if this evaluation is necessary. - boxes_to_text(item, **box_options).splitlines() - for item in row - ] - if isinstance(row, tuple) - else [boxes_to_text(row, **box_options).splitlines()] - ) + [ + # TODO: check if this evaluation is necessary. + boxes_to_text(item, **box_options).splitlines() + for item in row + ] + if isinstance(row, tuple) + else [boxes_to_text(row, **box_options).splitlines()] for row in items ] diff --git a/test/builtin/test-optimization.py b/test/builtin/test-optimization.py index 66e0ace34..8d2d68d32 100644 --- a/test/builtin/test-optimization.py +++ b/test/builtin/test-optimization.py @@ -7,7 +7,6 @@ """ - from test.helper import check_evaluation import pytest diff --git a/test/core/test_pattern.py b/test/core/test_pattern.py index 46847a2ce..75997b493 100644 --- a/test/core/test_pattern.py +++ b/test/core/test_pattern.py @@ -5,6 +5,7 @@ expressions. """ + from test.helper import check_evaluation, session import pytest