Skip to content

Commit b8569c6

Browse files
committed
Some tweaks to the doc building. Doc submodules...
* docs.py: - remove/replace some undefined functions - blacken file - start to understand structure of modules under builtins * `buiiltin/*/__init__.py`: start adding documentation * test.py: - add `-x` shorthand for stop on failure - blacken
1 parent 3b130d3 commit b8569c6

7 files changed

Lines changed: 128 additions & 45 deletions

File tree

mathics/builtin/__init__.py

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,26 +85,37 @@ def get_module_doc(module):
8585
return title, text
8686

8787
def import_builtins(module_names: List[str], submodule_name=None) -> None:
88-
for module_name in module_names:
89-
import_name = (
90-
f"mathics.builtin.{submodule_name}.{module_name}"
91-
if submodule_name
92-
else f"mathics.builtin.{module_name}"
93-
)
88+
"""
89+
Imports the list of Mathics Built-in modules so that inside
90+
Mathics we have these Builtin Functions, like Plus[], List[] are defined.
91+
92+
"""
93+
def import_module(module_name: str, import_name: str):
9494
try:
9595
module = importlib.import_module(import_name)
9696
except Exception as e:
9797
print(e)
9898
print(f" Not able to load {module_name}. Check your installation.")
9999
print(f" mathics.builtin loads from {__file__[:-11]}")
100-
continue
100+
return None
101101

102102
if __version__ != module.__version__:
103103
print(
104-
f"Version {module.__version__} in the module do not match with {__version__}"
104+
f"Version {module.__version__} in the module does not match top-level Mathics version {__version__}"
105105
)
106+
if module:
107+
modules.append(module)
106108

107-
modules.append(module)
109+
if submodule_name:
110+
import_module(submodule_name, f"mathics.builtin.{submodule_name}")
111+
112+
for module_name in module_names:
113+
import_name = (
114+
f"mathics.builtin.{submodule_name}.{module_name}"
115+
if submodule_name
116+
else f"mathics.builtin.{module_name}"
117+
)
118+
import_module(module_name, import_name)
108119

109120

110121
def is_builtin(var):
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,25 @@
11
"""
22
Graphics, Drawing, and Images
3+
4+
Functions like 'Plot' and 'ListPlot' can be used to draw graphs of functions and data.
5+
6+
Graphics is implemented as a collection of <i>graphics primitives</i>. Primatives are objects like 'Point', 'Line', and 'Polygon' and become elements of a <i>graphics object</i>.
7+
8+
A graphics object can have directives as well such as 'RGBColor', and 'Thickness'.
9+
10+
There are several kinds of graphics objects; each kind has a head which identifies its type.
11+
12+
>> ListPlot[ Table[Prime[n], {n, 20} ]]
13+
= -Graphics-
14+
>> Head[%]
15+
= Graphics
16+
>> Graphics3D[Sphere[]]
17+
= -Graphics3D-
18+
>> Head[%]
19+
= Graphics3D
20+
>>
21+
22+
323
"""
24+
25+
from mathics.version import __version__ # noqa used in loading to check consistency.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
"""
22
Input/Output, Files, and Filesystem
33
"""
4+
5+
from mathics.version import __version__ # noqa used in loading to check consistency.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
"""
22
Integer and Number-Theoretical Functions
33
"""
4+
5+
from mathics.version import __version__ # noqa used in loading to check consistency.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
11
"""
22
Special Functions
3+
4+
There are a number of functions found in mathematical physics and found in standard handbooks.
5+
6+
One thing to note is that the technical literature often contains several conflicting definitions. So beware and check for conformance with the Mathics documentation.
7+
8+
A number of special functions can be evaluated for arbitrary complex values of their arguments. However defining relations may apply only for some special choices of arguments. Here, the full function corresponds to an extension or "analytic continuation" of the defining relation.
9+
10+
For example, integral representations of functions are only valid when the integral exists, but the functions can usually be defined b by analytic continuation.
11+
312
"""
13+
14+
from mathics.version import __version__ # noqa used in loading to check consistency.

mathics/doc/doc.py

Lines changed: 52 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
# -*- coding: utf-8 -*-
22

3+
from html import escape as html_escape
34
import re
4-
from os import getenv, listdir, path
5+
from os import getenv, listdir
56
import pickle
67
import importlib
8+
import pkgutil
79

810
from mathics import settings
911

@@ -109,6 +111,15 @@
109111
except IOError:
110112
xml_data = {}
111113

114+
def get_submodule_names(object):
115+
modpkgs = []
116+
if hasattr(object, '__path__'):
117+
for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
118+
modpkgs.append(modname)
119+
modpkgs.sort()
120+
return modpkgs
121+
122+
112123

113124
def filter_comments(doc):
114125
return "\n".join(
@@ -241,21 +252,23 @@ def repl_list(match):
241252
[
242253
("$", r"\$"),
243254
("\u03c0", r"$\pi$"),
244-
("", r"$\ge$"),
245-
("", r"$\le$"),
246-
("", r"$\ne$"),
247-
("ç", r"\c{c}"),
248-
("é", r"\'e"),
249-
("ê", r"\^e"),
250-
("ñ", r"\~n"),
251-
("", r"\int"),
252-
("", r"d"),
255+
(" ", r"$\ge$"),
256+
(" ", r"$\le$"),
257+
(" ", r"$\ne$"),
258+
("\u00e7", r"\c{c}"),
259+
("\u00e9", r"\'e"),
260+
("\u00ea", r"\^e"),
261+
("\00f1", r"\~n"),
262+
("\u222b", r"\int"),
263+
("\uf74c", r"d"),
253264
],
254265
)
255266

256267
def repl_char(match):
257268
char = match.group(1)
258-
return {"^": "$^\wedge$",}[char]
269+
return {
270+
"^": "$^\wedge$",
271+
}[char]
259272

260273
text = LATEX_CHAR_RE.sub(repl_char, text)
261274

@@ -474,6 +487,7 @@ def post_sub(text, post_substitutions):
474487
return text
475488

476489

490+
# FIXME: can we replace this with Python 3's html.escape ?
477491
def escape_html(text, verbatim_mode=False, counters=None, single_line=False):
478492
def repl_python(match):
479493
return (
@@ -614,7 +628,8 @@ def repl_subsection(match):
614628
text = text.replace("\\" + key, xml)
615629

616630
if not single_line:
617-
text = linebreaks(text)
631+
# FIXME: linebreaks() is not defined
632+
# text = linebreaks(text)
618633
text = text.replace("<br />", "\n").replace("<br>", "<br />")
619634

620635
text = post_sub(text, post_substitutions)
@@ -654,7 +669,7 @@ def get_prev_next(self):
654669
return prev, next
655670

656671
def get_title_html(self):
657-
return mark_safe(escape_html(self.title, single_line=True))
672+
return escape_html(self.title, single_line=True)
658673

659674

660675
class Documentation(DocElement):
@@ -788,21 +803,36 @@ def __init__(self):
788803
title, text = get_module_doc(module)
789804
chapter = DocChapter(builtin_part, title, Doc(text))
790805
builtins = builtins_by_module[module.__name__]
791-
for instance in builtins:
806+
807+
if module.__file__.endswith("__init__.py"):
808+
section_names = get_submodule_names(module)
809+
else:
810+
section_names = builtins
811+
812+
for instance in section_names:
792813
installed = True
793814
for package in getattr(instance, "requires", []):
794815
try:
795816
importlib.import_module(package)
796817
except ImportError:
797818
installed = False
798819
break
799-
section = DocSection(
800-
chapter,
801-
strip_system_prefix(instance.get_name()),
802-
instance.__doc__ or "",
803-
operator=instance.get_operator(),
804-
installed=installed,
805-
)
820+
if isinstance(instance, str):
821+
section = DocSection(
822+
chapter,
823+
instance,
824+
"",
825+
None,
826+
installed=installed,
827+
)
828+
else:
829+
section = DocSection(
830+
chapter,
831+
strip_system_prefix(instance.get_name()),
832+
instance.__doc__ or "",
833+
operator=instance.get_operator(),
834+
installed=installed,
835+
)
806836
chapter.sections.append(section)
807837
builtin_part.chapters.append(chapter)
808838
self.parts.append(builtin_part)
@@ -1167,7 +1197,7 @@ def latex(self, output):
11671197

11681198
def html(self):
11691199
counters = {}
1170-
return mark_safe(
1200+
return html_escape(
11711201
"\n".join(
11721202
item.html(counters) for item in self.items if not item.is_private()
11731203
)

mathics/test.py

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,10 @@
1515
from mathics.core.parser import MathicsSingleLineFeeder
1616
from mathics.builtin import builtins_dict
1717

18-
builtins = builtins_dict()
19-
2018
from mathics import version_string
2119
from mathics import settings
2220

23-
21+
builtins = builtins_dict()
2422

2523

2624
class TestOutput(Output):
@@ -47,6 +45,7 @@ def print_and_log(*args):
4745
if logfile:
4846
logfile.write(string)
4947

48+
5049
def compare(result, wanted):
5150
if result == wanted:
5251
return True
@@ -93,16 +92,15 @@ def fail(why):
9392
time_parsing = datetime.now()
9493
query = evaluation.parse_feeder(feeder)
9594
if check_partial_enlapsed_time:
96-
print(" parsing took", datetime.now()-time_parsing)
95+
print(" parsing took", datetime.now() - time_parsing)
9796
if query is None:
9897
# parsed expression is None
9998
result = None
10099
out = evaluation.out
101100
else:
102-
time_evaluating = datetime.now()
103101
result = evaluation.evaluate(query)
104102
if check_partial_enlapsed_time:
105-
print(" evaluation took", datetime.now()-time_parsing)
103+
print(" evaluation took", datetime.now() - time_parsing)
106104
out = result.out
107105
result = result.result
108106
except Exception as exc:
@@ -114,7 +112,7 @@ def fail(why):
114112
time_comparing = datetime.now()
115113
comparison_result = compare(result, wanted)
116114
if check_partial_enlapsed_time:
117-
print(" comparison took ", datetime.now()-time_comparing)
115+
print(" comparison took ", datetime.now() - time_comparing)
118116
if not comparison_result:
119117
print("result =!=wanted")
120118
fail_msg = "Result: %s\nWanted: %s" % (result, wanted)
@@ -132,7 +130,7 @@ def fail(why):
132130
output_ok = False
133131
break
134132
if check_partial_enlapsed_time:
135-
print(" comparing messages took ", datetime.now()-time_comparing)
133+
print(" comparing messages took ", datetime.now() - time_comparing)
136134
if not output_ok:
137135
return fail(
138136
"Output:\n%s\nWanted:\n%s"
@@ -199,7 +197,6 @@ def test_section(sections: set, quiet=False, stop_on_failure=False):
199197
sections |= {"$" + s for s in sections}
200198
for tests in documentation.get_tests():
201199
if tests.section in sections:
202-
found = True
203200
for test in tests.tests:
204201
if test.ignore:
205202
continue
@@ -366,11 +363,19 @@ def main():
366363
"--version", "-v", action="version", version="%(prog)s " + mathics.__version__
367364
)
368365
parser.add_argument(
369-
"--sections", "-s", dest="section", metavar="SECTION", help="only test SECTION(s). "
370-
"You can list multiple sections by adding a comma (and no space) in between section names."
366+
"--sections",
367+
"-s",
368+
dest="section",
369+
metavar="SECTION",
370+
help="only test SECTION(s). "
371+
"You can list multiple sections by adding a comma (and no space) in between section names.",
371372
)
372373
parser.add_argument(
373-
"--logfile", "-f", dest="logfilename", metavar="LOGFILENAME", help="stores the output in [logfilename]. "
374+
"--logfile",
375+
"-f",
376+
dest="logfilename",
377+
metavar="LOGFILENAME",
378+
help="stores the output in [logfilename]. ",
374379
)
375380
parser.add_argument(
376381
"--pymathics",
@@ -418,7 +423,7 @@ def main():
418423
help="create documentation even if there is a test failure",
419424
)
420425
parser.add_argument(
421-
"--stop-on-failure", action="store_true", help="stop on failure"
426+
"--stop-on-failure", "-x", action="store_true", help="stop on failure"
422427
)
423428
parser.add_argument(
424429
"--skip",
@@ -443,7 +448,7 @@ def main():
443448
# If a test for a specific section is called
444449
# just test it
445450
if args.logfilename:
446-
logfile = open(args.logfilename,"wt")
451+
logfile = open(args.logfilename, "wt")
447452

448453
if args.section:
449454
sections = set(args.section.split(","))

0 commit comments

Comments
 (0)