From 53300f5fbde618656993af8d782a31ccba039c13 Mon Sep 17 00:00:00 2001 From: mmatera Date: Tue, 22 Nov 2022 10:01:16 -0300 Subject: [PATCH] the true fix: * adding comments * moving _initialize_system_definitions to a better place, and hide it. * fixing contribute in order to make work the pymathics loading mechanism without overwrite builtins --- mathics/builtin/base.py | 30 +++++++++++++++++++++++++-- mathics/docpipeline.py | 4 ++-- mathics/session.py | 7 +------ test/format/test_asy.py | 1 - test/helper.py | 2 -- test/test_custom_boxexpression.py | 34 +++++++++++++++---------------- 6 files changed, 48 insertions(+), 30 deletions(-) diff --git a/mathics/builtin/base.py b/mathics/builtin/base.py index b1e0dfae9..4d8890855 100644 --- a/mathics/builtin/base.py +++ b/mathics/builtin/base.py @@ -3,6 +3,7 @@ import importlib import re + from functools import lru_cache, total_ordering from itertools import chain from typing import Any, Callable, Dict, Iterable, List, Optional, Union, cast @@ -291,7 +292,13 @@ def check_options(options_to_check, evaluation): ) box_rules = [] - # FIXME: Why a special case for System`MakeBoxes? Remove this + + # System`MakeBoxes comes first because all the other symbols contribute to it. + # Then, a definition of this symbol must be available from the begining. + # Probably, this is not a good approach, since it makes that MakeBoxes has + # a very large number of inespecific rules. A better approach would imply at least + # to store the rules as upvalues of the symbols associated to these rules. + # if name != "System`MakeBoxes": new_rules = [] for rule in rules: @@ -389,13 +396,32 @@ def contextify_form_name(f): ) if is_pymodule: definitions.pymathics[name] = definition + try: + makeboxes_def = definitions.pymathics["System`MakeBoxes"] + except KeyError: + builtin_mb_def = definitions.builtin["System`MakeBoxes"] + makeboxes_def = Definition( + "System`MakeBoxes", + builtin=builtin_mb_def.builtin, + attributes=builtin_mb_def.attributes, + is_numeric=builtin_mb_def.is_numeric, + ) + definitions.pymathics["System`MakeBoxes"] = makeboxes_def else: definitions.builtin[name] = definition + makeboxes_def = definitions.builtin["System`MakeBoxes"] - makeboxes_def = definitions.builtin["System`MakeBoxes"] for rule in box_rules: makeboxes_def.add_rule(rule) + # If a pymathics module was loaded, then there are at least two + # definitions for MakeBoxes, the builtin, the pymathics, and the + # cached from combining the former two. Rules are added to one of + # both, which are not going to be in the cached version that + # Definitions.get_definition provides. To make the new rules + # accesible, we need to clear the definitions cache. + definitions.clear_cache("System`MakeBoxes") + @classmethod def get_name(cls, short=False) -> str: if cls.name is None: diff --git a/mathics/docpipeline.py b/mathics/docpipeline.py index 826d54066..29629af22 100644 --- a/mathics/docpipeline.py +++ b/mathics/docpipeline.py @@ -21,7 +21,7 @@ import mathics import mathics.settings -from mathics.core.definitions import Definitions, initialize_system_definitions +from mathics.core.definitions import Definitions from mathics.core.evaluation import Evaluation, Output from mathics.core.parser import MathicsSingleLineFeeder from mathics.builtin.system_init import builtins_dict @@ -446,7 +446,7 @@ def main(): global definitions global logfile global check_partial_enlapsed_time - initialize_system_definitions() + definitions = Definitions(add_builtin=True) parser = ArgumentParser(description="Mathics test suite.", add_help=False) diff --git a/mathics/session.py b/mathics/session.py index ddda2cab7..5d4278372 100644 --- a/mathics/session.py +++ b/mathics/session.py @@ -14,7 +14,7 @@ from mathics.builtin.system_init import autoload_files from mathics.core.parser import parse, MathicsSingleLineFeeder -from mathics.core.definitions import Definitions, initialize_system_definitions +from mathics.core.definitions import Definitions from mathics.core.evaluation import Evaluation import mathics.settings @@ -72,11 +72,6 @@ def reset(self, add_builtin=True, catch_interrupt=False): """ reset the definitions and the evaluation objects. """ - # TODO: Due to a fail in the Definitions __init__ method, - # we need to initialize this each time Definitions is - # instantiated. When it gets fixed, the next line - # can be removed. - initialize_system_definitions() self.definitions = Definitions(add_builtin) self.evaluation = Evaluation( definitions=self.definitions, catch_interrupt=catch_interrupt diff --git a/test/format/test_asy.py b/test/format/test_asy.py index 463173d99..30e43a186 100644 --- a/test/format/test_asy.py +++ b/test/format/test_asy.py @@ -8,7 +8,6 @@ from mathics.session import MathicsSession from mathics.builtin.makeboxes import MakeBoxes - session = MathicsSession(add_builtin=True, catch_interrupt=False) evaluation = Evaluation(session.definitions) diff --git a/test/helper.py b/test/helper.py index 7e8a8ae39..89aa0a2cd 100644 --- a/test/helper.py +++ b/test/helper.py @@ -4,9 +4,7 @@ from typing import Optional from mathics.session import MathicsSession -from mathics.core.definitions import initialize_system_definitions -initialize_system_definitions() # Set up a Mathics session with definitions. # For consistency set the character encoding ASCII which is diff --git a/test/test_custom_boxexpression.py b/test/test_custom_boxexpression.py index 48f4e6c44..6cd8edb0a 100644 --- a/test/test_custom_boxexpression.py +++ b/test/test_custom_boxexpression.py @@ -14,19 +14,19 @@ def __init__(self, evaluation): super().__init__(evaluation=evaluation) self._elements = [1, 2, 3] - def boxes_to_text(self, leaves=None, **options): - if not leaves: - leaves = self.elements + def boxes_to_text(self, elements=None, **options): + if not elements: + elements = self.elements return "CustomBoxExpression<<" + self.elements.__str__() + ">>" - def boxes_to_mathml(self, leaves=None, **options): - if not leaves: - leaves = self.elements + def boxes_to_mathml(self, elements=None, **options): + if not elements: + elements = self.elements return "CustomBoxExpression<<" + self.elements.__str__() + ">>" - def boxes_to_tex(self, leaves=None, **options): - if not leaves: - leaves = self.elements + def boxes_to_tex(self, elements=None, **options): + if not elements: + elements = self.elements return "CustomBoxExpression<<" + int(self.elements) + ">>" @@ -59,25 +59,25 @@ def init(self, *elems, **options): def to_expression(self): return Expression(SymbolCustomGraphicsBox, *self.elements) - def apply_box(self, elems, evaluation, options): - """System`MakeBoxes[System`Graphics[elems_, System`OptionsPattern[System`Graphics]], + def apply_box(self, expr, evaluation, options): + """System`MakeBoxes[System`Graphics[System`expr_, System`OptionsPattern[System`Graphics]], System`StandardForm|System`TraditionalForm|System`OutputForm]""" - instance = CustomGraphicsBox(*(elems.elements), evaluation=evaluation) + instance = CustomGraphicsBox(*(expr.elements), evaluation=evaluation) return instance - def boxes_to_text(self, leaves=None, **options): - if leaves: - self._elements = leaves + def boxes_to_text(self, elements=None, **options): + if elements: + self._elements = elements return ( "--custom graphics--: I should plot " + self.elements.__str__() + " items" ) - def boxes_to_tex(self, leaves=None, **options): + def boxes_to_tex(self, elements=None, **options): return ( "--custom graphics--: I should plot " + self.elements.__str__() + " items" ) - def boxes_to_mathml(self, leaves=None, **options): + def boxes_to_mathml(self, elements=None, **options): return ( "--custom graphics--: I should plot " + self.elements.__str__() + " items" )