Skip to content

Commit edf05e5

Browse files
authored
Merge branch 'master' into solve_ineq
2 parents 00d39ee + 0cdc458 commit edf05e5

9 files changed

+312
-153
lines changed

mathics/builtin/attributes.py

-23
Original file line numberDiff line numberDiff line change
@@ -203,29 +203,6 @@ class Flat(Predefined):
203203
'Flat' is taken into account in pattern matching:
204204
>> f[a, b, c] /. f[a, b] -> d
205205
= f[d, c]
206-
207-
#> SetAttributes[{u, v}, Flat]
208-
#> u[x_] := {x}
209-
#> u[]
210-
= u[]
211-
#> u[a]
212-
= {a}
213-
#> u[a, b]
214-
: Iteration limit of 1000 exceeded.
215-
= $Aborted
216-
#> u[a, b, c]
217-
: Iteration limit of 1000 exceeded.
218-
= $Aborted
219-
#> v[x_] := x
220-
#> v[]
221-
= v[]
222-
#> v[a]
223-
= a
224-
#> v[a, b] (* in Mathematica: Iteration limit of 4096 exceeded. *)
225-
= v[a, b]
226-
#> v[a, b, c] (* in Mathematica: Iteration limit of 4096 exceeded. *)
227-
: Iteration limit of 1000 exceeded.
228-
= $Aborted
229206
"""
230207

231208
summary_text = "attribute for associative symbols"

mathics/builtin/compilation.py

-20
Original file line numberDiff line numberDiff line change
@@ -57,32 +57,12 @@ class Compile(Builtin):
5757
= CompiledFunction[{x}, Sin[x], -CompiledCode-]
5858
>> cf[1.4]
5959
= 0.98545
60-
#> cf[1/2]
61-
= 0.479426
62-
#> cf[4]
63-
= -0.756802
64-
#> cf[x]
65-
: Invalid argument x should be Integer, Real or boolean.
66-
= CompiledFunction[{x}, Sin[x], -CompiledCode-][x]
67-
#> cf = Compile[{{x, _Real}, {x, _Integer}}, Sin[x + y]]
68-
: Duplicate parameter x found in {{x, _Real}, {x, _Integer}}.
69-
= Compile[{{x, _Real}, {x, _Integer}}, Sin[x + y]]
70-
#> cf = Compile[{{x, _Real}, {y, _Integer}}, Sin[x + z]]
71-
= CompiledFunction[{x, y}, Sin[x + z], -PythonizedCode-]
72-
#> cf = Compile[{{x, _Real}, {y, _Integer}}, Sin[x + y]]
73-
= CompiledFunction[{x, y}, Sin[x + y], -CompiledCode-]
74-
#> cf[1, 2]
75-
= 0.14112
76-
#> cf[x + y]
77-
= CompiledFunction[{x, y}, Sin[x + y], -CompiledCode-][x + y]
7860
7961
Compile supports basic flow control:
8062
>> cf = Compile[{{x, _Real}, {y, _Integer}}, If[x == 0.0 && y <= 0, 0.0, Sin[x ^ y] + 1 / Min[x, 0.5]] + 0.5]
8163
= CompiledFunction[{x, y}, ..., -CompiledCode-]
8264
>> cf[3.5, 2]
8365
= 2.18888
84-
#> cf[0, -2]
85-
= 0.5
8666
8767
Loops and variable assignments are supported usinv Python builtin "compile" function:
8868
>> Compile[{{a, _Integer}, {b, _Integer}}, While[b != 0, {a, b} = {b, Mod[a, b]}]; a] (* GCD of a, b *)

mathics/builtin/datentime.py

-24
Original file line numberDiff line numberDiff line change
@@ -375,10 +375,6 @@ class AbsoluteTime(_DateFormat):
375375
376376
>> AbsoluteTime[{"6-6-91", {"Day", "Month", "YearShort"}}]
377377
= 2885155200
378-
379-
## Mathematica Bug - Mathics gets it right
380-
#> AbsoluteTime[1000]
381-
= 1000
382378
"""
383379

384380
summary_text = "get absolute time in seconds"
@@ -834,10 +830,6 @@ class DateList(_DateFormat):
834830
: The interpretation of 1/10/1991 is ambiguous.
835831
= {1991, 1, 10, 0, 0, 0.}
836832
837-
#> DateList["7/8/9"]
838-
: The interpretation of 7/8/9 is ambiguous.
839-
= {2009, 7, 8, 0, 0, 0.}
840-
841833
>> DateList[{"31/10/91", {"Day", "Month", "YearShort"}}]
842834
= {1991, 10, 31, 0, 0, 0.}
843835
@@ -912,22 +904,6 @@ class DateString(_DateFormat):
912904
Non-integer values are accepted too:
913905
>> DateString[{1991, 6, 6.5}]
914906
= Thu 6 Jun 1991 12:00:00
915-
916-
## Check Leading 0
917-
#> DateString[{1979, 3, 14}, {"DayName", " ", "MonthShort", "-", "YearShort"}]
918-
= Wednesday 3-79
919-
920-
#> DateString[{"DayName", " ", "Month", "/", "YearShort"}]
921-
= ...
922-
923-
## Assumed separators
924-
#> DateString[{"06/06/1991", {"Month", "Day", "Year"}}]
925-
= Thu 6 Jun 1991 00:00:00
926-
927-
## Specified separators
928-
#> DateString[{"06/06/1991", {"Month", "/", "Day", "/", "Year"}}]
929-
= Thu 6 Jun 1991 00:00:00
930-
931907
"""
932908

933909
attributes = A_READ_PROTECTED | A_PROTECTED

mathics/builtin/graphics.py

-3
Original file line numberDiff line numberDiff line change
@@ -1450,9 +1450,6 @@ class Text(Inset):
14501450
14511451
>> Graphics[{Text["First", {0, 0}], Text["Second", {1, 1}]}, Axes->True, PlotRange->{{-2, 2}, {-2, 2}}]
14521452
= -Graphics-
1453-
1454-
#> Graphics[{Text[x, {0,0}]}]
1455-
= -Graphics-
14561453
"""
14571454

14581455
summary_text = "arbitrary text or other expressions in 2D or 3D"

mathics/builtin/patterns.py

-82
Original file line numberDiff line numberDiff line change
@@ -327,9 +327,6 @@ class ReplaceAll(BinaryOperator):
327327
>> ReplaceAll[{a -> 1}][{a, b}]
328328
= {1, b}
329329
330-
#> a + b /. x_ + y_ -> {x, y}
331-
= {a, b}
332-
333330
ReplaceAll replaces the shallowest levels first:
334331
>> ReplaceAll[x[1], {x[1] -> y, 1 -> 2}]
335332
= y
@@ -761,9 +758,6 @@ class Alternatives(BinaryOperator, PatternObject):
761758
Alternatives can also be used for string expressions
762759
>> StringReplace["0123 3210", "1" | "2" -> "X"]
763760
= 0XX3 3XX0
764-
765-
#> StringReplace["h1d9a f483", DigitCharacter | WhitespaceCharacter -> ""]
766-
= hdaf
767761
"""
768762

769763
arg_counts = None
@@ -829,9 +823,6 @@ class Except(PatternObject):
829823
Except can also be used for string expressions:
830824
>> StringReplace["Hello world!", Except[LetterCharacter] -> ""]
831825
= Helloworld
832-
833-
#> StringReplace["abc DEF 123!", Except[LetterCharacter, WordCharacter] -> "0"]
834-
= abc DEF 000!
835826
"""
836827

837828
arg_counts = [1, 2]
@@ -1091,15 +1082,6 @@ class Optional(BinaryOperator, PatternObject):
10911082
>> Default[h, k_] := k
10921083
>> h[a] /. h[x_, y_.] -> {x, y}
10931084
= {a, 2}
1094-
1095-
#> a:b:c
1096-
= a : b : c
1097-
#> FullForm[a:b:c]
1098-
= Optional[Pattern[a, b], c]
1099-
#> (a:b):c
1100-
= a : b : c
1101-
#> a:(b:c)
1102-
= a : (b : c)
11031085
"""
11041086

11051087
arg_counts = [1, 2]
@@ -1235,9 +1217,6 @@ class Blank(_Blank):
12351217
'Blank' only matches a single expression:
12361218
>> MatchQ[f[1, 2], f[_]]
12371219
= False
1238-
1239-
#> StringReplace["hello world!", _ -> "x"]
1240-
= xxxxxxxxxxxx
12411220
"""
12421221

12431222
rules = {
@@ -1293,14 +1272,6 @@ class BlankSequence(_Blank):
12931272
'Sequence' object:
12941273
>> f[1, 2, 3] /. f[x__] -> x
12951274
= Sequence[1, 2, 3]
1296-
1297-
#> f[a, b, c, d] /. f[x__, c, y__] -> {{x},{y}}
1298-
= {{a, b}, {d}}
1299-
#> a + b + c + d /. Plus[x__, c] -> {x}
1300-
= {a, b, d}
1301-
1302-
#> StringReplace[{"ab", "abc", "abcd"}, "b" ~~ __ -> "x"]
1303-
= {ab, ax, ax}
13041275
"""
13051276

13061277
rules = {
@@ -1350,21 +1321,6 @@ class BlankNullSequence(_Blank):
13501321
empty sequence:
13511322
>> MatchQ[f[], f[___]]
13521323
= True
1353-
1354-
## This test hits infinite recursion
1355-
##
1356-
##The value captured by a named 'BlankNullSequence' pattern is a
1357-
##'Sequence' object, which can have no elements:
1358-
##>> f[] /. f[x___] -> x
1359-
## = Sequence[]
1360-
1361-
#> ___symbol
1362-
= ___symbol
1363-
#> ___symbol //FullForm
1364-
= BlankNullSequence[symbol]
1365-
1366-
#> StringReplace[{"ab", "abc", "abcd"}, "b" ~~ ___ -> "x"]
1367-
= {ax, ax, ax}
13681324
"""
13691325

13701326
rules = {
@@ -1414,16 +1370,6 @@ class Repeated(PostfixOperator, PatternObject):
14141370
= {{}, a, {a, b}, a, {a, a, a, a}}
14151371
>> f[x, 0, 0, 0] /. f[x, s:0..] -> s
14161372
= Sequence[0, 0, 0]
1417-
1418-
#> 1.. // FullForm
1419-
= Repeated[1]
1420-
#> 8^^1.. // FullForm (* Mathematica gets this wrong *)
1421-
= Repeated[1]
1422-
1423-
#> StringReplace["010110110001010", "01".. -> "a"]
1424-
= a1a100a0
1425-
#> StringMatchQ[#, "a" ~~ ("b"..) ~~ "a"] &/@ {"aa", "aba", "abba"}
1426-
= {False, True, True}
14271373
"""
14281374

14291375
arg_counts = [1, 2]
@@ -1502,14 +1448,6 @@ class RepeatedNull(Repeated):
15021448
= RepeatedNull[Pattern[a, BlankNullSequence[Integer]]]
15031449
>> f[x] /. f[x, 0...] -> t
15041450
= t
1505-
1506-
#> 1... // FullForm
1507-
= RepeatedNull[1]
1508-
#> 8^^1... // FullForm (* Mathematica gets this wrong *)
1509-
= RepeatedNull[1]
1510-
1511-
#> StringMatchQ[#, "a" ~~ ("b"...) ~~ "a"] &/@ {"aa", "aba", "abba"}
1512-
= {True, True, True}
15131451
"""
15141452

15151453
operator = "..."
@@ -1666,26 +1604,6 @@ class OptionsPattern(PatternObject):
16661604
Options might be given in nested lists:
16671605
>> f[x, {{{n->4}}}]
16681606
= x ^ 4
1669-
1670-
#> {opt -> b} /. OptionsPattern[{}] -> t
1671-
= t
1672-
1673-
#> Clear[f]
1674-
#> Options[f] = {Power -> 2};
1675-
#> f[x_, OptionsPattern[f]] := x ^ OptionValue[Power]
1676-
#> f[10]
1677-
= 100
1678-
#> f[10, Power -> 3]
1679-
= 1000
1680-
#> Clear[f]
1681-
1682-
#> Options[f] = {Power -> 2};
1683-
#> f[x_, OptionsPattern[]] := x ^ OptionValue[Power]
1684-
#> f[10]
1685-
= 100
1686-
#> f[10, Power -> 3]
1687-
= 1000
1688-
#> Clear[f]
16891607
"""
16901608

16911609
arg_counts = [0, 1]

test/builtin/test_attributes.py

+82-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"""
55

66
import os
7-
from test.helper import check_evaluation
7+
from test.helper import check_evaluation, session
88

99
import pytest
1010

@@ -226,3 +226,84 @@ def test_Attributes_wrong_args(str_expr, arg_count):
226226
f"SetAttributes called with {arg_count} arguments; 2 arguments are expected.",
227227
),
228228
)
229+
230+
231+
@pytest.mark.parametrize(
232+
("str_expr", "msgs", "str_expected", "fail_msg"),
233+
[
234+
("CleanAll[u];CleanAll[v];", None, None, None),
235+
("SetAttributes[{u, v}, Flat];u[x_] := {x};u[]", None, "u[]", None),
236+
("u[a]", None, "{a}", None),
237+
("v[x_] := x;v[]", None, "v[]", None),
238+
("v[a]", None, "a", None),
239+
(
240+
"v[a, b]",
241+
None,
242+
"v[a, b]",
243+
"in Mathematica: Iteration limit of 4096 exceeded.",
244+
),
245+
("CleanAll[u];CleanAll[v];", None, None, None),
246+
],
247+
)
248+
def test_private_doctests_attributes(str_expr, msgs, str_expected, fail_msg):
249+
""" """
250+
check_evaluation(
251+
str_expr,
252+
str_expected,
253+
to_string_expr=True,
254+
to_string_expected=True,
255+
hold_expected=True,
256+
failure_message=fail_msg,
257+
expected_messages=msgs,
258+
)
259+
260+
261+
@pytest.mark.parametrize(
262+
("str_expr", "msgs", "str_expected", "fail_msg"),
263+
[
264+
("CleanAll[u];CleanAll[v];", None, None, None),
265+
(
266+
"SetAttributes[{u, v}, Flat];u[x_] := {x};u[a, b]",
267+
("Iteration limit of 1000 exceeded.",),
268+
"$Aborted",
269+
None,
270+
),
271+
("u[a, b, c]", ("Iteration limit of 1000 exceeded.",), "$Aborted", None),
272+
(
273+
"v[x_] := x;v[a,b,c]",
274+
("Iteration limit of 1000 exceeded.",),
275+
"$Aborted",
276+
"in Mathematica: Iteration limit of 4096 exceeded.",
277+
),
278+
("CleanAll[u];CleanAll[v];", None, None, None),
279+
],
280+
)
281+
def test_private_doctests_attributes_with_exceptions(
282+
str_expr, msgs, str_expected, fail_msg
283+
):
284+
"""These tests check the behavior of $RecursionLimit and $IterationLimit"""
285+
286+
# Here we do not use the session object to check the messages
287+
# produced by the exceptions. If $RecursionLimit / $IterationLimit
288+
# are reached during the evaluation using a MathicsSession object,
289+
# an exception is raised. On the other hand, using the `Evaluation.evaluate`
290+
# method, the exception is handled.
291+
#
292+
# TODO: Maybe it makes sense to clone this exception handling in
293+
# the check_evaluation function.
294+
#
295+
def eval_expr(expr_str):
296+
query = session.evaluation.parse(expr_str)
297+
res = session.evaluation.evaluate(query)
298+
session.evaluation.stopped = False
299+
return res
300+
301+
res = eval_expr(str_expr)
302+
if msgs is None:
303+
assert len(res.out) == 0
304+
else:
305+
assert len(res.out) == len(msgs)
306+
for li1, li2 in zip(res.out, msgs):
307+
assert li1.text == li2
308+
309+
assert res.result == str_expected

0 commit comments

Comments
 (0)