Skip to content

Commit 9079351

Browse files
committed
Merge remote-tracking branch 'upstream/master' into useasyforxmlgraphics
2 parents a4d8ec5 + 349ea11 commit 9079351

16 files changed

Lines changed: 418 additions & 225 deletions

CHANGES.rst

Lines changed: 79 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,81 @@ CHANGES
44
2.0.0
55
-----
66

7-
The Django front-end has been unbundled and is a separate `PyPI installable package <https://pypi.org/project/Mathics-Django/>`_.
7+
In order to accomdate growth and increase use pieces of Mathics inside other packages, some parts of
8+
Mathics have been split off and moved to separately installable packages. In particular:
9+
10+
* The Django front-end `PyPI installable package <https://pypi.org/project/Mathics-Django/>`_.
11+
* Scanner routines and character translations tables to/from unicode and noting some character properties
12+
* Specific builtins involving heavy, non-standard routines were moved to pymathics modules.
13+
14+
15+
Incompatible changes:
16+
+++++++++++++++++++++
17+
18+
* `-e` `--execute` is better suited for embedded use. It shows just evaluation output as text.
19+
820

921
New builtins
10-
++++++++++++++
22+
++++++++++++
1123

1224
- ``TimeRemaining`` and ``TimeConstrained``
1325
-``MathicsVersion`` (this is not in WL)
1426
- ``\[RadicalBox]``
15-
- ``FirstCase``, ``Lookup``
16-
- ``Catalan``, ``LerchPhi``
17-
- ``System`ConvertersDump`` context variables
27+
- ``ContinuedFraction``
28+
- ``Insert`` and ``Delete``
29+
- ``FirstCase``, ``Lookup``, ``Key``, ``Lookup`` and ``Failure``
30+
- ``ConvertCommonDumpRemoveLinearSyntax`` and ``System`ConvertersDump`` context variables
31+
- ``PossibleZeroQ`` PR #1100
32+
- ``Run``
33+
- ``SympyObject``
34+
- ``NumberQ``
35+
- ``AnglePath``, ``AnglePathFold``, ``AngleVector``
36+
- ``Haversine``, ``InverseHaversine``
37+
- ``Show``
38+
- Improving support for options in the Plot module: ``Axes``, ``Filling``, ``ImageSize``, ``Joined``
39+
- ``BoxData``, ``TextData``, ``InterpretationBox``, ``StyleBox``, ``TagBox``, ``TemplateBox``, ``ButtonBox``, ``InterpretationBox``
40+
- ``LerchPhi``
41+
42+
New Constants
43+
+++++++++++++
44+
45+
Mathematical Constants is now its own module/section. Contants have been filled out.
46+
These constants have been added:
47+
48+
- ``Catalan``
49+
- ``Glaisher``
50+
- ``Khinchin``
51+
- ``Degree``
52+
- ``GoldenRatio``
53+
- ``Khinchin``
54+
55+
56+
Many of these and the existing constants are computable via mpmath, numpy, or sympy.
57+
58+
59+
Settings through WL variables
60+
-----------------------------
61+
62+
Certain aspects of the configuration of the kernel are now controlled by variables, defined in /autoad/settings.m
63+
64+
- ``$GetTrace`` (``False`` by default). Defines if when a WL module is load through ``Get``, definitions will be traced (for debug).
65+
- ``$PreferredBackendMethod`` Set this do whether to use mpmath, numpy or Sympy for numeric and symbolic constants and methods when there is s choice (``"sympy"`` by default) (see #1124)
66+
67+
68+
Enhancements
69+
------------
70+
71+
- Add ``Method`` option "mpmath" to compute ``Eignevalues`` using mpmath (#1115).
72+
- Improving the support for OptionValue and OptionsPattern (#1113)
73+
74+
75+
Bug Fixes
76+
---------
77+
78+
There have been numerous bug is driven by working on Combinatorica V0.9 and CellsToTeX.
79+
80+
- ``Sum`` involving numeric integer bounds involving Mathics functions fixed.
81+
- ``Equal`` ``UnEqual`` testing on Strings (#1128).
1882

1983
Document updates
2084
----------------
@@ -32,6 +96,14 @@ Enhancements and Bug fixes:
3296
- Set the numeric threshold in PossibleZeroQ to 10^(-10), for compatibility with ``System`Chop``.
3397
- Catch possible exceptions generated by ``$UserName``.
3498

99+
100+
Miscelanea
101+
----------
102+
103+
- Enlarge of the set of gries_schneider tests
104+
- Improvement in the way builtins modules are loaded at initialization time (#1138).
105+
106+
35107
1.1.1
36108
-----
37109

@@ -51,7 +123,7 @@ Package Updates
51123

52124
Mathics Packages added:
53125

54-
- ``DiscreteMath`CombinatoricaV0.9`` (preferred) aand
126+
- ``DiscreteMath`CombinatoricaV0.9`` (preferred) and
55127
``DiscreteMath`CombinatoricaV0.6``.
56128

57129
Both of these correspond to Steven Skiena's *older* book: "Implementing Discrete Mathematics: Combinatorics and Graph Theory" book.
@@ -93,7 +165,7 @@ New builtins:
93165
- Adding support in ``from_python()`` to convert dictionaries in list of rules.
94166
- Fix OptionsPattern associated symbols.
95167

96-
168+
97169
1.1.0
98170
-----
99171

mathics/builtin/__init__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#!/usr/bin/env python3
22
# -*- coding: utf-8 -*-
3+
from mathics.core.expression import ensure_context
34

45
import glob
56
import importlib
@@ -71,7 +72,10 @@ def is_builtin(var):
7172
instance = var(expression=False)
7273

7374
if isinstance(instance, Builtin):
74-
builtins.append((instance.get_name(), instance))
75+
# This set the default context for symbols in mathics.builtins
76+
if not type(instance).context:
77+
type(instance).context = "System`"
78+
builtins.append( (instance.get_name(), instance))
7579
builtins_by_module[module.__name__].append(instance)
7680

7781

mathics/builtin/assignment.py

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1748,20 +1748,17 @@ def apply(self, module, evaluation):
17481748
except ImportError as e:
17491749
evaluation.message(self.get_name(), 'notfound', module)
17501750
return SymbolFailed
1751-
except PyMathicsLoadException as e:
1752-
evaluation.message(self.get_name(), 'notmathicslib', module)
1753-
return SymbolFailed
1754-
else:
1755-
# Add PyMathics` to $ContextPath so that when user don't
1756-
# have to qualify PyMathics variables and functions,
1757-
# as the those in the module just loaded.
1758-
1759-
# Following the example of $ContextPath in the WL
1760-
# reference manual where PackletManager appears first in
1761-
# the list, it seems to be preferable to add this PyMathics
1762-
# at the beginning.
1763-
context_path = evaluation.definitions.get_context_path()
1764-
if "PyMathics`" not in context_path:
1765-
context_path.insert(0, "PyMathics`")
1766-
evaluation.definitions.set_context_path(context_path)
1751+
1752+
# Add PyMathics` to $ContextPath so that when user don't
1753+
# have to qualify PyMathics variables and functions,
1754+
# as the those in the module just loaded.
1755+
# Following the example of $ContextPath in the WL
1756+
# reference manual where PackletManager appears first in
1757+
# the list, it seems to be preferable to add this PyMathics
1758+
# at the beginning.
1759+
context_path = evaluation.definitions.get_context_path()
1760+
if "PyMathics`" not in context_path:
1761+
context_path.insert(0, "PyMathics`")
1762+
evaluation.definitions.set_context_path(context_path)
1763+
17671764
return module

mathics/builtin/base.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,20 +34,17 @@ def get_option(options, name, evaluation, pop=False, evaluate=True):
3434
# matter. Also, the quoted string form "X" is ok. all these
3535
# variants name the same option. this matches Wolfram Language
3636
# behaviour.
37-
37+
name = strip_context(name)
3838
contexts = (s + "%s" for s in evaluation.definitions.get_context_path())
3939

4040
for variant in chain(contexts, ('"%s"',)):
4141
resolved_name = variant % name
42-
4342
if pop:
4443
value = options.pop(resolved_name, None)
4544
else:
4645
value = options.get(resolved_name)
47-
4846
if value is not None:
4947
return value.evaluate(evaluation) if evaluate else value
50-
5148
return None
5249

5350

@@ -60,7 +57,7 @@ def has_option(options, name, evaluation):
6057

6158
class Builtin(object):
6259
name: typing.Optional[str] = None
63-
context = "System`"
60+
context = ""
6461
abstract = False
6562
attributes: typing.Tuple[Any, ...] = ()
6663
rules: typing.Dict[str, Any] = {}
@@ -87,11 +84,11 @@ def __init__(self, *args, **kwargs):
8784

8885
def contribute(self, definitions, is_pymodule=False):
8986
from mathics.core.parser import parse_builtin_rule
87+
# Set the default context
88+
if not self.context:
89+
self.context = "Pymathics`" if is_pymodule else "System`"
9090

91-
if is_pymodule:
92-
name = "PyMathics`" + self.get_name(short=True)
93-
else:
94-
name = self.get_name()
91+
name = self.get_name()
9592

9693
options = {}
9794
option_syntax = "Warn"
@@ -317,7 +314,7 @@ def get_functions(self, prefix="apply", is_pymodule=False):
317314
else:
318315
attrs = []
319316
if is_pymodule:
320-
name = "PyMathics`" + self.get_name(short=True)
317+
name = ensure_context(self.get_name(short=True), "Pymathics")
321318
else:
322319
name = self.get_name()
323320

@@ -768,3 +765,4 @@ def from_expression(expr):
768765
return CountableInteger(0, upper_limit=True)
769766

770767
return None # leave original expression unevaluated
768+

mathics/builtin/files.py

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3813,6 +3813,8 @@ class FileHash(Builtin):
38133813
<dt>'FileHash[$file$, $type$]'
38143814
<dd>returns an integer hash of the specified $type$ for the given $file$.</dd>
38153815
<dd>The types supported are "MD5", "Adler32", "CRC32", "SHA", "SHA224", "SHA256", "SHA384", and "SHA512".</dd>
3816+
<dt>'FileHash[$file$, $type$, $format$]'
3817+
<dd>gives a hash code in the specified format.</dd>
38163818
</dl>
38173819
38183820
>> FileHash["ExampleData/sunflowers.jpg"]
@@ -3841,19 +3843,20 @@ class FileHash(Builtin):
38413843
#> FileHash["ExampleData/sunflowers.jpg", xyzsymbol]
38423844
= FileHash[ExampleData/sunflowers.jpg, xyzsymbol]
38433845
#> FileHash["ExampleData/sunflowers.jpg", "xyzstr"]
3844-
= FileHash[ExampleData/sunflowers.jpg, xyzstr]
3846+
= FileHash[ExampleData/sunflowers.jpg, xyzstr, Integer]
38453847
#> FileHash[xyzsymbol]
38463848
= FileHash[xyzsymbol]
38473849
"""
38483850

38493851
rules = {
3850-
"FileHash[filename_String]": 'FileHash[filename, "MD5"]',
3852+
"FileHash[filename_String]": 'FileHash[filename, "MD5", "Integer"]',
3853+
"FileHash[filename_String, hashtype_String]": 'FileHash[filename, hashtype, "Integer"]',
38513854
}
38523855

38533856
attributes = ("Protected", "ReadProtected")
38543857

3855-
def apply(self, filename, hashtype, evaluation):
3856-
"FileHash[filename_String, hashtype_String]"
3858+
def apply(self, filename, hashtype, format, evaluation):
3859+
"FileHash[filename_String, hashtype_String, format_String]"
38573860
py_filename = filename.get_string_value()
38583861

38593862
try:
@@ -3866,7 +3869,7 @@ def apply(self, filename, hashtype, evaluation):
38663869
e.message(evaluation)
38673870
return
38683871

3869-
return Hash.compute(lambda update: update(dump), hashtype.get_string_value())
3872+
return Hash.compute(lambda update: update(dump), hashtype.get_string_value(), format.get_string_value())
38703873

38713874

38723875
class FileDate(Builtin):
@@ -4802,6 +4805,7 @@ def apply(self, pathname, evaluation):
48024805
return SymbolTrue
48034806
return SymbolFalse
48044807

4808+
48054809
class Needs(Builtin):
48064810
"""
48074811
<dl>
@@ -4921,7 +4925,6 @@ def apply(self, context, evaluation):
49214925
curr_ctxt = evaluation.definitions.get_current_context()
49224926
contextstr = curr_ctxt + contextstr[1:]
49234927
context = String(contextstr)
4924-
49254928
if not valid_context_name(contextstr):
49264929
evaluation.message('Needs', 'ctx', Expression(
49274930
'Needs', context), 1, '`')
@@ -4931,19 +4934,11 @@ def apply(self, context, evaluation):
49314934
if test_loaded.is_true():
49324935
# Already loaded
49334936
return SymbolNull
4934-
4935-
# TODO: Figure out why this raises the message:
4936-
# "Select::normal: Nonatomic expression expected."
4937-
already_loaded = Expression('MemberQ',
4938-
Symbol('System`$Packages'), context)
4939-
already_loaded = already_loaded.evaluate(evaluation).is_true()
4940-
if already_loaded:
4941-
return SymbolNull
4942-
49434937
result = Expression('Get', context).evaluate(evaluation)
49444938

49454939
if result == SymbolFailed:
49464940
evaluation.message("Needs", "nocont", context)
49474941
return SymbolFailed
49484942

49494943
return SymbolNull
4944+

mathics/builtin/functional.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ class Function(PostfixOperator):
1919
<dd>represents a pure function with parameters '#1', '#2', etc.
2020
<dt>'Function[{$x1$, $x2$, ...}, $body$]'
2121
<dd>represents a pure function with parameters $x1$, $x2$, etc.
22+
<dt>'Function[{$x1$, $x2$, ...}, $body$, $attr$]'
23+
<dd>assume that the function has the attributes $attr$.
2224
</dl>
2325
2426
>> f := # ^ 2 &
@@ -87,6 +89,22 @@ def apply_named(self, vars, body, args, evaluation):
8789
var.get_name() for var in vars), args[:len(vars)])))
8890
return body.replace_vars(vars)
8991

92+
# Not sure if DRY is possible here...
93+
def apply_named_attr(self, vars, body, attr, args, evaluation):
94+
'Function[vars_, body_, attr_][args___]'
95+
if vars.has_form('List', None):
96+
vars = vars.leaves
97+
else:
98+
vars = [vars]
99+
100+
args = args.get_sequence()
101+
if len(vars) > len(args):
102+
evaluation.message('Function', 'fpct', )
103+
else:
104+
vars = dict(list(zip((
105+
var.get_name() for var in vars), args[:len(vars)])))
106+
return body.replace_vars(vars)
107+
90108

91109
class Slot(Builtin):
92110
"""

mathics/builtin/importexport.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,34 @@ class ExportFormats(Predefined):
228228
def evaluate(self, evaluation):
229229
return Expression('List', *sorted(EXPORTERS.keys()))
230230

231+
class ConverterDumpsExtensionMappings(Predefined):
232+
"""
233+
<dl>
234+
<dt>'$extensionMappings'
235+
<dd>Returns a list of associations between file extensions and file types.
236+
</dl>
237+
"""
238+
context = 'System`ConvertersDump`'
239+
name = "$extensionMappings"
240+
attributes = ['Unprotected']
241+
242+
def evaluate(self, evaluation):
243+
return from_python(EXTENSIONMAPPINGS)
244+
245+
246+
class ConverterDumpsFormatMappings(Predefined):
247+
"""
248+
<dl>
249+
<dt>'$formatMappings'
250+
<dd>Returns a list of associations between file extensions and file types.
251+
</dl>
252+
"""
253+
context = 'System`ConvertersDump`'
254+
name = "$formatMappings"
255+
attributes = ['Unprotected']
256+
def evaluate(self, evaluation):
257+
return from_python(FORMATMAPPINGS)
258+
231259

232260
class ConverterDumpsExtensionMappings(Predefined):
233261
"""

0 commit comments

Comments
 (0)