mathjson-solver 1.10.0__tar.gz → 1.11.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: mathjson-solver
3
- Version: 1.10.0
3
+ Version: 1.11.0
4
4
  Summary: Utilities for MathJSON evaluation
5
5
  Home-page: https://github.com/LongenesisLtd/mathjson-solver
6
6
  Author: Martins Mednis
@@ -30,14 +30,6 @@ _MathJSON Solver_ is a Python module to numerically evaluate MathJSON expression
30
30
 
31
31
  Please ask questions and share feedback in our Gitter chat [https://gitter.im/mathjson-solver/community](https://gitter.im/mathjson-solver/community).
32
32
 
33
- ## What's new
34
-
35
- ### 1.4.2
36
- Added `Str` construct. It tries to convert value to string.
37
-
38
- ### 1.4.0
39
- We changed the behavior of `Average` to be more forgiving. In version 1.4.0 `Average` accepts arrays like `[2, 4 ,"6"]` and internally converts numeric strings to floats.
40
- Also, it skips values that cannot be converted to numeric. Internally `Average` will convert array `[2, "three", 4 ,"6"]` to `[2.0, 4.0 ,6.0]`. When given an empty array, `Average` now returns `None` instead of throwing an error.
41
33
 
42
34
  ## How to use
43
35
  ```python
@@ -53,75 +45,64 @@ print(answer)
53
45
  # 9, because 2+3+4=9
54
46
  ```
55
47
 
56
- ## How to run tests
57
- Make sure you have `pytest` installed. Then `cd` into project directory and run:
58
- ```bash
59
- pytest
60
- ```
61
-
62
- ## Contributing Code
63
-
64
- We welcome your contributions in the form of pull requests.
65
-
66
- 1. Fork the repo;
67
- 2. Make improvements;
68
- 3. Make a pull request to share your improvements with the community and to include it into official release.
69
-
70
-
71
48
  ## Currently supported constructs
72
- ### Math
73
- * `Sum` (alias `Add`)
74
- * `Subtract`
75
- * `Multiply`
76
- * `Divide`
77
- * `Negate`
78
- * `Power`
79
- * `Root`
80
- * `Sqrt`
81
- * `Square`
82
- * `Exp`
83
- * `Log`
84
- * `Log2`
85
- * `Log10`
86
-
87
-
88
- ### Aggregation
89
- * `Array`
90
- * `Max`
91
- * `Min`
92
- * `Average`
93
- * `Median`
94
- * `Len`
95
- * `All`
96
- * `Any`
97
-
98
-
99
- ### Conditions
100
- * `If`
101
- * `Switch`
102
- * `Equal`
103
- * `Greater`
104
- * `GreaterEqual`
105
- * `Less`
106
- * `LessEqual`
107
- * `NotEqual`
108
-
109
- ### Membership operators
110
- * `In`
111
- * `NotIn`
112
- * `ContainsAnyOf`
113
- * `ContainsAllOf`
114
- * `ContainsNoneOf`
115
-
116
- ### Typecasting
117
- * `Str`
118
- * `Int`
119
- * `Float`
120
- * `Not`
121
-
122
- ### Additional constructs
123
- * `Constants`
124
-
49
+ * `Add` - Iteratively adds up the given values. Compatible with time delta.
50
+ * `Sum` - Internally uses python's `sum`. Not compatible with time delta.
51
+ * `Subtract` -
52
+ * `Constants` -
53
+ * `Switch` -
54
+ * `If` -
55
+ * `Multiply` -
56
+ * `Divide` -
57
+ * `Negate` -
58
+ * `Power` -
59
+ * `Root` -
60
+ * `Sqrt` -
61
+ * `Square` -
62
+ * `Exp` -
63
+ * `Log` -
64
+ * `Log2` -
65
+ * `Log10` -
66
+ * `Equal` -
67
+ * `Greater` -
68
+ * `GreaterEqual` -
69
+ * `Less` -
70
+ * `LessEqual` -
71
+ * `NotEqual` -
72
+ * `Abs` -
73
+ * `Round` -
74
+ * `Max` -
75
+ * `Min` -
76
+ * `Average` - Internally tries to convert strings to numbers, making calculation of average from `[2, 4 ,"6"]` actually possible. Also, it ignores un-convertible elements so arrays like `[2, "three", 4 ,"6"]` don't crash the solver.
77
+ * `Median` -
78
+ * `Length` -
79
+ * `Any` -
80
+ * `All` -
81
+ * `Array` -
82
+ * `In` -
83
+ * `Not_in` -
84
+ * `Contains_any_of` -
85
+ * `Contains_all_of` -
86
+ * `Contains_none_of` -
87
+ * `NotIn` -
88
+ * `ContainsAnyOf` -
89
+ * `ContainsAllOf` -
90
+ * `ContainsNoneOf` -
91
+ * `Int` -
92
+ * `Float` -
93
+ * `Str` -
94
+ * `Not` -
95
+ * `IsDefined` - Checks if a value is in parameters.
96
+ * `Map` -
97
+ * `HasMatchingSublist` -
98
+ * `Strptime` -
99
+ * `Strftime` -
100
+ * `Today` -
101
+ * `Now` -
102
+ * `TimeDeltaWeeks` -
103
+ * `TimeDeltaHours` -
104
+ * `TimeDeltaMinutes` -
105
+ * `TimeDeltaDays` -
125
106
 
126
107
  ## Examples
127
108
  ```python
@@ -142,7 +123,7 @@ We welcome your contributions in the form of pull requests.
142
123
  ["Log2", 8] # log2(8)=3.0
143
124
  ["Log10", 1000] # log10(1000)=3.0
144
125
  ["Equal", 10, 10] # 10==10 = True
145
- ["Equal", 10, 12] # 10==10 = False
126
+ ["Equal", 10, 12] # 10==12 = False
146
127
  ["Abs", -3.5] # |-3.5| = 3.5
147
128
  ["Round", -5.123456, 2] # -5.12
148
129
  ["Round", -5.123456, 0] # -5.0
@@ -245,7 +226,7 @@ elif 2 == 2 then 20
245
226
  else 9000
246
227
  ```
247
228
 
248
- `If` expression do not need to be strictly _boolean_. Any value that is not _false_ are considered _true_.
229
+ `If` expressions do not need to be strictly _boolean_. Any value that is not _false_ are considered _true_.
249
230
 
250
231
  ### Switch-Case statement
251
232
  ```
@@ -276,3 +257,18 @@ except MathJSONException:
276
257
  ```
277
258
 
278
259
  Left unhandled, the exception will look like `MathJSONException("Problem in Divide. ['Divide', 1, 0]. division by zero")`.
260
+
261
+
262
+ ## How to run tests
263
+ Make sure you have `pytest` installed. Then `cd` into project directory and run:
264
+ ```bash
265
+ pytest
266
+ ```
267
+
268
+ ## Contributing Code
269
+
270
+ We welcome your contributions in the form of pull requests.
271
+
272
+ 1. Fork the repo;
273
+ 2. Make improvements;
274
+ 3. Make a pull request to share your improvements with the community and to include it into official release.
@@ -6,14 +6,6 @@ _MathJSON Solver_ is a Python module to numerically evaluate MathJSON expression
6
6
 
7
7
  Please ask questions and share feedback in our Gitter chat [https://gitter.im/mathjson-solver/community](https://gitter.im/mathjson-solver/community).
8
8
 
9
- ## What's new
10
-
11
- ### 1.4.2
12
- Added `Str` construct. It tries to convert value to string.
13
-
14
- ### 1.4.0
15
- We changed the behavior of `Average` to be more forgiving. In version 1.4.0 `Average` accepts arrays like `[2, 4 ,"6"]` and internally converts numeric strings to floats.
16
- Also, it skips values that cannot be converted to numeric. Internally `Average` will convert array `[2, "three", 4 ,"6"]` to `[2.0, 4.0 ,6.0]`. When given an empty array, `Average` now returns `None` instead of throwing an error.
17
9
 
18
10
  ## How to use
19
11
  ```python
@@ -29,75 +21,64 @@ print(answer)
29
21
  # 9, because 2+3+4=9
30
22
  ```
31
23
 
32
- ## How to run tests
33
- Make sure you have `pytest` installed. Then `cd` into project directory and run:
34
- ```bash
35
- pytest
36
- ```
37
-
38
- ## Contributing Code
39
-
40
- We welcome your contributions in the form of pull requests.
41
-
42
- 1. Fork the repo;
43
- 2. Make improvements;
44
- 3. Make a pull request to share your improvements with the community and to include it into official release.
45
-
46
-
47
24
  ## Currently supported constructs
48
- ### Math
49
- * `Sum` (alias `Add`)
50
- * `Subtract`
51
- * `Multiply`
52
- * `Divide`
53
- * `Negate`
54
- * `Power`
55
- * `Root`
56
- * `Sqrt`
57
- * `Square`
58
- * `Exp`
59
- * `Log`
60
- * `Log2`
61
- * `Log10`
62
-
63
-
64
- ### Aggregation
65
- * `Array`
66
- * `Max`
67
- * `Min`
68
- * `Average`
69
- * `Median`
70
- * `Len`
71
- * `All`
72
- * `Any`
73
-
74
-
75
- ### Conditions
76
- * `If`
77
- * `Switch`
78
- * `Equal`
79
- * `Greater`
80
- * `GreaterEqual`
81
- * `Less`
82
- * `LessEqual`
83
- * `NotEqual`
84
-
85
- ### Membership operators
86
- * `In`
87
- * `NotIn`
88
- * `ContainsAnyOf`
89
- * `ContainsAllOf`
90
- * `ContainsNoneOf`
91
-
92
- ### Typecasting
93
- * `Str`
94
- * `Int`
95
- * `Float`
96
- * `Not`
97
-
98
- ### Additional constructs
99
- * `Constants`
100
-
25
+ * `Add` - Iteratively adds up the given values. Compatible with time delta.
26
+ * `Sum` - Internally uses python's `sum`. Not compatible with time delta.
27
+ * `Subtract` -
28
+ * `Constants` -
29
+ * `Switch` -
30
+ * `If` -
31
+ * `Multiply` -
32
+ * `Divide` -
33
+ * `Negate` -
34
+ * `Power` -
35
+ * `Root` -
36
+ * `Sqrt` -
37
+ * `Square` -
38
+ * `Exp` -
39
+ * `Log` -
40
+ * `Log2` -
41
+ * `Log10` -
42
+ * `Equal` -
43
+ * `Greater` -
44
+ * `GreaterEqual` -
45
+ * `Less` -
46
+ * `LessEqual` -
47
+ * `NotEqual` -
48
+ * `Abs` -
49
+ * `Round` -
50
+ * `Max` -
51
+ * `Min` -
52
+ * `Average` - Internally tries to convert strings to numbers, making calculation of average from `[2, 4 ,"6"]` actually possible. Also, it ignores un-convertible elements so arrays like `[2, "three", 4 ,"6"]` don't crash the solver.
53
+ * `Median` -
54
+ * `Length` -
55
+ * `Any` -
56
+ * `All` -
57
+ * `Array` -
58
+ * `In` -
59
+ * `Not_in` -
60
+ * `Contains_any_of` -
61
+ * `Contains_all_of` -
62
+ * `Contains_none_of` -
63
+ * `NotIn` -
64
+ * `ContainsAnyOf` -
65
+ * `ContainsAllOf` -
66
+ * `ContainsNoneOf` -
67
+ * `Int` -
68
+ * `Float` -
69
+ * `Str` -
70
+ * `Not` -
71
+ * `IsDefined` - Checks if a value is in parameters.
72
+ * `Map` -
73
+ * `HasMatchingSublist` -
74
+ * `Strptime` -
75
+ * `Strftime` -
76
+ * `Today` -
77
+ * `Now` -
78
+ * `TimeDeltaWeeks` -
79
+ * `TimeDeltaHours` -
80
+ * `TimeDeltaMinutes` -
81
+ * `TimeDeltaDays` -
101
82
 
102
83
  ## Examples
103
84
  ```python
@@ -118,7 +99,7 @@ We welcome your contributions in the form of pull requests.
118
99
  ["Log2", 8] # log2(8)=3.0
119
100
  ["Log10", 1000] # log10(1000)=3.0
120
101
  ["Equal", 10, 10] # 10==10 = True
121
- ["Equal", 10, 12] # 10==10 = False
102
+ ["Equal", 10, 12] # 10==12 = False
122
103
  ["Abs", -3.5] # |-3.5| = 3.5
123
104
  ["Round", -5.123456, 2] # -5.12
124
105
  ["Round", -5.123456, 0] # -5.0
@@ -221,7 +202,7 @@ elif 2 == 2 then 20
221
202
  else 9000
222
203
  ```
223
204
 
224
- `If` expression do not need to be strictly _boolean_. Any value that is not _false_ are considered _true_.
205
+ `If` expressions do not need to be strictly _boolean_. Any value that is not _false_ are considered _true_.
225
206
 
226
207
  ### Switch-Case statement
227
208
  ```
@@ -252,3 +233,18 @@ except MathJSONException:
252
233
  ```
253
234
 
254
235
  Left unhandled, the exception will look like `MathJSONException("Problem in Divide. ['Divide', 1, 0]. division by zero")`.
236
+
237
+
238
+ ## How to run tests
239
+ Make sure you have `pytest` installed. Then `cd` into project directory and run:
240
+ ```bash
241
+ pytest
242
+ ```
243
+
244
+ ## Contributing Code
245
+
246
+ We welcome your contributions in the form of pull requests.
247
+
248
+ 1. Fork the repo;
249
+ 2. Make improvements;
250
+ 3. Make a pull request to share your improvements with the community and to include it into official release.
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = mathjson-solver
3
- version = 1.10.0
3
+ version = 1.11.0
4
4
  author = Martins Mednis
5
5
  author_email = mrt@mednis.info
6
6
  description = Utilities for MathJSON evaluation
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name="mathjson-solver",
8
- version="1.10.0",
8
+ version="1.11.0",
9
9
  author="Martins Mednis",
10
10
  author_email="mrt@mednis.info",
11
11
  description="Utilities for MathJSON evaluation",
@@ -147,7 +147,7 @@ def create_mathjson_solver(solver_parameters):
147
147
  tmp = 0
148
148
  for i, x in enumerate(s[1:]):
149
149
  res = f(x, c)
150
- if i ==0:
150
+ if i == 0:
151
151
  tmp = res
152
152
  else:
153
153
  tmp = tmp + res
@@ -467,7 +467,17 @@ def create_mathjson_solver(solver_parameters):
467
467
  if s[0] in constructs:
468
468
  try:
469
469
  return constructs[s[0]](s)
470
- except Exception as e:
470
+
471
+ # except RecursionError:
472
+ # return s[0]
473
+ # except Exception as e:
474
+ except TypeError as e:
475
+ raise MathJSONException(e, s, mathjson_construct=s[0])
476
+ except ValueError as e:
477
+ raise MathJSONException(e, s, mathjson_construct=s[0])
478
+ except IndexError as e:
479
+ raise MathJSONException(e, s, mathjson_construct=s[0])
480
+ except ZeroDivisionError as e:
471
481
  raise MathJSONException(e, s, mathjson_construct=s[0])
472
482
  else:
473
483
  # raise MathJSONException(
@@ -475,7 +485,10 @@ def create_mathjson_solver(solver_parameters):
475
485
  # )
476
486
  return s
477
487
  elif s in solver_parameters:
478
- return f(solver_parameters[s], c)
488
+ try:
489
+ return f(solver_parameters[s], c)
490
+ except RecursionError:
491
+ return solver_parameters[s]
479
492
  elif s in c:
480
493
  return f(c[s], c)
481
494
  else:
@@ -536,6 +549,14 @@ def extract_variables(s: Union[list, int, float, str], li: set, ignore_list: set
536
549
  "IsDefined",
537
550
  "Map",
538
551
  "HasMatchingSublist",
552
+ "Strptime",
553
+ "Strftime",
554
+ "Today",
555
+ "Now",
556
+ "TimeDeltaWeeks",
557
+ "TimeDeltaHours",
558
+ "TimeDeltaMinutes",
559
+ "TimeDeltaDays",
539
560
  ]
540
561
  if isinstance(s, str):
541
562
  if s in ignore_list:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: mathjson-solver
3
- Version: 1.10.0
3
+ Version: 1.11.0
4
4
  Summary: Utilities for MathJSON evaluation
5
5
  Home-page: https://github.com/LongenesisLtd/mathjson-solver
6
6
  Author: Martins Mednis
@@ -30,14 +30,6 @@ _MathJSON Solver_ is a Python module to numerically evaluate MathJSON expression
30
30
 
31
31
  Please ask questions and share feedback in our Gitter chat [https://gitter.im/mathjson-solver/community](https://gitter.im/mathjson-solver/community).
32
32
 
33
- ## What's new
34
-
35
- ### 1.4.2
36
- Added `Str` construct. It tries to convert value to string.
37
-
38
- ### 1.4.0
39
- We changed the behavior of `Average` to be more forgiving. In version 1.4.0 `Average` accepts arrays like `[2, 4 ,"6"]` and internally converts numeric strings to floats.
40
- Also, it skips values that cannot be converted to numeric. Internally `Average` will convert array `[2, "three", 4 ,"6"]` to `[2.0, 4.0 ,6.0]`. When given an empty array, `Average` now returns `None` instead of throwing an error.
41
33
 
42
34
  ## How to use
43
35
  ```python
@@ -53,75 +45,64 @@ print(answer)
53
45
  # 9, because 2+3+4=9
54
46
  ```
55
47
 
56
- ## How to run tests
57
- Make sure you have `pytest` installed. Then `cd` into project directory and run:
58
- ```bash
59
- pytest
60
- ```
61
-
62
- ## Contributing Code
63
-
64
- We welcome your contributions in the form of pull requests.
65
-
66
- 1. Fork the repo;
67
- 2. Make improvements;
68
- 3. Make a pull request to share your improvements with the community and to include it into official release.
69
-
70
-
71
48
  ## Currently supported constructs
72
- ### Math
73
- * `Sum` (alias `Add`)
74
- * `Subtract`
75
- * `Multiply`
76
- * `Divide`
77
- * `Negate`
78
- * `Power`
79
- * `Root`
80
- * `Sqrt`
81
- * `Square`
82
- * `Exp`
83
- * `Log`
84
- * `Log2`
85
- * `Log10`
86
-
87
-
88
- ### Aggregation
89
- * `Array`
90
- * `Max`
91
- * `Min`
92
- * `Average`
93
- * `Median`
94
- * `Len`
95
- * `All`
96
- * `Any`
97
-
98
-
99
- ### Conditions
100
- * `If`
101
- * `Switch`
102
- * `Equal`
103
- * `Greater`
104
- * `GreaterEqual`
105
- * `Less`
106
- * `LessEqual`
107
- * `NotEqual`
108
-
109
- ### Membership operators
110
- * `In`
111
- * `NotIn`
112
- * `ContainsAnyOf`
113
- * `ContainsAllOf`
114
- * `ContainsNoneOf`
115
-
116
- ### Typecasting
117
- * `Str`
118
- * `Int`
119
- * `Float`
120
- * `Not`
121
-
122
- ### Additional constructs
123
- * `Constants`
124
-
49
+ * `Add` - Iteratively adds up the given values. Compatible with time delta.
50
+ * `Sum` - Internally uses python's `sum`. Not compatible with time delta.
51
+ * `Subtract` -
52
+ * `Constants` -
53
+ * `Switch` -
54
+ * `If` -
55
+ * `Multiply` -
56
+ * `Divide` -
57
+ * `Negate` -
58
+ * `Power` -
59
+ * `Root` -
60
+ * `Sqrt` -
61
+ * `Square` -
62
+ * `Exp` -
63
+ * `Log` -
64
+ * `Log2` -
65
+ * `Log10` -
66
+ * `Equal` -
67
+ * `Greater` -
68
+ * `GreaterEqual` -
69
+ * `Less` -
70
+ * `LessEqual` -
71
+ * `NotEqual` -
72
+ * `Abs` -
73
+ * `Round` -
74
+ * `Max` -
75
+ * `Min` -
76
+ * `Average` - Internally tries to convert strings to numbers, making calculation of average from `[2, 4 ,"6"]` actually possible. Also, it ignores un-convertible elements so arrays like `[2, "three", 4 ,"6"]` don't crash the solver.
77
+ * `Median` -
78
+ * `Length` -
79
+ * `Any` -
80
+ * `All` -
81
+ * `Array` -
82
+ * `In` -
83
+ * `Not_in` -
84
+ * `Contains_any_of` -
85
+ * `Contains_all_of` -
86
+ * `Contains_none_of` -
87
+ * `NotIn` -
88
+ * `ContainsAnyOf` -
89
+ * `ContainsAllOf` -
90
+ * `ContainsNoneOf` -
91
+ * `Int` -
92
+ * `Float` -
93
+ * `Str` -
94
+ * `Not` -
95
+ * `IsDefined` - Checks if a value is in parameters.
96
+ * `Map` -
97
+ * `HasMatchingSublist` -
98
+ * `Strptime` -
99
+ * `Strftime` -
100
+ * `Today` -
101
+ * `Now` -
102
+ * `TimeDeltaWeeks` -
103
+ * `TimeDeltaHours` -
104
+ * `TimeDeltaMinutes` -
105
+ * `TimeDeltaDays` -
125
106
 
126
107
  ## Examples
127
108
  ```python
@@ -142,7 +123,7 @@ We welcome your contributions in the form of pull requests.
142
123
  ["Log2", 8] # log2(8)=3.0
143
124
  ["Log10", 1000] # log10(1000)=3.0
144
125
  ["Equal", 10, 10] # 10==10 = True
145
- ["Equal", 10, 12] # 10==10 = False
126
+ ["Equal", 10, 12] # 10==12 = False
146
127
  ["Abs", -3.5] # |-3.5| = 3.5
147
128
  ["Round", -5.123456, 2] # -5.12
148
129
  ["Round", -5.123456, 0] # -5.0
@@ -245,7 +226,7 @@ elif 2 == 2 then 20
245
226
  else 9000
246
227
  ```
247
228
 
248
- `If` expression do not need to be strictly _boolean_. Any value that is not _false_ are considered _true_.
229
+ `If` expressions do not need to be strictly _boolean_. Any value that is not _false_ are considered _true_.
249
230
 
250
231
  ### Switch-Case statement
251
232
  ```
@@ -276,3 +257,18 @@ except MathJSONException:
276
257
  ```
277
258
 
278
259
  Left unhandled, the exception will look like `MathJSONException("Problem in Divide. ['Divide', 1, 0]. division by zero")`.
260
+
261
+
262
+ ## How to run tests
263
+ Make sure you have `pytest` installed. Then `cd` into project directory and run:
264
+ ```bash
265
+ pytest
266
+ ```
267
+
268
+ ## Contributing Code
269
+
270
+ We welcome your contributions in the form of pull requests.
271
+
272
+ 1. Fork the repo;
273
+ 2. Make improvements;
274
+ 3. Make a pull request to share your improvements with the community and to include it into official release.
@@ -45,6 +45,60 @@ from mathjson_solver import create_solver, MathJSONException, extract_variables
45
45
  ({}, ["Constants", ["a", 1], ["b", 2], ["c", 100], ["Sum", "a", "b"]], 3),
46
46
  ({}, ["Constants", ["a", 1], ["b", ["Add", 2, "a"]], "b"], 3),
47
47
  ({"x": 1}, ["Add", 2, "x"], 3),
48
+ ({"value": 1}, ["Switch", "value", 0, [1, 11], [2, 22]], 11),
49
+ ({"value": 3}, ["Switch", "value", 0, [1, 11], [2, 22]], 0),
50
+ (
51
+ {"[uzwuoy][-1][14]": 1},
52
+ ["Switch", "[uzwuoy][-1][14]", 0, [1, 11], [2, 22]],
53
+ 11,
54
+ ),
55
+ ({"14": 1}, ["Switch", "14", 0, [1, 11], [2, 22]], 11),
56
+ ({"14": "1"}, ["Switch", "14", 0, ["0", 0], ["1", 1], ["2", 2]], 1),
57
+ ({"29": "1"}, ["Switch", "29", 0, ["0", 0], ["1", 1], ["2", 2]], 1),
58
+ ({"29": "2"}, ["Switch", "29", 0, ["0", 0], ["1", 1], ["2", 2]], 2),
59
+ ({"a": "a"}, ["Switch", "a", 0, ["0", 0], ["1", 1], ["2", 2]], 0),
60
+ (
61
+ {"14": "1", "29": "1"},
62
+ [
63
+ "Add",
64
+ ["Switch", "14", 0, ["0", 0], ["1", 1], ["2", 2]],
65
+ ["Switch", "29", 0, ["0", 0], ["1", 1], ["2", 2]],
66
+ ],
67
+ 2,
68
+ ),
69
+ ({}, ["Switch", "14", 6, ["0", 0], ["1", 1], ["2", 2]], 6),
70
+ ({}, ["Switch", "1", 6, ["0", 0], ["1", 1], ["2", 2]], 1), # BKUS
71
+ (
72
+ {"1": "2"},
73
+ ["Switch", "1", 6, ["0", 0], ["1", 1], ["2", 2]],
74
+ 1,
75
+ ), # Because all "1"s become "2"
76
+ (
77
+ {"1": "3"},
78
+ ["Switch", "1", 6, ["0", 0], ["1", 1], ["2", 2]],
79
+ 1,
80
+ ), # Because string "1" is equal string "1"
81
+ # The following test works.
82
+ # It is commented out because otherwise black auto-formatter would expand it to 100+ lines
83
+ # (
84
+ # {"14": "1", "29": "1", "30": "1", "31": "1", "32": "1", "33": "1", "35": "1", "45": "1", "50": "1", "52": "1", "71": "1", "91": "1", "112": "1"},
85
+ # ["Add",
86
+ # ["Switch","14",0,["0",0],["1",1],["2",2]],
87
+ # ["Switch","29",0,["0",0],["1",1],["2",2]],
88
+ # ["Switch","30",0,["0",0],["1",1],["2",2]],
89
+ # ["Switch","31",0,["0",0],["1",1],["2",2]],
90
+ # ["Switch","32",0,["0",0],["1",1],["2",2]],
91
+ # ["Switch","33",0,["0",0],["1",1],["2",2]],
92
+ # ["Switch","35",0,["0",0],["1",1],["2",2]],
93
+ # ["Switch","45",0,["0",0],["1",1],["2",2]],
94
+ # ["Switch","50",0,["0",0],["1",1],["2",2]],
95
+ # ["Switch","52",0,["0",0],["1",1],["2",2]],
96
+ # ["Switch","71",0,["0",0],["1",1],["2",2]],
97
+ # ["Switch","91",0,["0",0],["1",1],["2",2]],
98
+ # ["Switch","112",0,["0",0],["1",1],["2",2]]
99
+ # ],
100
+ # 13
101
+ # ),
48
102
  ({"color": "red"}, ["Switch", "color", 0, ["blue", 10], ["red", 30]], 30),
49
103
  ({"color": "green"}, ["Switch", "color", 0, ["blue", 10], ["red", 30]], 0),
50
104
  ({"color": "green"}, ["Switch", "undefined", 0, ["blue", 10], ["red", 30]], 0),
@@ -52,6 +106,7 @@ from mathjson_solver import create_solver, MathJSONException, extract_variables
52
106
  ({"a": 10, "b": 10}, ["If", [["Equal", "a", "b"], 10], 9000], 10),
53
107
  ({"a": 10, "b": 20}, ["If", [["Equal", "a", "b"], 10], 9000], 9000),
54
108
  ({"a": 10}, ["If", [["Equal", "a", "b"], 10], 9000], 9000),
109
+ # The following test checks if Sum failure (1+"b") is handled correctly in If.
55
110
  ({"a": 10}, ["If", [["Equal", "a", ["Sum", 1, "b"]], 10], 9000], 9000),
56
111
  ({}, ["Array", 1, 2, 3, 5, 2], ["Array", 1, 2, 3, 5, 2]),
57
112
  ({}, ["Max", ["Array", 1, 2, 3, 5, 2]], 5),
@@ -93,6 +148,9 @@ from mathjson_solver import create_solver, MathJSONException, extract_variables
93
148
  ({}, ["Length", ["Array", 1, 2, 3, 5, 2, 9]], 6),
94
149
  ({"a": ["Array", 1, 2, 3, 5, 2, 9]}, ["Length", "a"], 6),
95
150
  ({}, ["Length", ["Array"]], 0),
151
+ # Next test illustrates an invalid formula, where 'Length' receives an invalid array.
152
+ ({}, ["Length", ["Greater", ["Array", 3, 5, 6, 4, 8, 1, 0, 1], 5]], 2),
153
+ ({}, ["Sum", ["Array", True, False, True, False, False]], 2),
96
154
  ({}, ["Int", "12"], 12),
97
155
  ({}, ["Int", "12.2"], 12),
98
156
  ({}, ["Float", "12.2"], 12.2),
@@ -180,6 +238,12 @@ from mathjson_solver import create_solver, MathJSONException, extract_variables
180
238
  ["Map", ["Array", 1, 2, 3], ["GreaterEqual"], 2],
181
239
  ["Array", False, True, True],
182
240
  ),
241
+ (
242
+ {},
243
+ ["Sum", ["Map", ["Array", 1, 2, 3, 4, 1, 1, 0, 1], ["GreaterEqual"], 2]],
244
+ 3,
245
+ ),
246
+ ({}, ["Sum", ["Array", True, False, True, False, False]], 2),
183
247
  # ["HasMatchingSublist", list, required_match_count, position, contiguous, function, more parameters]
184
248
  (
185
249
  {},
@@ -259,13 +323,78 @@ from mathjson_solver import create_solver, MathJSONException, extract_variables
259
323
  ],
260
324
  False,
261
325
  ),
262
- ({}, ["Strftime", ["Strptime", "2025-01-10T10:05", "%Y-%m-%dT%H:%M"], "%Y"], "2025"),
326
+ (
327
+ {},
328
+ ["Strftime", ["Strptime", "2025-01-10T10:05", "%Y-%m-%dT%H:%M"], "%Y"],
329
+ "2025",
330
+ ),
263
331
  ({}, ["Strftime", ["Today"], "%Y"], "2025"),
264
332
  ({}, ["Strftime", ["Now"], "%Y"], "2025"),
265
- ({}, ["Strftime", ["Add", ["Strptime", "2025-01-10T10:05", "%Y-%m-%dT%H:%M"], ["TimeDeltaDays", 3]], "%d"], "13"),
266
- ({}, ["Strftime", ["Add", ["Strptime", "2025-01-10T10:05", "%Y-%m-%dT%H:%M"], ["TimeDeltaMinutes", 5]], "%M"], "10"),
267
- ({}, ["Strftime", ["Add", ["Strptime", "2025-01-10T10:05", "%Y-%m-%dT%H:%M"], ["TimeDeltaHours", 2]], "%H"], "12"),
268
- ({}, ["Strftime", ["Add", ["Strptime", "2025-01-10T10:05", "%Y-%m-%dT%H:%M"], ["TimeDeltaWeeks", 1]], "%d"], "17"),
333
+ (
334
+ {},
335
+ [
336
+ "Strftime",
337
+ [
338
+ "Add",
339
+ ["Strptime", "2025-01-10T10:05", "%Y-%m-%dT%H:%M"],
340
+ ["TimeDeltaDays", 3],
341
+ ],
342
+ "%d",
343
+ ],
344
+ "13",
345
+ ),
346
+ (
347
+ {},
348
+ [
349
+ "Strftime",
350
+ [
351
+ "Subtract",
352
+ ["Strptime", "2025-01-10T10:05", "%Y-%m-%dT%H:%M"],
353
+ ["TimeDeltaDays", 3],
354
+ ],
355
+ "%d",
356
+ ],
357
+ "07",
358
+ ),
359
+ (
360
+ {},
361
+ [
362
+ "Strftime",
363
+ [
364
+ "Add",
365
+ ["Strptime", "2025-01-10T10:05", "%Y-%m-%dT%H:%M"],
366
+ ["TimeDeltaMinutes", 5],
367
+ ],
368
+ "%M",
369
+ ],
370
+ "10",
371
+ ),
372
+ (
373
+ {},
374
+ [
375
+ "Strftime",
376
+ [
377
+ "Add",
378
+ ["Strptime", "2025-01-10T10:05", "%Y-%m-%dT%H:%M"],
379
+ ["TimeDeltaHours", 2],
380
+ ],
381
+ "%H",
382
+ ],
383
+ "12",
384
+ ),
385
+ (
386
+ {},
387
+ [
388
+ "Strftime",
389
+ [
390
+ "Add",
391
+ ["Strptime", "2025-01-10T10:05", "%Y-%m-%dT%H:%M"],
392
+ ["TimeDeltaWeeks", 1],
393
+ ],
394
+ "%d",
395
+ ],
396
+ "17",
397
+ ),
269
398
  ],
270
399
  )
271
400
  def test_solver_simple(parameters, expression, expected_result):