Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A second pass at redoing load_builtin.py #899

Merged
merged 2 commits into from
Aug 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 86 additions & 56 deletions mathics/core/load_builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
import pkgutil
from glob import glob
from types import ModuleType
from typing import List, Optional
from typing import Dict, List, Optional, Set

from mathics.core.convert.sympy import mathics_to_sympy, sympy_to_mathics
from mathics.core.pattern import pattern_objects
from mathics.core.symbols import Symbol
from mathics.eval.makeboxes import builtins_precedence
Expand All @@ -27,11 +28,55 @@
mathics3_builtins_modules: List[ModuleType] = []

_builtins = {}
builtins_by_module = {}
display_operators_set = set()

# builtins_by_module gives a way of mapping a Python module name
# e.g. 'mathics.builtin.arithmetic' to the list of Builtin class instances
# that appear inside that module, e.g. for key 'mathics.builtin.arithmetic' we
# have:
# [<mathics.builtin.arithmetic.Arg object>, <mathics.builtin.arithmetic.Assuming object, ...]
#
builtins_by_module: Dict[str, list] = {}

# The fact that are importing inside here, suggests add_builtins
# Set operators strings, unary, binary, or ternary.
# For example "!, "!!", ^, "+", "-", ">=", "===", "<<", etc.
display_operators_set: Set[str] = set()


def add_builtins_from_builtin_module(module: ModuleType, builtins_list: list):
"""
Process a modules which contains Builtin classes so that the
class is imported in the Python sense but also that we
have information added to module variable ``builtins_by_module``.

"""
from mathics.core.builtin import Builtin

builtins_by_module[module.__name__] = []
module_vars = dir(module)

for name in module_vars:
builtin_class = name_is_builtin_symbol(module, name)
if builtin_class is not None:
instance = builtin_class(expression=False)

if isinstance(instance, Builtin):
# This set the default context for symbols in mathics.builtins
if not type(instance).context:
type(instance).context = "System`"
builtins_list.append((instance.get_name(), instance))
builtins_by_module[module.__name__].append(instance)
update_display_operators_set(instance)


def add_builtins_from_builtin_modules(modules: List[ModuleType]):
builtins_list = []
for module in modules:
add_builtins_from_builtin_module(module, builtins_list)
add_builtins(builtins_list)
return builtins_by_module


# The fact that we are importing inside here, suggests add_builtins
# should get moved elsewhere.
def add_builtins(new_builtins):
from mathics.core.builtin import (
Expand All @@ -40,7 +85,6 @@ def add_builtins(new_builtins):
SympyObject,
mathics_to_python,
)
from mathics.core.convert.sympy import mathics_to_sympy, sympy_to_mathics

for _, builtin in new_builtins:
name = builtin.get_name()
Expand All @@ -54,37 +98,13 @@ def add_builtins(new_builtins):
# print("XXX1", sympy_name)
sympy_to_mathics[sympy_name] = builtin
if isinstance(builtin, Operator):
assert builtin.precedence is not None
builtins_precedence[Symbol(name)] = builtin.precedence
if isinstance(builtin, PatternObject):
pattern_objects[name] = builtin.__class__
_builtins.update(dict(new_builtins))


def add_builtins_from_builtin_modules(modules: List[ModuleType]):
# This can be put at the top after mathics.builtin.__init__
# cleanup is done.
from mathics.core.builtin import Builtin

builtins_list = []
for module in modules:
builtins_by_module[module.__name__] = []
module_vars = dir(module)

for name in module_vars:
builtin_class = name_is_builtin_symbol(module, name)
if builtin_class is not None:
instance = builtin_class(expression=False)

if isinstance(instance, Builtin):
# This set the default context for symbols in mathics.builtins
if not type(instance).context:
type(instance).context = "System`"
builtins_list.append((instance.get_name(), instance))
builtins_by_module[module.__name__].append(instance)
add_builtins(builtins_list)
return builtins_by_module


def builtins_dict(builtins_by_module):
return {
builtin.get_name(): builtin
Expand Down Expand Up @@ -143,13 +163,32 @@ def import_and_load_builtins():
# server, we disallow local file access.
disable_file_module_names = set() if ENABLE_FILES_MODULE else {"files_io"}

subdirectories = next(os.walk(builtin_path))[1]
subdirectory_list = next(os.walk(builtin_path))[1]
subdirectories = set(subdirectory_list) - set("__pycache__")
import_builtin_subdirectories(
subdirectories, disable_file_module_names, mathics3_builtins_modules
)

add_builtins_from_builtin_modules(mathics3_builtins_modules)
initialize_display_operators_set()


def import_builtin_module(import_name: str, modules: List[ModuleType]):
"""
Imports ``the list of Mathics3 Built-in modules so that inside
Mathics3 Builtin Functions, like Plus[], List[] are defined.

List ``module_names`` is updated.
"""
try:
module = importlib.import_module(import_name)
except Exception as e:
print(e)
print(f" Not able to load {import_name}. Check your installation.")
print(f" mathics.builtin loads from {__file__[:-11]}")
return None

if module:
modules.append(module)


# TODO: When we drop Python 3.7,
Expand All @@ -162,34 +201,24 @@ def import_builtins(
"""
Imports the list of Mathics3 Built-in modules so that inside
Mathics3 Builtin Functions, like Plus[], List[] are defined.
"""

def import_module(module_name: str, import_name: str):
try:
module = importlib.import_module(import_name)
except Exception as e:
print(e)
print(f" Not able to load {module_name}. Check your installation.")
print(f" mathics.builtin loads from {__file__[:-11]}")
return None

if module:
modules.append(module)
List ``module_names`` is updated.
"""

if submodule_name:
import_module(submodule_name, f"mathics.builtin.{submodule_name}")
import_builtin_module(f"mathics.builtin.{submodule_name}", modules)

for module_name in module_names:
import_name = (
f"mathics.builtin.{submodule_name}.{module_name}"
if submodule_name
else f"mathics.builtin.{module_name}"
)
import_module(module_name, import_name)
import_builtin_module(import_name, modules)


def import_builtin_subdirectories(
subdirectories: List[str], disable_file_module_names: set, modules
subdirectories: Set[str], disable_file_module_names: set, modules
):
"""
Runs import_builtisn on the each subdirectory in ``subdirectories`` that inside
Expand All @@ -209,15 +238,6 @@ def import_builtin_subdirectories(
import_builtins(submodule_names, modules, subdir)


def initialize_display_operators_set():
for _, builtins in builtins_by_module.items():
for builtin in builtins:
# name = builtin.get_name()
operator = builtin.get_operator_display()
if operator is not None:
display_operators_set.add(operator)


def name_is_builtin_symbol(module: ModuleType, name: str) -> Optional[type]:
"""
Checks if ``name`` should be added to definitions, and return
Expand Down Expand Up @@ -277,3 +297,13 @@ def name_is_builtin_symbol(module: ModuleType, name: str) -> Optional[type]:
if module_object in getattr(module, "DOES_NOT_ADD_BUILTIN_DEFINITION", []):
return None
return module_object


def update_display_operators_set(builtin_instance):
"""
If builtin_instance is an operator of some kind, add that
to the set of opererator strings ``display_operators_set``.
"""
operator = builtin_instance.get_operator_display()
if operator is not None:
display_operators_set.add(operator)
1 change: 1 addition & 0 deletions mathics/data/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/doc_latex_data.pcl
/doctest_latex_data.pcl
/op-tables.json
1 change: 1 addition & 0 deletions mathics/doc/latex/.gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/core-version.tex
/doc_latex_data.pcl
/documentation.log
/documentation.tex
/documentation.tex-before-sed
/images/
Expand Down
Loading