mathjson-solver 1.9.1__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.
- {mathjson_solver-1.9.1/src/mathjson_solver.egg-info → mathjson_solver-1.11.0}/PKG-INFO +85 -80
- {mathjson_solver-1.9.1 → mathjson_solver-1.11.0}/README.md +74 -78
- {mathjson_solver-1.9.1 → mathjson_solver-1.11.0}/setup.cfg +1 -1
- {mathjson_solver-1.9.1 → mathjson_solver-1.11.0}/setup.py +1 -1
- {mathjson_solver-1.9.1 → mathjson_solver-1.11.0}/src/mathjson_solver/__main__.py +86 -3
- {mathjson_solver-1.9.1 → mathjson_solver-1.11.0/src/mathjson_solver.egg-info}/PKG-INFO +85 -80
- {mathjson_solver-1.9.1 → mathjson_solver-1.11.0}/tests/test_with_pytest.py +136 -0
- {mathjson_solver-1.9.1 → mathjson_solver-1.11.0}/LICENSE +0 -0
- {mathjson_solver-1.9.1 → mathjson_solver-1.11.0}/pyproject.toml +0 -0
- {mathjson_solver-1.9.1 → mathjson_solver-1.11.0}/src/mathjson_solver/__init__.py +0 -0
- {mathjson_solver-1.9.1 → mathjson_solver-1.11.0}/src/mathjson_solver.egg-info/SOURCES.txt +0 -0
- {mathjson_solver-1.9.1 → mathjson_solver-1.11.0}/src/mathjson_solver.egg-info/dependency_links.txt +0 -0
- {mathjson_solver-1.9.1 → mathjson_solver-1.11.0}/src/mathjson_solver.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: mathjson-solver
|
|
3
|
-
Version: 1.
|
|
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
|
|
@@ -12,6 +12,15 @@ Classifier: Operating System :: OS Independent
|
|
|
12
12
|
Requires-Python: >=3.6
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
|
+
Dynamic: author
|
|
16
|
+
Dynamic: author-email
|
|
17
|
+
Dynamic: classifier
|
|
18
|
+
Dynamic: description
|
|
19
|
+
Dynamic: description-content-type
|
|
20
|
+
Dynamic: home-page
|
|
21
|
+
Dynamic: project-url
|
|
22
|
+
Dynamic: requires-python
|
|
23
|
+
Dynamic: summary
|
|
15
24
|
|
|
16
25
|
# MathJSON Solver
|
|
17
26
|
|
|
@@ -21,14 +30,6 @@ _MathJSON Solver_ is a Python module to numerically evaluate MathJSON expression
|
|
|
21
30
|
|
|
22
31
|
Please ask questions and share feedback in our Gitter chat [https://gitter.im/mathjson-solver/community](https://gitter.im/mathjson-solver/community).
|
|
23
32
|
|
|
24
|
-
## What's new
|
|
25
|
-
|
|
26
|
-
### 1.4.2
|
|
27
|
-
Added `Str` construct. It tries to convert value to string.
|
|
28
|
-
|
|
29
|
-
### 1.4.0
|
|
30
|
-
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.
|
|
31
|
-
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.
|
|
32
33
|
|
|
33
34
|
## How to use
|
|
34
35
|
```python
|
|
@@ -44,75 +45,64 @@ print(answer)
|
|
|
44
45
|
# 9, because 2+3+4=9
|
|
45
46
|
```
|
|
46
47
|
|
|
47
|
-
## How to run tests
|
|
48
|
-
Make sure you have `pytest` installed. Then `cd` into project directory and run:
|
|
49
|
-
```bash
|
|
50
|
-
pytest
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
## Contributing Code
|
|
54
|
-
|
|
55
|
-
We welcome your contributions in the form of pull requests.
|
|
56
|
-
|
|
57
|
-
1. Fork the repo;
|
|
58
|
-
2. Make improvements;
|
|
59
|
-
3. Make a pull request to share your improvements with the community and to include it into official release.
|
|
60
|
-
|
|
61
|
-
|
|
62
48
|
## Currently supported constructs
|
|
63
|
-
|
|
64
|
-
* `Sum`
|
|
65
|
-
* `Subtract`
|
|
66
|
-
* `
|
|
67
|
-
* `
|
|
68
|
-
* `
|
|
69
|
-
* `
|
|
70
|
-
* `
|
|
71
|
-
* `
|
|
72
|
-
* `
|
|
73
|
-
* `
|
|
74
|
-
* `
|
|
75
|
-
* `
|
|
76
|
-
* `
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
* `
|
|
81
|
-
* `
|
|
82
|
-
* `
|
|
83
|
-
* `
|
|
84
|
-
* `
|
|
85
|
-
* `
|
|
86
|
-
* `
|
|
87
|
-
* `
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
* `
|
|
92
|
-
* `
|
|
93
|
-
* `
|
|
94
|
-
* `
|
|
95
|
-
* `
|
|
96
|
-
* `
|
|
97
|
-
* `
|
|
98
|
-
* `
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
* `
|
|
102
|
-
* `
|
|
103
|
-
* `
|
|
104
|
-
* `
|
|
105
|
-
* `
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
* `
|
|
109
|
-
* `
|
|
110
|
-
* `
|
|
111
|
-
* `
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
* `
|
|
115
|
-
|
|
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` -
|
|
116
106
|
|
|
117
107
|
## Examples
|
|
118
108
|
```python
|
|
@@ -133,7 +123,7 @@ We welcome your contributions in the form of pull requests.
|
|
|
133
123
|
["Log2", 8] # log2(8)=3.0
|
|
134
124
|
["Log10", 1000] # log10(1000)=3.0
|
|
135
125
|
["Equal", 10, 10] # 10==10 = True
|
|
136
|
-
["Equal", 10, 12] # 10==
|
|
126
|
+
["Equal", 10, 12] # 10==12 = False
|
|
137
127
|
["Abs", -3.5] # |-3.5| = 3.5
|
|
138
128
|
["Round", -5.123456, 2] # -5.12
|
|
139
129
|
["Round", -5.123456, 0] # -5.0
|
|
@@ -236,7 +226,7 @@ elif 2 == 2 then 20
|
|
|
236
226
|
else 9000
|
|
237
227
|
```
|
|
238
228
|
|
|
239
|
-
`If`
|
|
229
|
+
`If` expressions do not need to be strictly _boolean_. Any value that is not _false_ are considered _true_.
|
|
240
230
|
|
|
241
231
|
### Switch-Case statement
|
|
242
232
|
```
|
|
@@ -267,3 +257,18 @@ except MathJSONException:
|
|
|
267
257
|
```
|
|
268
258
|
|
|
269
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
|
-
|
|
49
|
-
* `Sum`
|
|
50
|
-
* `Subtract`
|
|
51
|
-
* `
|
|
52
|
-
* `
|
|
53
|
-
* `
|
|
54
|
-
* `
|
|
55
|
-
* `
|
|
56
|
-
* `
|
|
57
|
-
* `
|
|
58
|
-
* `
|
|
59
|
-
* `
|
|
60
|
-
* `
|
|
61
|
-
* `
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
* `
|
|
66
|
-
* `
|
|
67
|
-
* `
|
|
68
|
-
* `
|
|
69
|
-
* `
|
|
70
|
-
* `
|
|
71
|
-
* `
|
|
72
|
-
* `
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
* `
|
|
77
|
-
* `
|
|
78
|
-
* `
|
|
79
|
-
* `
|
|
80
|
-
* `
|
|
81
|
-
* `
|
|
82
|
-
* `
|
|
83
|
-
* `
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
* `
|
|
87
|
-
* `
|
|
88
|
-
* `
|
|
89
|
-
* `
|
|
90
|
-
* `
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
* `
|
|
94
|
-
* `
|
|
95
|
-
* `
|
|
96
|
-
* `
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
* `
|
|
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==
|
|
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`
|
|
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.
|
|
@@ -6,6 +6,7 @@ from copy import deepcopy
|
|
|
6
6
|
from statistics import median
|
|
7
7
|
import logging
|
|
8
8
|
import traceback
|
|
9
|
+
import datetime
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
class MathJSONException(Exception):
|
|
@@ -141,6 +142,31 @@ def create_mathjson_solver(solver_parameters):
|
|
|
141
142
|
def Arr(s):
|
|
142
143
|
return s
|
|
143
144
|
|
|
145
|
+
def Add(s):
|
|
146
|
+
l_res = []
|
|
147
|
+
tmp = 0
|
|
148
|
+
for i, x in enumerate(s[1:]):
|
|
149
|
+
res = f(x, c)
|
|
150
|
+
if i == 0:
|
|
151
|
+
tmp = res
|
|
152
|
+
else:
|
|
153
|
+
tmp = tmp + res
|
|
154
|
+
|
|
155
|
+
# if isinstance(res, list):
|
|
156
|
+
# l_res.append(sum([xx for xx in res[1:]]))
|
|
157
|
+
# else:
|
|
158
|
+
# l_res.append(res)
|
|
159
|
+
|
|
160
|
+
return tmp
|
|
161
|
+
|
|
162
|
+
# tmp = 0
|
|
163
|
+
# for i, x in enumerate(l):
|
|
164
|
+
# if i == 0:
|
|
165
|
+
# tmp = x
|
|
166
|
+
# else:
|
|
167
|
+
# tmp = tmp + x
|
|
168
|
+
# return tmp
|
|
169
|
+
|
|
144
170
|
def Sum(s):
|
|
145
171
|
l_res = []
|
|
146
172
|
for x in s[1:]:
|
|
@@ -343,9 +369,37 @@ def create_mathjson_solver(solver_parameters):
|
|
|
343
369
|
conditions=conditions,
|
|
344
370
|
)
|
|
345
371
|
|
|
372
|
+
def Strptime(s):
|
|
373
|
+
datetime_str = f(s[1], c)
|
|
374
|
+
parameters = f(s[2], c)
|
|
375
|
+
return datetime.datetime.strptime(datetime_str, parameters)
|
|
376
|
+
|
|
377
|
+
def Strftime(s):
|
|
378
|
+
dt = f(s[1], c)
|
|
379
|
+
parameters = f(s[2], c)
|
|
380
|
+
return dt.strftime(parameters)
|
|
381
|
+
|
|
382
|
+
def Now(s):
|
|
383
|
+
return datetime.datetime.now()
|
|
384
|
+
|
|
385
|
+
def Today(s):
|
|
386
|
+
return datetime.date.today()
|
|
387
|
+
|
|
388
|
+
def TimeDeltaDays(s):
|
|
389
|
+
return datetime.timedelta(days=f(s[1], c))
|
|
390
|
+
|
|
391
|
+
def TimeDeltaMinutes(s):
|
|
392
|
+
return datetime.timedelta(minutes=f(s[1], c))
|
|
393
|
+
|
|
394
|
+
def TimeDeltaHours(s):
|
|
395
|
+
return datetime.timedelta(hours=f(s[1], c))
|
|
396
|
+
|
|
397
|
+
def TimeDeltaWeeks(s):
|
|
398
|
+
return datetime.timedelta(weeks=f(s[1], c))
|
|
399
|
+
|
|
346
400
|
constructs = {
|
|
347
401
|
"Sum": Sum,
|
|
348
|
-
"Add":
|
|
402
|
+
"Add": Add,
|
|
349
403
|
"Subtract": lambda s: reduce(
|
|
350
404
|
lambda a, b: a - b, [f(x, c) for x in s[1:]]
|
|
351
405
|
),
|
|
@@ -401,11 +455,29 @@ def create_mathjson_solver(solver_parameters):
|
|
|
401
455
|
"IsDefined": lambda s: s[1] in c,
|
|
402
456
|
"Map": Map,
|
|
403
457
|
"HasMatchingSublist": HasMatchingSublist,
|
|
458
|
+
"Strptime": Strptime,
|
|
459
|
+
"Strftime": Strftime,
|
|
460
|
+
"Today": Today,
|
|
461
|
+
"Now": Now,
|
|
462
|
+
"TimeDeltaWeeks": TimeDeltaWeeks,
|
|
463
|
+
"TimeDeltaHours": TimeDeltaHours,
|
|
464
|
+
"TimeDeltaMinutes": TimeDeltaMinutes,
|
|
465
|
+
"TimeDeltaDays": TimeDeltaDays,
|
|
404
466
|
}
|
|
405
467
|
if s[0] in constructs:
|
|
406
468
|
try:
|
|
407
469
|
return constructs[s[0]](s)
|
|
408
|
-
|
|
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:
|
|
409
481
|
raise MathJSONException(e, s, mathjson_construct=s[0])
|
|
410
482
|
else:
|
|
411
483
|
# raise MathJSONException(
|
|
@@ -413,7 +485,10 @@ def create_mathjson_solver(solver_parameters):
|
|
|
413
485
|
# )
|
|
414
486
|
return s
|
|
415
487
|
elif s in solver_parameters:
|
|
416
|
-
|
|
488
|
+
try:
|
|
489
|
+
return f(solver_parameters[s], c)
|
|
490
|
+
except RecursionError:
|
|
491
|
+
return solver_parameters[s]
|
|
417
492
|
elif s in c:
|
|
418
493
|
return f(c[s], c)
|
|
419
494
|
else:
|
|
@@ -474,6 +549,14 @@ def extract_variables(s: Union[list, int, float, str], li: set, ignore_list: set
|
|
|
474
549
|
"IsDefined",
|
|
475
550
|
"Map",
|
|
476
551
|
"HasMatchingSublist",
|
|
552
|
+
"Strptime",
|
|
553
|
+
"Strftime",
|
|
554
|
+
"Today",
|
|
555
|
+
"Now",
|
|
556
|
+
"TimeDeltaWeeks",
|
|
557
|
+
"TimeDeltaHours",
|
|
558
|
+
"TimeDeltaMinutes",
|
|
559
|
+
"TimeDeltaDays",
|
|
477
560
|
]
|
|
478
561
|
if isinstance(s, str):
|
|
479
562
|
if s in ignore_list:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: mathjson-solver
|
|
3
|
-
Version: 1.
|
|
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
|
|
@@ -12,6 +12,15 @@ Classifier: Operating System :: OS Independent
|
|
|
12
12
|
Requires-Python: >=3.6
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
|
+
Dynamic: author
|
|
16
|
+
Dynamic: author-email
|
|
17
|
+
Dynamic: classifier
|
|
18
|
+
Dynamic: description
|
|
19
|
+
Dynamic: description-content-type
|
|
20
|
+
Dynamic: home-page
|
|
21
|
+
Dynamic: project-url
|
|
22
|
+
Dynamic: requires-python
|
|
23
|
+
Dynamic: summary
|
|
15
24
|
|
|
16
25
|
# MathJSON Solver
|
|
17
26
|
|
|
@@ -21,14 +30,6 @@ _MathJSON Solver_ is a Python module to numerically evaluate MathJSON expression
|
|
|
21
30
|
|
|
22
31
|
Please ask questions and share feedback in our Gitter chat [https://gitter.im/mathjson-solver/community](https://gitter.im/mathjson-solver/community).
|
|
23
32
|
|
|
24
|
-
## What's new
|
|
25
|
-
|
|
26
|
-
### 1.4.2
|
|
27
|
-
Added `Str` construct. It tries to convert value to string.
|
|
28
|
-
|
|
29
|
-
### 1.4.0
|
|
30
|
-
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.
|
|
31
|
-
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.
|
|
32
33
|
|
|
33
34
|
## How to use
|
|
34
35
|
```python
|
|
@@ -44,75 +45,64 @@ print(answer)
|
|
|
44
45
|
# 9, because 2+3+4=9
|
|
45
46
|
```
|
|
46
47
|
|
|
47
|
-
## How to run tests
|
|
48
|
-
Make sure you have `pytest` installed. Then `cd` into project directory and run:
|
|
49
|
-
```bash
|
|
50
|
-
pytest
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
## Contributing Code
|
|
54
|
-
|
|
55
|
-
We welcome your contributions in the form of pull requests.
|
|
56
|
-
|
|
57
|
-
1. Fork the repo;
|
|
58
|
-
2. Make improvements;
|
|
59
|
-
3. Make a pull request to share your improvements with the community and to include it into official release.
|
|
60
|
-
|
|
61
|
-
|
|
62
48
|
## Currently supported constructs
|
|
63
|
-
|
|
64
|
-
* `Sum`
|
|
65
|
-
* `Subtract`
|
|
66
|
-
* `
|
|
67
|
-
* `
|
|
68
|
-
* `
|
|
69
|
-
* `
|
|
70
|
-
* `
|
|
71
|
-
* `
|
|
72
|
-
* `
|
|
73
|
-
* `
|
|
74
|
-
* `
|
|
75
|
-
* `
|
|
76
|
-
* `
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
* `
|
|
81
|
-
* `
|
|
82
|
-
* `
|
|
83
|
-
* `
|
|
84
|
-
* `
|
|
85
|
-
* `
|
|
86
|
-
* `
|
|
87
|
-
* `
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
* `
|
|
92
|
-
* `
|
|
93
|
-
* `
|
|
94
|
-
* `
|
|
95
|
-
* `
|
|
96
|
-
* `
|
|
97
|
-
* `
|
|
98
|
-
* `
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
* `
|
|
102
|
-
* `
|
|
103
|
-
* `
|
|
104
|
-
* `
|
|
105
|
-
* `
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
* `
|
|
109
|
-
* `
|
|
110
|
-
* `
|
|
111
|
-
* `
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
* `
|
|
115
|
-
|
|
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` -
|
|
116
106
|
|
|
117
107
|
## Examples
|
|
118
108
|
```python
|
|
@@ -133,7 +123,7 @@ We welcome your contributions in the form of pull requests.
|
|
|
133
123
|
["Log2", 8] # log2(8)=3.0
|
|
134
124
|
["Log10", 1000] # log10(1000)=3.0
|
|
135
125
|
["Equal", 10, 10] # 10==10 = True
|
|
136
|
-
["Equal", 10, 12] # 10==
|
|
126
|
+
["Equal", 10, 12] # 10==12 = False
|
|
137
127
|
["Abs", -3.5] # |-3.5| = 3.5
|
|
138
128
|
["Round", -5.123456, 2] # -5.12
|
|
139
129
|
["Round", -5.123456, 0] # -5.0
|
|
@@ -236,7 +226,7 @@ elif 2 == 2 then 20
|
|
|
236
226
|
else 9000
|
|
237
227
|
```
|
|
238
228
|
|
|
239
|
-
`If`
|
|
229
|
+
`If` expressions do not need to be strictly _boolean_. Any value that is not _false_ are considered _true_.
|
|
240
230
|
|
|
241
231
|
### Switch-Case statement
|
|
242
232
|
```
|
|
@@ -267,3 +257,18 @@ except MathJSONException:
|
|
|
267
257
|
```
|
|
268
258
|
|
|
269
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,6 +323,78 @@ from mathjson_solver import create_solver, MathJSONException, extract_variables
|
|
|
259
323
|
],
|
|
260
324
|
False,
|
|
261
325
|
),
|
|
326
|
+
(
|
|
327
|
+
{},
|
|
328
|
+
["Strftime", ["Strptime", "2025-01-10T10:05", "%Y-%m-%dT%H:%M"], "%Y"],
|
|
329
|
+
"2025",
|
|
330
|
+
),
|
|
331
|
+
({}, ["Strftime", ["Today"], "%Y"], "2025"),
|
|
332
|
+
({}, ["Strftime", ["Now"], "%Y"], "2025"),
|
|
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
|
+
),
|
|
262
398
|
],
|
|
263
399
|
)
|
|
264
400
|
def test_solver_simple(parameters, expression, expected_result):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mathjson_solver-1.9.1 → mathjson_solver-1.11.0}/src/mathjson_solver.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|