1313import pkgutil
1414from glob import glob
1515from types import ModuleType
16- from typing import List , Optional
16+ from typing import Dict , List , Optional , Set
1717
18+ from mathics .core .convert .sympy import mathics_to_sympy , sympy_to_mathics
1819from mathics .core .pattern import pattern_objects
1920from mathics .core .symbols import Symbol
2021from mathics .eval .makeboxes import builtins_precedence
2728mathics3_builtins_modules : List [ModuleType ] = []
2829
2930_builtins = {}
30- builtins_by_module = {}
31- display_operators_set = set ()
3231
32+ # builtins_by_module gives a way of mapping a Python module name
33+ # e.g. 'mathics.builtin.arithmetic' to the list of Builtin class instances
34+ # that appear inside that module, e.g. for key 'mathics.builtin.arithmetic' we
35+ # have:
36+ # [<mathics.builtin.arithmetic.Arg object>, <mathics.builtin.arithmetic.Assuming object, ...]
37+ #
38+ builtins_by_module : Dict [str , list ] = {}
3339
34- # The fact that are importing inside here, suggests add_builtins
40+ # Set operators strings, unary, binary, or ternary.
41+ # For example "!, "!!", ^, "+", "-", ">=", "===", "<<", etc.
42+ display_operators_set : Set [str ] = set ()
43+
44+
45+ def add_builtins_from_builtin_module (module : ModuleType , builtins_list : list ):
46+ """
47+ Process a modules which contains Builtin classes so that the
48+ class is imported in the Python sense but also that we
49+ have information added to module variable ``builtins_by_module``.
50+
51+ """
52+ from mathics .core .builtin import Builtin
53+
54+ builtins_by_module [module .__name__ ] = []
55+ module_vars = dir (module )
56+
57+ for name in module_vars :
58+ builtin_class = name_is_builtin_symbol (module , name )
59+ if builtin_class is not None :
60+ instance = builtin_class (expression = False )
61+
62+ if isinstance (instance , Builtin ):
63+ # This set the default context for symbols in mathics.builtins
64+ if not type (instance ).context :
65+ type(instance ).context = "System`"
66+ builtins_list .append ((instance .get_name (), instance ))
67+ builtins_by_module [module .__name__ ].append (instance )
68+ update_display_operators_set (instance )
69+
70+
71+ def add_builtins_from_builtin_modules (modules : List [ModuleType ]):
72+ builtins_list = []
73+ for module in modules :
74+ add_builtins_from_builtin_module (module , builtins_list )
75+ add_builtins (builtins_list )
76+ return builtins_by_module
77+
78+
79+ # The fact that we are importing inside here, suggests add_builtins
3580# should get moved elsewhere.
3681def add_builtins (new_builtins ):
3782 from mathics .core .builtin import (
@@ -40,7 +85,6 @@ def add_builtins(new_builtins):
4085 SympyObject ,
4186 mathics_to_python ,
4287 )
43- from mathics .core .convert .sympy import mathics_to_sympy , sympy_to_mathics
4488
4589 for _ , builtin in new_builtins :
4690 name = builtin .get_name ()
@@ -54,37 +98,13 @@ def add_builtins(new_builtins):
5498 # print("XXX1", sympy_name)
5599 sympy_to_mathics [sympy_name ] = builtin
56100 if isinstance (builtin , Operator ):
101+ assert builtin .precedence is not None
57102 builtins_precedence [Symbol (name )] = builtin .precedence
58103 if isinstance (builtin , PatternObject ):
59104 pattern_objects [name ] = builtin .__class__
60105 _builtins .update (dict (new_builtins ))
61106
62107
63- def add_builtins_from_builtin_modules (modules : List [ModuleType ]):
64- # This can be put at the top after mathics.builtin.__init__
65- # cleanup is done.
66- from mathics .core .builtin import Builtin
67-
68- builtins_list = []
69- for module in modules :
70- builtins_by_module [module .__name__ ] = []
71- module_vars = dir (module )
72-
73- for name in module_vars :
74- builtin_class = name_is_builtin_symbol (module , name )
75- if builtin_class is not None :
76- instance = builtin_class (expression = False )
77-
78- if isinstance (instance , Builtin ):
79- # This set the default context for symbols in mathics.builtins
80- if not type (instance ).context :
81- type(instance ).context = "System`"
82- builtins_list .append ((instance .get_name (), instance ))
83- builtins_by_module [module .__name__ ].append (instance )
84- add_builtins (builtins_list )
85- return builtins_by_module
86-
87-
88108def builtins_dict (builtins_by_module ):
89109 return {
90110 builtin .get_name (): builtin
@@ -143,13 +163,32 @@ def import_and_load_builtins():
143163 # server, we disallow local file access.
144164 disable_file_module_names = set () if ENABLE_FILES_MODULE else {"files_io" }
145165
146- subdirectories = next (os .walk (builtin_path ))[1 ]
166+ subdirectory_list = next (os .walk (builtin_path ))[1 ]
167+ subdirectories = set (subdirectory_list ) - set ("__pycache__" )
147168 import_builtin_subdirectories (
148169 subdirectories , disable_file_module_names , mathics3_builtins_modules
149170 )
150171
151172 add_builtins_from_builtin_modules (mathics3_builtins_modules )
152- initialize_display_operators_set ()
173+
174+
175+ def import_builtin_module (import_name : str , modules : List [ModuleType ]):
176+ """
177+ Imports ``the list of Mathics3 Built-in modules so that inside
178+ Mathics3 Builtin Functions, like Plus[], List[] are defined.
179+
180+ List ``module_names`` is updated.
181+ """
182+ try :
183+ module = importlib .import_module (import_name )
184+ except Exception as e :
185+ print (e )
186+ print (f" Not able to load { import_name } . Check your installation." )
187+ print (f" mathics.builtin loads from { __file__ [:- 11 ]} " )
188+ return None
189+
190+ if module :
191+ modules .append (module )
153192
154193
155194# TODO: When we drop Python 3.7,
@@ -162,34 +201,24 @@ def import_builtins(
162201 """
163202 Imports the list of Mathics3 Built-in modules so that inside
164203 Mathics3 Builtin Functions, like Plus[], List[] are defined.
165- """
166204
167- def import_module (module_name : str , import_name : str ):
168- try :
169- module = importlib .import_module (import_name )
170- except Exception as e :
171- print (e )
172- print (f" Not able to load { module_name } . Check your installation." )
173- print (f" mathics.builtin loads from { __file__ [:- 11 ]} " )
174- return None
175-
176- if module :
177- modules .append (module )
205+ List ``module_names`` is updated.
206+ """
178207
179208 if submodule_name :
180- import_module ( submodule_name , f"mathics.builtin.{ submodule_name } " )
209+ import_builtin_module ( f"mathics.builtin.{ submodule_name } " , modules )
181210
182211 for module_name in module_names :
183212 import_name = (
184213 f"mathics.builtin.{ submodule_name } .{ module_name } "
185214 if submodule_name
186215 else f"mathics.builtin.{ module_name } "
187216 )
188- import_module ( module_name , import_name )
217+ import_builtin_module ( import_name , modules )
189218
190219
191220def import_builtin_subdirectories (
192- subdirectories : List [str ], disable_file_module_names : set , modules
221+ subdirectories : Set [str ], disable_file_module_names : set , modules
193222):
194223 """
195224 Runs import_builtisn on the each subdirectory in ``subdirectories`` that inside
@@ -209,15 +238,6 @@ def import_builtin_subdirectories(
209238 import_builtins (submodule_names , modules , subdir )
210239
211240
212- def initialize_display_operators_set ():
213- for _ , builtins in builtins_by_module .items ():
214- for builtin in builtins :
215- # name = builtin.get_name()
216- operator = builtin .get_operator_display ()
217- if operator is not None :
218- display_operators_set .add (operator )
219-
220-
221241def name_is_builtin_symbol (module : ModuleType , name : str ) -> Optional [type ]:
222242 """
223243 Checks if ``name`` should be added to definitions, and return
@@ -277,3 +297,13 @@ def name_is_builtin_symbol(module: ModuleType, name: str) -> Optional[type]:
277297 if module_object in getattr (module , "DOES_NOT_ADD_BUILTIN_DEFINITION" , []):
278298 return None
279299 return module_object
300+
301+
302+ def update_display_operators_set (builtin_instance ):
303+ """
304+ If builtin_instance is an operator of some kind, add that
305+ to the set of opererator strings ``display_operators_set``.
306+ """
307+ operator = builtin_instance .get_operator_display ()
308+ if operator is not None :
309+ display_operators_set .add (operator )
0 commit comments