diff --git a/mathics/builtin/assignments/assignment.py b/mathics/builtin/assignments/assignment.py index f3a7a68ba..f960691c5 100644 --- a/mathics/builtin/assignments/assignment.py +++ b/mathics/builtin/assignments/assignment.py @@ -11,6 +11,7 @@ assign_store_rules_by_tag, normalize_lhs, ) +from mathics.core.atoms import String from mathics.core.attributes import ( A_HOLD_ALL, A_HOLD_FIRST, @@ -66,17 +67,17 @@ class LoadModule(Builtin):
'Load Mathics definitions from the python module $module$ >> LoadModule["nomodule"] - : Python module nomodule does not exist. + : Python import errors with: No module named 'nomodule'. = $Failed >> LoadModule["sys"] - : Python module sys is not a pymathics module. + : Python module "sys" is not a Mathics3 module. = $Failed """ name = "LoadModule" messages = { - "notfound": "Python module `1` does not exist.", - "notmathicslib": "Python module `1` is not a pymathics module.", + "loaderror": """Python import errors with: `1`.""", + "notmathicslib": """Python module "`1`" is not a Mathics3 module.""", } summary_text = "load a pymathics module" @@ -87,8 +88,8 @@ def eval(self, module, evaluation): except PyMathicsLoadException: evaluation.message(self.name, "notmathicslib", module) return SymbolFailed - except ImportError: - evaluation.message(self.get_name(), "notfound", module) + except Exception as e: + evaluation.message(self.get_name(), "loaderror", String(str(e))) return SymbolFailed return module diff --git a/mathics/doc/common_doc.py b/mathics/doc/common_doc.py index 1c647325e..85c59cd69 100644 --- a/mathics/doc/common_doc.py +++ b/mathics/doc/common_doc.py @@ -23,7 +23,7 @@ More importantly, this code should be replaced by Sphinx and autodoc. Things are such a mess, that it is too difficult to contemplate this right now. """ - +import importlib import os.path as osp import pkgutil import re @@ -36,6 +36,7 @@ from mathics.core.evaluation import Message, Print from mathics.core.util import IS_PYPY from mathics.doc.utils import slugify +from mathics.eval.pymathics import pymathics_builtins_by_module, pymathics_modules # These are all the XML/HTML-like tags that documentation supports. ALLOWED_TAGS = ( @@ -357,6 +358,310 @@ def __init__(self, part: str, title: str, doc=None): self.title = title part.chapters_by_slug[self.slug] = self + def add_section( + self, + chapter, + section_name: str, + section_object, + operator, + is_guide: bool = False, + in_guide: bool = False, + ): + """ + Adds a DocSection or DocGuideSection + object to the chapter, a DocChapter object. + "section_object" is either a Python module or a Class object instance. + """ + installed = check_requires_list(getattr(section_object, "requires", [])) + + # FIXME add an additional mechanism in the module + # to allow a docstring and indicate it is not to go in the + # user manual + if not section_object.__doc__: + return + if is_guide: + section = self.doc_guide_section_fn( + chapter, + section_name, + section_object.__doc__, + section_object, + installed=installed, + ) + chapter.guide_sections.append(section) + else: + section = self.doc_section_fn( + chapter, + section_name, + section_object.__doc__, + operator=operator, + installed=installed, + in_guide=in_guide, + ) + chapter.sections.append(section) + + return section + + def add_subsection( + self, + chapter, + section, + subsection_name: str, + instance, + operator=None, + in_guide=False, + ): + installed = check_requires_list(getattr(instance, "requires", [])) + + # FIXME add an additional mechanism in the module + # to allow a docstring and indicate it is not to go in the + # user manual + + """ + Append a subsection for ``instance`` into ``section.subsections`` + """ + installed = True + for package in getattr(instance, "requires", []): + try: + importlib.import_module(package) + except ImportError: + installed = False + break + + # FIXME add an additional mechanism in the module + # to allow a docstring and indicate it is not to go in the + # user manual + if not instance.__doc__: + return + summary_text = ( + instance.summary_text if hasattr(instance, "summary_text") else "" + ) + subsection = self.doc_subsection_fn( + chapter, + section, + subsection_name, + instance.__doc__, + operator=operator, + installed=installed, + in_guide=in_guide, + summary_text=summary_text, + ) + section.subsections.append(subsection) + + def doc_part(self, title, modules, builtins_by_module, start): + """ + Produce documentation for a "Part" - reference section or + possibly Pymathics modules + """ + + builtin_part = self.doc_part_fn(self, title, is_reference=start) + modules_seen = set([]) + + want_sorting = True + if want_sorting: + module_collection_fn = lambda x: sorted( + modules, + key=lambda module: module.sort_order + if hasattr(module, "sort_order") + else module.__name__, + ) + else: + module_collection_fn = lambda x: x + for module in module_collection_fn(modules): + if skip_module_doc(module, modules_seen): + continue + title, text = get_module_doc(module) + chapter = self.doc_chapter_fn( + builtin_part, title, self.doc_fn(text, title, None) + ) + builtins = builtins_by_module[module.__name__] + sections = [ + builtin for builtin in builtins if not skip_doc(builtin.__class__) + ] + + if module.__file__.endswith("__init__.py"): + # We have a Guide Section. + name = get_doc_name_from_module(module) + guide_section = self.add_section( + chapter, name, module, operator=None, is_guide=True + ) + submodules = [ + value + for value in module.__dict__.values() + if isinstance(value, ModuleType) + ] + + sorted_submodule = lambda x: sorted( + submodules, + key=lambda submodule: submodule.sort_order + if hasattr(submodule, "sort_order") + else submodule.__name__, + ) + + # Add sections in the guide section... + for submodule in sorted_submodule(submodules): + # FIXME add an additional mechanism in the module + # to allow a docstring and indicate it is not to go in the + # user manual + + if skip_module_doc(submodule, modules_seen): + continue + elif IS_PYPY and submodule.__name__ == "builtins": + # PyPy seems to add this module on its own, + # but it is not something that can be importable + continue + + submodule_name = get_doc_name_from_module(submodule) + section = self.add_section( + chapter, + submodule_name, + submodule, + operator=None, + is_guide=False, + in_guide=True, + ) + modules_seen.add(submodule) + guide_section.subsections.append(section) + + builtins = builtins_by_module.get(submodule.__name__, []) + subsections = [builtin for builtin in builtins] + for instance in subsections: + if hasattr(instance, "no_doc") and instance.no_doc: + continue + + modules_seen.add(instance) + name = instance.get_name(short=True) + + self.add_subsection( + chapter, + section, + instance.get_name(short=True), + instance, + instance.get_operator(), + in_guide=True, + ) + else: + self.doc_sections(sections, modules_seen, chapter) + builtin_part.chapters.append(chapter) + self.parts.append(builtin_part) + + def doc_sections(self, sections, modules_seen, chapter): + for instance in sections: + if instance not in modules_seen and ( + not hasattr(instance, "no_doc") or not instance.no_doc + ): + name = instance.get_name(short=True) + self.add_section( + chapter, + name, + instance, + instance.get_operator(), + is_guide=False, + in_guide=False, + ) + modules_seen.add(instance) + + def gather_doc_data(self): + """ + Extract documentation data from various static XML-like doc files, Mathics3 Built-in functions + (inside mathics.builtin), and external Mathics3 Modules. + + The extracted structure is stored in ``self``. + """ + + # First gather data from static XML-like files. This constitutes "Part 1" of the + # documentation. + files = listdir(self.doc_dir) + files.sort() + appendix = [] + + for file in files: + part_title = file[2:] + if part_title.endswith(".mdoc"): + part_title = part_title[: -len(".mdoc")] + part = self.doc_part_fn(self, part_title) + text = open(osp.join(self.doc_dir, file), "rb").read().decode("utf8") + text = filter_comments(text) + chapters = CHAPTER_RE.findall(text) + for title, text in chapters: + chapter = self.doc_chapter_fn(part, title) + text += '
' + sections = SECTION_RE.findall(text) + for pre_text, title, text in sections: + if title: + section = self.doc_section_fn( + chapter, title, text, operator=None, installed=True + ) + chapter.sections.append(section) + subsections = SUBSECTION_RE.findall(text) + for subsection_title in subsections: + subsection = self.doc_subsection_fn( + chapter, + section, + subsection_title, + text, + ) + section.subsections.append(subsection) + pass + pass + else: + section = None + if not chapter.doc: + chapter.doc = self.doc_fn(pre_text, title, section) + pass + + part.chapters.append(chapter) + if file[0].isdigit(): + self.parts.append(part) + else: + part.is_appendix = True + appendix.append(part) + + # Next extract data that has been loaded into Mathics3 when it runs. + # This is information from `mathics.builtin`. + # This is Part 2 of the documentation. + + for title, modules, builtins_by_module, start in [ + ( + "Reference of Built-in Symbols", + builtin.modules, + builtin.builtins_by_module, + True, + ) + ]: + self.doc_part(title, modules, builtins_by_module, start) + + # Now extract external Mathics3 Modules that have been loaded via + # LoadModule, or eval_LoadModule. + + # This is Part 3 of the documentation. + + for title, modules, builtins_by_module, start in [ + ( + "Mathics3 Modules", + pymathics_modules, + pymathics_builtins_by_module, + True, + ) + ]: + self.doc_part(title, modules, builtins_by_module, start) + + # Now extract Appendix information. This include License text + + # This is the final Part of the documentation. + + for part in appendix: + self.parts.append(part) + + # Via the wanderings above, collect all tests that have been + # seen. + # + # Each test is accessble by its part + chapter + section and test number + # in that section. + for tests in self.get_tests(): + for test in tests.tests: + test.key = (tests.part, tests.chapter, tests.section, test.index) + return + def get_part(self, part_slug): return self.parts_by_slug.get(part_slug) @@ -459,7 +764,14 @@ def all_sections(self): class DocSection: def __init__( - self, chapter, title, text, operator=None, installed=True, in_guide=False + self, + chapter, + title: str, + text: str, + operator, + installed=True, + in_guide=False, + summary_text="", ): self.chapter = chapter @@ -470,7 +782,9 @@ def __init__( self.slug = slugify(title) self.subsections = [] self.subsections_by_slug = {} + self.summary_text = summary_text self.title = title + if text.count("
") != text.count("
"): raise ValueError( "Missing opening or closing
tag in " @@ -557,6 +871,7 @@ def __init__( operator=None, installed=True, in_guide=False, + summary_text="", ): """ Information that goes into a subsection object. This can be a written text, or @@ -572,6 +887,11 @@ def __init__( the "section" name for the class Read (the subsection) inside it. """ + title_summary_text = re.split(" -- ", title) + n = len(title_summary_text) + self.title = title_summary_text[0] if n > 0 else "" + self.summary_text = title_summary_text[1] if n > 1 else summary_text + self.doc = XMLDoc(text, title, section) self.chapter = chapter self.in_guide = in_guide @@ -583,10 +903,18 @@ def __init__( self.subsections = [] self.title = title + if section: + chapter = section.chapter + part = chapter.part + # Note: we elide section.title + key_prefix = (part.title, chapter.title, title) + else: + key_prefix = None + if in_guide: # Tests haven't been picked out yet from the doc string yet. # Gather them here. - self.items = gather_tests(text, DocTests, DocTest, DocText) + self.items = gather_tests(text, DocTests, DocTest, DocText, key_prefix) else: self.items = [] @@ -689,251 +1017,32 @@ def __str__(self): return self.test +# FIXME: think about - do we need this? Or can we use DjangoMathicsDocumentation and +# LatTeXMathicsDocumentation only? class MathicsMainDocumentation(Documentation): + """ + This module is used for creating test data and saving it to a Python Pickle file + and running tests that appear in the documentation (doctests). + + There are other classes DjangoMathicsDocumentation and LaTeXMathicsDocumentation + that format the data accumulated here. In fact I think those can sort of serve + instead of this. + """ + def __init__(self, want_sorting=False): + self.doc_chapter_fn = DocChapter self.doc_dir = settings.DOC_DIR + self.doc_fn = XMLDoc + self.doc_guide_section_fn = DocGuideSection + self.doc_part_fn = DocPart + self.doc_section_fn = DocSection + self.doc_subsection_fn = DocSubsection self.latex_pcl_path = settings.DOC_LATEX_DATA_PCL self.parts = [] self.parts_by_slug = {} self.pymathics_doc_loaded = False self.doc_data_file = settings.get_doc_latex_data_path(should_be_readable=True) self.title = "Overview" - files = listdir(self.doc_dir) - files.sort() - appendix = [] - - for file in files: - part_title = file[2:] - if part_title.endswith(".mdoc"): - part_title = part_title[: -len(".mdoc")] - part = DocPart(self, part_title) - text = open(osp.join(self.doc_dir, file), "rb").read().decode("utf8") - text = filter_comments(text) - chapters = CHAPTER_RE.findall(text) - for title, text in chapters: - chapter = DocChapter(part, title) - text += '
' - sections = SECTION_RE.findall(text) - for pre_text, title, text in sections: - if title: - section = DocSection( - chapter, title, text, operator=None, installed=True - ) - chapter.sections.append(section) - subsections = SUBSECTION_RE.findall(text) - for subsection_title in subsections: - subsection = DocSubsection( - chapter, - section, - subsection_title, - text, - ) - section.subsections.append(subsection) - pass - pass - else: - section = None - if not chapter.doc: - chapter.doc = XMLDoc(pre_text, title, section) - - part.chapters.append(chapter) - if file[0].isdigit(): - self.parts.append(part) - else: - part.is_appendix = True - appendix.append(part) - - for title, modules, builtins_by_module, start in [ - ( - "Reference of Built-in Symbols", - builtin.modules, - builtin.builtins_by_module, - True, - ) - ]: # nopep8 - # ("Reference of optional symbols", optional.modules, - # optional.optional_builtins_by_module, False)]: - - builtin_part = DocPart(self, title, is_reference=start) - modules_seen = set() - if want_sorting: - module_collection_fn = lambda x: sorted( - modules, - key=lambda module: module.sort_order - if hasattr(module, "sort_order") - else module.__name__, - ) - else: - module_collection_fn = lambda x: x - - for module in module_collection_fn(modules): - if skip_module_doc(module, modules_seen): - continue - title, text = get_module_doc(module) - chapter = DocChapter(builtin_part, title, XMLDoc(text, title, None)) - builtins = builtins_by_module[module.__name__] - sections = [builtin for builtin in builtins] - if module.__file__.endswith("__init__.py"): - # We have a Guide Section. - name = get_doc_name_from_module(module) - guide_section = self.add_section( - chapter, name, module, operator=None, is_guide=True - ) - submodules = [ - value - for value in module.__dict__.values() - if isinstance(value, ModuleType) - ] - - # Add sections in the guide section... - for submodule in submodules: - # FIXME add an additional mechanism in the module - # to allow a docstring and indicate it is not to go in the - # user manual - if submodule.__doc__ is None: - continue - elif IS_PYPY and submodule.__name__ == "builtins": - # PyPy seems to add this module on its own, - # but it is not something that can be importable - continue - - if submodule in modules_seen: - continue - - section = self.add_section( - chapter, - get_doc_name_from_module(submodule), - submodule, - operator=None, - is_guide=False, - in_guide=True, - ) - modules_seen.add(submodule) - guide_section.subsections.append(section) - builtins = builtins_by_module[submodule.__name__] - - subsections = [ - builtin - for builtin in builtins - if not builtin.__class__.__name__.endswith("Box") - ] - for instance in subsections: - if hasattr(instance, "no_doc") and instance.no_doc: - continue - - modules_seen.add(instance) - name = instance.get_name(short=True) - self.add_subsection( - chapter, - section, - instance.get_name(short=True), - instance, - instance.get_operator(), - in_guide=True, - ) - else: - for instance in sections: - if instance not in modules_seen and ( - not hasattr(instance, "no_doc") or not instance.no_doc - ): - name = instance.get_name(short=True) - self.add_section( - chapter, - instance.get_name(short=True), - instance, - instance.get_operator(), - is_guide=False, - in_guide=False, - ) - modules_seen.add(instance) - pass - pass - pass - builtin_part.chapters.append(chapter) - self.parts.append(builtin_part) - - for part in appendix: - self.parts.append(part) - - # set keys of tests - for tests in self.get_tests(want_sorting=want_sorting): - for test in tests.tests: - test.key = (tests.part, tests.chapter, tests.section, test.index) - - def add_section( - self, - chapter, - section_name: str, - section_object, - operator, - is_guide: bool = False, - in_guide: bool = False, - ): - """ - Adds a DocSection or DocGuideSection - object to the chapter, a DocChapter object. - "section_object" is either a Python module or a Class object instance. - """ - installed = check_requires_list(getattr(section_object, "requires", [])) - - # FIXME add an additional mechanism in the module - # to allow a docstring and indicate it is not to go in the - # user manual - if not section_object.__doc__: - return - if is_guide: - section = DocGuideSection( - chapter, - section_name, - section_object.__doc__, - section_object, - installed=installed, - ) - chapter.guide_sections.append(section) - else: - section = DocSection( - chapter, - section_name, - section_object.__doc__, - operator=operator, - installed=installed, - in_guide=in_guide, - ) - chapter.sections.append(section) - - return section - - def add_subsection( - self, - chapter, - section, - subsection_name: str, - instance, - operator=None, - in_guide=False, - ): - installed = check_requires_list(getattr(instance, "requires", [])) - - # FIXME add an additional mechanism in the module - # to allow a docstring and indicate it is not to go in the - # user manual - - if not instance.__doc__: - return - subsection = DocSubsection( - chapter, - section, - subsection_name, - instance.__doc__, - operator=operator, - installed=installed, - in_guide=in_guide, - ) - section.subsections.append(subsection) - - def load_pymathics_doc(self): - # This has always been broken. Revisit after revising Pymathics. - return class XMLDoc: @@ -1019,6 +1128,7 @@ def test_indices(self): class DocTests: def __init__(self): self.tests = [] + self.text = "" def get_tests(self): return self.tests diff --git a/mathics/doc/latex/doc2latex.py b/mathics/doc/latex/doc2latex.py index f49b2e262..7d392060b 100755 --- a/mathics/doc/latex/doc2latex.py +++ b/mathics/doc/latex/doc2latex.py @@ -17,7 +17,7 @@ import mathics from mathics import __version__, settings, version_string -from mathics.doc.latex_doc import LaTeXMathicsMainDocumentation +from mathics.doc.latex_doc import LaTeXMathicsDocumentation # Global variables logfile = None @@ -95,7 +95,7 @@ def try_cmd(cmd_list: tuple, stdout_or_stderr: str) -> str: def write_latex( doc_data, quiet=False, filter_parts=None, filter_chapters=None, filter_sections=None ): - documentation = LaTeXMathicsMainDocumentation() + documentation = LaTeXMathicsDocumentation() if not quiet: print(f"Writing LaTeX document to {DOC_LATEX_FILE}") with open_ensure_dir(DOC_LATEX_FILE, "wb") as doc: diff --git a/mathics/doc/latex_doc.py b/mathics/doc/latex_doc.py index 75a656ae3..e852d05c9 100644 --- a/mathics/doc/latex_doc.py +++ b/mathics/doc/latex_doc.py @@ -3,17 +3,12 @@ FIXME: Ditch this and hook into sphinx. """ -import os.path as osp import re -from os import getenv, listdir -from types import ModuleType +from os import getenv -from mathics import builtin, settings -from mathics.builtin.base import check_requires_list +from mathics import settings from mathics.core.evaluation import Message, Print -from mathics.core.util import IS_PYPY from mathics.doc.common_doc import ( - CHAPTER_RE, CONSOLE_RE, DL_ITEM_RE, DL_RE, @@ -28,7 +23,6 @@ PYTHON_RE, QUOTATIONS_RE, REF_RE, - SECTION_RE, SPECIAL_COMMANDS, SUBSECTION_END_RE, SUBSECTION_RE, @@ -40,17 +34,12 @@ DocTests, DocText, Documentation, - MathicsMainDocumentation, XMLDoc, _replace_all, - filter_comments, gather_tests, - get_doc_name_from_module, - get_module_doc, get_results_by_test, post_sub, pre_sub, - skip_module_doc, sorted_chapters, ) from mathics.doc.utils import slugify @@ -666,258 +655,22 @@ def latex(self, doc_data: dict): ) -class LaTeXMathicsMainDocumentation(MathicsMainDocumentation): +class LaTeXMathicsDocumentation(Documentation): def __init__(self, want_sorting=False): + self.doc_chapter_fn = LaTeXDocChapter self.doc_dir = settings.DOC_DIR + self.doc_fn = LaTeXDoc + self.doc_data_file = settings.get_doc_latex_data_path(should_be_readable=True) + self.doc_guide_section_fn = LaTeXDocGuideSection + self.doc_part_fn = LaTeXDocPart + self.doc_section_fn = LaTeXDocSection + self.doc_subsection_fn = LaTeXDocSubsection self.latex_pcl_path = settings.DOC_LATEX_DATA_PCL self.parts = [] self.parts_by_slug = {} - self.pymathics_doc_loaded = False - self.doc_data_file = settings.get_doc_latex_data_path(should_be_readable=True) self.title = "Overview" - files = listdir(self.doc_dir) - files.sort() - appendix = [] - - for file in files: - part_title = file[2:] - if part_title.endswith(".mdoc"): - part_title = part_title[: -len(".mdoc")] - part = LaTeXDocPart(self, part_title) - text = open(osp.join(self.doc_dir, file), "rb").read().decode("utf8") - text = filter_comments(text) - chapters = CHAPTER_RE.findall(text) - for title, text in chapters: - chapter = LaTeXDocChapter(part, title) - text += '
' - sections = SECTION_RE.findall(text) - for pre_text, title, text in sections: - if title: - section = LaTeXDocSection( - chapter, title, text, operator=None, installed=True - ) - chapter.sections.append(section) - subsections = SUBSECTION_RE.findall(text) - for subsection_title in subsections: - subsection = LaTeXDocSubsection( - chapter, - section, - subsection_title, - text, - ) - section.subsections.append(subsection) - pass - pass - else: - section = None - if not chapter.doc: - chapter.doc = LaTeXDoc(pre_text, title, section) - - part.chapters.append(chapter) - if file[0].isdigit(): - self.parts.append(part) - else: - part.is_appendix = True - appendix.append(part) - - for title, modules, builtins_by_module, start in [ - ( - "Reference of Built-in Symbols", - builtin.modules, - builtin.builtins_by_module, - True, - ) - ]: # nopep8 - # ("Reference of optional symbols", optional.modules, - # optional.optional_builtins_by_module, False)]: - - builtin_part = LaTeXDocPart(self, title, is_reference=start) - modules_seen = set() - if want_sorting: - module_collection_fn = lambda x: sorted( - modules, - key=lambda module: module.sort_order - if hasattr(module, "sort_order") - else module.__name__, - ) - else: - module_collection_fn = lambda x: x - for module in module_collection_fn(modules): - if skip_module_doc(module, modules_seen): - continue - title, text = get_module_doc(module) - chapter = LaTeXDocChapter( - builtin_part, title, LaTeXDoc(text, title, None) - ) - builtins = builtins_by_module[module.__name__] - # FIXME: some Box routines, like RowBox *are* - # documented - sections = [ - builtin - for builtin in builtins - if not builtin.__class__.__name__.endswith("Box") - ] - if module.__file__.endswith("__init__.py"): - # We have a Guide Section. - name = get_doc_name_from_module(module) - guide_section = self.add_section( - chapter, name, module, operator=None, is_guide=True - ) - submodules = [ - value - for value in module.__dict__.values() - if isinstance(value, ModuleType) - ] - - sorted_submodule = lambda x: sorted( - submodules, - key=lambda submodule: submodule.sort_order - if hasattr(submodule, "sort_order") - else submodule.__name__, - ) - - # Add sections in the guide section... - for submodule in sorted_submodule(submodules): - - # FIXME add an additional mechanism in the module - # to allow a docstring and indicate it is not to go in the - # user manual - if submodule.__doc__ is None: - continue - elif IS_PYPY and submodule.__name__ == "builtins": - # PyPy seems to add this module on its own, - # but it is not something that can be importable - continue - - if submodule in modules_seen: - continue - - section = self.add_section( - chapter, - get_doc_name_from_module(submodule), - submodule, - operator=None, - is_guide=False, - in_guide=True, - ) - modules_seen.add(submodule) - guide_section.subsections.append(section) - builtins = builtins_by_module[submodule.__name__] - - subsections = [ - builtin - for builtin in builtins - if not builtin.__class__.__name__.endswith("Box") - ] - for instance in subsections: - modules_seen.add(instance) - name = instance.get_name(short=True) - self.add_subsection( - chapter, - section, - instance.get_name(short=True), - instance, - instance.get_operator(), - in_guide=True, - ) - else: - for instance in sections: - if instance not in modules_seen: - name = instance.get_name(short=True) - self.add_section( - chapter, - instance.get_name(short=True), - instance, - instance.get_operator(), - is_guide=False, - in_guide=False, - ) - modules_seen.add(instance) - pass - pass - pass - builtin_part.chapters.append(chapter) - self.parts.append(builtin_part) - - for part in appendix: - self.parts.append(part) - - # set keys of tests - for tests in self.get_tests(want_sorting=want_sorting): - for test in tests.tests: - test.key = (tests.part, tests.chapter, tests.section, test.index) - - def add_section( - self, - chapter, - section_name: str, - section_object, - operator, - is_guide: bool = False, - in_guide: bool = False, - ): - """ - Adds a DocSection or DocGuideSection - object to the chapter, a DocChapter object. - "section_object" is either a Python module or a Class object instance. - """ - installed = check_requires_list(getattr(section_object, "requires", [])) - - # FIXME add an additional mechanism in the module - # to allow a docstring and indicate it is not to go in the - # user manual - if not section_object.__doc__: - return - if is_guide: - section = LaTeXDocGuideSection( - chapter, - section_name, - section_object.__doc__, - section_object, - installed=installed, - ) - chapter.guide_sections.append(section) - else: - section = LaTeXDocSection( - chapter, - section_name, - section_object.__doc__, - operator=operator, - installed=installed, - in_guide=in_guide, - ) - chapter.sections.append(section) - - return section - - def add_subsection( - self, - chapter, - section, - subsection_name: str, - instance, - operator=None, - in_guide=False, - ): - installed = check_requires_list(getattr(instance, "requires", [])) - - # FIXME add an additional mechanism in the module - # to allow a docstring and indicate it is not to go in the - # user manual - - if not instance.__doc__: - return - subsection = LaTeXDocSubsection( - chapter, - section, - subsection_name, - instance.__doc__, - operator=operator, - installed=installed, - in_guide=in_guide, - ) - section.subsections.append(subsection) + self.gather_doc_data() def latex( self, diff --git a/mathics/docpipeline.py b/mathics/docpipeline.py index de1c46a93..63234b066 100644 --- a/mathics/docpipeline.py +++ b/mathics/docpipeline.py @@ -25,8 +25,7 @@ from mathics.core.evaluation import Evaluation, Output from mathics.core.parser import MathicsSingleLineFeeder from mathics.doc.common_doc import MathicsMainDocumentation - -# from mathics.eval.pymathics import eval_LoadModule +from mathics.eval.pymathics import PyMathicsLoadException, eval_LoadModule from mathics.timing import show_lru_cache_statistics builtins = builtins_dict() @@ -486,11 +485,13 @@ def main(): help="stores the output in [logfilename]. ", ) parser.add_argument( - "--pymathics", + "--load-module", "-l", dest="pymathics", - action="store_true", - help="also checks pymathics modules.", + metavar="MATHIC3-MODULES", + help="load Mathics3 module MATHICS3-MODULES. " + "You can list multiple Mathics3 Modules by adding a comma (and no space) in between " + "module names.", ) parser.add_argument( "--time-each", @@ -554,11 +555,12 @@ def main(): action="store_true", help="print cache statistics", ) - # FIXME: there is some weird interacting going on with - # mathics when tests in sorted order. Some of the Plot - # show a noticeable 2 minute delay in processing. - # I think the problem is in Mathics itself rather than - # sorting, but until we figure that out, use + # FIXME: historically was weird interacting going on with + # mathics when tests in sorted order. Possibly a + # mpmath precsion reset bug. + # We see a noticeable 2 minute delay in processing. + # WHile the problem is in Mathics itself rather than + # sorting, until we get this fixed, use # sort as an option only. For normal testing we don't # want it for speed. But for document building which is # rarely done, we do want sorting of the sections and chapters. @@ -581,10 +583,24 @@ def main(): global documentation documentation = MathicsMainDocumentation(want_sorting=args.want_sorting) + + # LoadModule Mathics3 modules + if args.pymathics: + for module_name in args.pymathics.split(","): + try: + eval_LoadModule(module_name, definitions) + except PyMathicsLoadException: + print(f"Python module {module_name} is not a Mathics3 module.") + + except Exception as e: + print(f"Python import errors with: {e}.") + else: + print(f"Mathics3 Module {module_name} loaded") + + documentation.gather_doc_data() + if args.sections: sections = set(args.sections.split(",")) - if args.pymathics: # in case the section is in a pymathics module... - documentation.load_pymathics_doc() test_sections( sections, @@ -594,18 +610,12 @@ def main(): ) elif args.chapters: chapters = set(args.chapters.split(",")) - if args.pymathics: # in case the section is in a pymathics module... - documentation.load_pymathics_doc() test_chapters( chapters, stop_on_failure=args.stop_on_failure, reload=args.reload ) else: - # if we want to check also the pymathics modules - if args.pymathics: - print("Building pymathics documentation object") - documentation.load_pymathics_doc() - elif args.doc_only: + if args.doc_only: extract_doc_from_source( quiet=args.quiet, reload=args.reload,