math-engine 0.3.0__tar.gz → 0.3.2__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.
- {math_engine-0.3.0 → math_engine-0.3.2}/PKG-INFO +125 -71
- {math_engine-0.3.0 → math_engine-0.3.2}/README.md +124 -70
- {math_engine-0.3.0 → math_engine-0.3.2}/math_engine/__init__.py +2 -1
- {math_engine-0.3.0 → math_engine-0.3.2}/math_engine.egg-info/PKG-INFO +125 -71
- {math_engine-0.3.0 → math_engine-0.3.2}/pyproject.toml +1 -1
- {math_engine-0.3.0 → math_engine-0.3.2}/LICENSE +0 -0
- {math_engine-0.3.0 → math_engine-0.3.2}/math_engine/ScientificEngine.py +0 -0
- {math_engine-0.3.0 → math_engine-0.3.2}/math_engine/calculator.py +0 -0
- {math_engine-0.3.0 → math_engine-0.3.2}/math_engine/config.json +0 -0
- {math_engine-0.3.0 → math_engine-0.3.2}/math_engine/config_manager.py +0 -0
- {math_engine-0.3.0 → math_engine-0.3.2}/math_engine/error.py +0 -0
- {math_engine-0.3.0 → math_engine-0.3.2}/math_engine.egg-info/SOURCES.txt +0 -0
- {math_engine-0.3.0 → math_engine-0.3.2}/math_engine.egg-info/dependency_links.txt +0 -0
- {math_engine-0.3.0 → math_engine-0.3.2}/math_engine.egg-info/top_level.txt +0 -0
- {math_engine-0.3.0 → math_engine-0.3.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: math-engine
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: A fast and secure mathematical expression evaluator.
|
|
5
5
|
Author-email: Jan Teske <jan.teske.06@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/JanTeske06/math_engine
|
|
@@ -12,18 +12,18 @@ Requires-Python: >=3.8
|
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
|
|
16
|
+
# Math Engine 0.3.2
|
|
16
17
|
|
|
17
18
|
[](https://pypi.org/project/math-engine/)
|
|
18
19
|
[](https://opensource.org/licenses/MIT)
|
|
19
20
|
[](https://pypi.org/project/math-engine/)
|
|
20
21
|
|
|
21
|
-
A fast, safe, configurable expression parser and calculator for Python
|
|
22
|
+
A fast, safe, configurable expression parser and calculator for Python.
|
|
22
23
|
|
|
23
|
-
**math_engine** is a powerful expression evaluation library designed for developers who need a **safe**, **configurable**, and **extendable** alternative to Python’s built-in `eval()` or other ad-hoc parsers.
|
|
24
|
+
**math_engine** is a powerful expression evaluation library designed for developers who need a **safe**, **configurable**, and **extendable** alternative to Python’s built-in `eval()` or other ad-hoc parsers.
|
|
24
25
|
It provides a complete pipeline:
|
|
25
26
|
|
|
26
|
-
|
|
27
27
|
* Tokenizer
|
|
28
28
|
* AST (Abstract Syntax Tree) parser
|
|
29
29
|
* Evaluator (numeric + equation solver)
|
|
@@ -33,7 +33,7 @@ It provides a complete pipeline:
|
|
|
33
33
|
* Scientific functions
|
|
34
34
|
* Strict error codes for reliable debugging and automated testing
|
|
35
35
|
|
|
36
|
-
**Version
|
|
36
|
+
**Version _0.3.2_** adds extensive non-decimal number support (hex, binary, octal), prefix-based type casting, improved settings management, expanded error reporting, and an optional programmer mode with bitwise operations and word-size simulation.
|
|
37
37
|
|
|
38
38
|
This library is ideal for:
|
|
39
39
|
|
|
@@ -58,12 +58,11 @@ This library is ideal for:
|
|
|
58
58
|
* Strong error handling with unique codes
|
|
59
59
|
* Settings system with presets
|
|
60
60
|
* Optional strict modes:
|
|
61
|
-
|
|
62
61
|
* `only_hex`
|
|
63
62
|
* `only_binary`
|
|
64
63
|
* `only_octal`
|
|
65
64
|
|
|
66
|
-
### Non-Decimal Support (0.2.1)
|
|
65
|
+
### Non-Decimal Support (≥ 0.2.1)
|
|
67
66
|
|
|
68
67
|
* Read binary `0b1101`
|
|
69
68
|
* Read octal `0o755`
|
|
@@ -76,9 +75,9 @@ This library is ideal for:
|
|
|
76
75
|
|
|
77
76
|
# Installation
|
|
78
77
|
|
|
79
|
-
```
|
|
78
|
+
```bash
|
|
80
79
|
pip install math-engine
|
|
81
|
-
|
|
80
|
+
````
|
|
82
81
|
|
|
83
82
|
---
|
|
84
83
|
|
|
@@ -109,11 +108,27 @@ math_engine.evaluate("octal: 64")
|
|
|
109
108
|
## Automatic Format Correction
|
|
110
109
|
|
|
111
110
|
```python
|
|
112
|
-
math_engine
|
|
113
|
-
|
|
111
|
+
import math_engine
|
|
112
|
+
|
|
113
|
+
settings = math_engine.load_all_settings()
|
|
114
|
+
settings["correct_output_format"] = True
|
|
115
|
+
math_engine.load_preset(settings)
|
|
116
|
+
|
|
117
|
+
math_engine.evaluate("bool: 3+3=6")
|
|
114
118
|
# True
|
|
115
119
|
```
|
|
116
120
|
|
|
121
|
+
## Reset all Settings to Default
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
import math_engine
|
|
125
|
+
|
|
126
|
+
reset_settings()
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
If a requested output type does not match the actual result, `correct_output_format=True` allows math_engine to fall back to a compatible type instead of raising an error.
|
|
131
|
+
|
|
117
132
|
---
|
|
118
133
|
|
|
119
134
|
# Prefix System (Casting Syntax)
|
|
@@ -145,14 +160,21 @@ math_engine.evaluate("hex: 3 + 3")
|
|
|
145
160
|
```python
|
|
146
161
|
vars = {
|
|
147
162
|
"A": 10,
|
|
148
|
-
"B": 5
|
|
163
|
+
"B": 5,
|
|
149
164
|
}
|
|
150
165
|
|
|
151
|
-
math_engine.evaluate("A + B",
|
|
166
|
+
math_engine.evaluate("A + B", variables=vars)
|
|
167
|
+
# Decimal('15')
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Alternatively, you can pass variables as keyword arguments:
|
|
171
|
+
|
|
172
|
+
```python
|
|
173
|
+
math_engine.evaluate("A + B", A=10, B=5)
|
|
152
174
|
# Decimal('15')
|
|
153
175
|
```
|
|
154
176
|
|
|
155
|
-
Variables
|
|
177
|
+
Variables are mapped internally to a safe internal representation and are designed to be simple and predictable.
|
|
156
178
|
|
|
157
179
|
---
|
|
158
180
|
|
|
@@ -166,7 +188,7 @@ math_engine.evaluate("√(16)")
|
|
|
166
188
|
math_engine.evaluate("pi * 2")
|
|
167
189
|
```
|
|
168
190
|
|
|
169
|
-
All functions are processed by the internal ScientificEngine.
|
|
191
|
+
All functions are processed by the internal `ScientificEngine`, honoring your settings (for example, `use_degrees`).
|
|
170
192
|
|
|
171
193
|
---
|
|
172
194
|
|
|
@@ -195,58 +217,64 @@ math_engine.evaluate("0b1010 * 3")
|
|
|
195
217
|
# Decimal('30')
|
|
196
218
|
```
|
|
197
219
|
|
|
198
|
-
|
|
220
|
+
Non-decimal parsing respects the setting `allow_non_decimal`. If it is set to `False`, using `0b`, `0o`, or `0x` will raise a conversion error.
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
# Bitwise Operations & Developer Mode (v0.3.x)
|
|
199
225
|
|
|
200
|
-
Math Engine
|
|
226
|
+
Math Engine can act as a **programmer's calculator**. It supports standard operator precedence and bitwise logic.
|
|
201
227
|
|
|
202
228
|
### New Operators
|
|
203
229
|
|
|
204
|
-
| Operator | Description | Example
|
|
205
|
-
|
|
|
206
|
-
| `&`
|
|
207
|
-
| `\|`
|
|
208
|
-
| `^`
|
|
209
|
-
| `<<`
|
|
210
|
-
| `>>`
|
|
211
|
-
| `**`
|
|
230
|
+
| Operator | Description | Example | Result |
|
|
231
|
+
| :------- | :---------- | :------- | :----- |
|
|
232
|
+
| `&` | Bitwise AND | `3 & 1` | `1` |
|
|
233
|
+
| `\|` | Bitwise OR | `1 \| 2` | `3` |
|
|
234
|
+
| `^` | Bitwise XOR | `3 ^ 1` | `2` |
|
|
235
|
+
| `<<` | Left Shift | `1 << 2` | `4` |
|
|
236
|
+
| `>>` | Right Shift | `8 >> 2` | `2` |
|
|
237
|
+
| `**` | Power | `2 ** 3` | `8` |
|
|
212
238
|
|
|
213
|
-
>
|
|
239
|
+
> Note: Since `^` is used for **XOR**, use `**` for exponentiation (power).
|
|
214
240
|
|
|
215
241
|
### Word Size & Overflow Simulation
|
|
216
242
|
|
|
217
243
|
You can simulate hardware constraints (like C++ `int8`, `uint16`, etc.) by setting a `word_size`.
|
|
218
244
|
|
|
219
|
-
* **`word_size: 0` (Default):** Python mode (
|
|
220
|
-
* **`word_size: 8/16/32/64`:** Enforces bit limits. Numbers will wrap around (overflow).
|
|
245
|
+
* **`word_size: 0` (Default):** Python mode (arbitrary precision, no overflow).
|
|
246
|
+
* **`word_size: 8/16/32/64`:** Enforces bit limits. Numbers will wrap around (overflow) accordingly.
|
|
221
247
|
|
|
222
248
|
### Signed vs. Unsigned Mode
|
|
223
249
|
|
|
224
|
-
When `word_size > 0`, you can
|
|
250
|
+
When `word_size > 0`, you can control how values are interpreted via `signed_mode`:
|
|
225
251
|
|
|
226
|
-
* **`True` (Default):**
|
|
227
|
-
* **`False`:**
|
|
252
|
+
* **`True` (Default):** Use **Two's Complement** for negative values.
|
|
253
|
+
* **`False`:** Treat all values as unsigned.
|
|
228
254
|
|
|
229
|
-
**Example: 8-
|
|
255
|
+
**Example: 8-bit Simulation**
|
|
230
256
|
|
|
231
257
|
```python
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
258
|
+
import math_engine
|
|
259
|
+
|
|
260
|
+
settings = math_engine.load_all_settings()
|
|
261
|
+
settings["word_size"] = 8
|
|
262
|
+
settings["signed_mode"] = True
|
|
237
263
|
math_engine.load_preset(settings)
|
|
238
264
|
|
|
239
|
-
# Calculation: 127 + 1
|
|
240
|
-
# Mathematically 128, but in 8-bit signed this overflows to -128.
|
|
241
265
|
math_engine.evaluate("127 + 1")
|
|
266
|
+
# In 8-bit signed arithmetic this overflows to -128
|
|
242
267
|
# Decimal('-128')
|
|
268
|
+
```
|
|
243
269
|
|
|
244
|
-
|
|
245
|
-
|
|
270
|
+
Hex output respects the current word size and signedness:
|
|
271
|
+
|
|
272
|
+
```python
|
|
246
273
|
math_engine.evaluate("hex: -1")
|
|
247
|
-
#
|
|
274
|
+
# Hex representation consistent with word_size / signed_mode configuration
|
|
248
275
|
```
|
|
249
|
-
|
|
276
|
+
|
|
277
|
+
### Force-only-hex Mode
|
|
250
278
|
|
|
251
279
|
```python
|
|
252
280
|
settings = math_engine.load_all_settings()
|
|
@@ -257,39 +285,58 @@ math_engine.evaluate("FF + 3")
|
|
|
257
285
|
# Decimal('258')
|
|
258
286
|
```
|
|
259
287
|
|
|
260
|
-
Input validation ensures safety.
|
|
288
|
+
Input validation ensures safety and prevents mixing incompatible formats in strict modes.
|
|
261
289
|
|
|
262
290
|
---
|
|
263
291
|
|
|
264
292
|
# Settings System
|
|
265
293
|
|
|
266
|
-
You
|
|
294
|
+
You can inspect and modify settings programmatically.
|
|
295
|
+
|
|
296
|
+
### Load Current Settings
|
|
297
|
+
|
|
298
|
+
```python
|
|
299
|
+
import math_engine
|
|
300
|
+
|
|
301
|
+
settings = math_engine.load_all_settings()
|
|
302
|
+
print(settings)
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Apply a Full Preset
|
|
306
|
+
|
|
307
|
+
This is a plain Python `dict` (not JSON):
|
|
267
308
|
|
|
268
309
|
```python
|
|
269
310
|
preset = {
|
|
270
311
|
"decimal_places": 2,
|
|
271
|
-
"use_degrees":
|
|
272
|
-
"allow_augmented_assignment":
|
|
273
|
-
"fractions":
|
|
274
|
-
"allow_non_decimal":
|
|
275
|
-
"debug":
|
|
276
|
-
"correct_output_format":
|
|
312
|
+
"use_degrees": False,
|
|
313
|
+
"allow_augmented_assignment": True,
|
|
314
|
+
"fractions": False,
|
|
315
|
+
"allow_non_decimal": True,
|
|
316
|
+
"debug": False,
|
|
317
|
+
"correct_output_format": True,
|
|
277
318
|
"default_output_format": "decimal:",
|
|
278
|
-
"only_hex":
|
|
279
|
-
"only_binary":
|
|
280
|
-
"only_octal":
|
|
281
|
-
# New in
|
|
282
|
-
"word_size": 0,
|
|
283
|
-
"signed_mode":
|
|
319
|
+
"only_hex": False,
|
|
320
|
+
"only_binary": False,
|
|
321
|
+
"only_octal": False,
|
|
322
|
+
# New in 0.3.0
|
|
323
|
+
"word_size": 0, # 0 = unlimited, or 8, 16, 32, 64
|
|
324
|
+
"signed_mode": True, # True = Two's Complement, False = Unsigned
|
|
284
325
|
}
|
|
285
326
|
|
|
286
327
|
math_engine.load_preset(preset)
|
|
287
328
|
```
|
|
288
329
|
|
|
289
|
-
|
|
330
|
+
### Change a Single Setting
|
|
290
331
|
|
|
291
332
|
```python
|
|
292
|
-
math_engine.
|
|
333
|
+
math_engine.change_setting("decimal_places", 10)
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
You can also read a single setting:
|
|
337
|
+
|
|
338
|
+
```python
|
|
339
|
+
decimal_places = math_engine.load_one_setting("decimal_places")
|
|
293
340
|
```
|
|
294
341
|
|
|
295
342
|
---
|
|
@@ -306,10 +353,15 @@ Every error is a custom exception with:
|
|
|
306
353
|
Example:
|
|
307
354
|
|
|
308
355
|
```python
|
|
356
|
+
import math_engine
|
|
357
|
+
from math_engine import error as E
|
|
358
|
+
|
|
309
359
|
try:
|
|
310
360
|
math_engine.evaluate("1/0")
|
|
311
|
-
except
|
|
312
|
-
print(e.code)
|
|
361
|
+
except E.CalculationError as e:
|
|
362
|
+
print(e.code) # 3003
|
|
363
|
+
print(e.message) # "Division by zero"
|
|
364
|
+
print(e.equation) # "1/0"
|
|
313
365
|
```
|
|
314
366
|
|
|
315
367
|
### Example Error Codes
|
|
@@ -323,6 +375,9 @@ except math_engine.error.CalculationError as e:
|
|
|
323
375
|
| 8000 | Conversion to int failed |
|
|
324
376
|
| 8006 | Output conversion error |
|
|
325
377
|
|
|
378
|
+
For a complete list of all error codes and their meanings, please see the **[Error Codes Reference](https://github.com/JanTeske06/math_engine/blob/master/ERRORS.md)**.
|
|
379
|
+
|
|
380
|
+
---
|
|
326
381
|
---
|
|
327
382
|
|
|
328
383
|
# Testing and Reliability
|
|
@@ -334,18 +389,21 @@ math_engine is designed with testing in mind:
|
|
|
334
389
|
* Unit-test friendly behavior
|
|
335
390
|
* No reliance on Python’s runtime execution
|
|
336
391
|
|
|
337
|
-
|
|
392
|
+
Example with `pytest`:
|
|
338
393
|
|
|
339
394
|
```python
|
|
340
395
|
import pytest
|
|
396
|
+
import math_engine
|
|
341
397
|
from math_engine import error as E
|
|
342
398
|
|
|
343
|
-
def
|
|
399
|
+
def test_division_by_zero_error_code():
|
|
344
400
|
with pytest.raises(E.CalculationError) as exc:
|
|
345
401
|
math_engine.evaluate("1/0")
|
|
346
402
|
assert exc.value.code == "3003"
|
|
347
403
|
```
|
|
348
404
|
|
|
405
|
+
You can also test more advanced behavior (non-decimal, strict modes, bitwise operations, etc.) in the same way.
|
|
406
|
+
|
|
349
407
|
---
|
|
350
408
|
|
|
351
409
|
# Performance
|
|
@@ -367,7 +425,7 @@ Future updates focus on:
|
|
|
367
425
|
|
|
368
426
|
### Calculator Applications
|
|
369
427
|
|
|
370
|
-
Build full scientific calculators, both GUI and command line.
|
|
428
|
+
Build full scientific or programmer calculators, both GUI and command line.
|
|
371
429
|
|
|
372
430
|
### Education
|
|
373
431
|
|
|
@@ -377,7 +435,7 @@ Great for learning about lexers, parsers, ASTs, and expression evaluation.
|
|
|
377
435
|
|
|
378
436
|
Safe math evaluation inside larger apps.
|
|
379
437
|
|
|
380
|
-
### Security-
|
|
438
|
+
### Security-Sensitive Input
|
|
381
439
|
|
|
382
440
|
Rejects arbitrary Python code and ensures controlled evaluation.
|
|
383
441
|
|
|
@@ -392,7 +450,6 @@ Conversion between hex/bin/decimal is easy and reliable.
|
|
|
392
450
|
* Non-decimal output formatting upgrades
|
|
393
451
|
* Strict type-matching modes
|
|
394
452
|
* Function overloading
|
|
395
|
-
* Bitwise operators (`&`, `|`, `^`, `<<`, `>>`)
|
|
396
453
|
* Memory/register system
|
|
397
454
|
* Speed optimization via caching
|
|
398
455
|
* User-defined functions
|
|
@@ -412,9 +469,6 @@ MIT License
|
|
|
412
469
|
Contributions are welcome.
|
|
413
470
|
Feel free to submit issues or PRs on GitHub:
|
|
414
471
|
|
|
415
|
-
```
|
|
472
|
+
```text
|
|
416
473
|
https://github.com/JanTeske06/math_engine
|
|
417
474
|
```
|
|
418
|
-
|
|
419
|
-
---
|
|
420
|
-
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
|
+
# Math Engine 0.3.2
|
|
2
3
|
|
|
3
4
|
[](https://pypi.org/project/math-engine/)
|
|
4
5
|
[](https://opensource.org/licenses/MIT)
|
|
5
6
|
[](https://pypi.org/project/math-engine/)
|
|
6
7
|
|
|
7
|
-
A fast, safe, configurable expression parser and calculator for Python
|
|
8
|
+
A fast, safe, configurable expression parser and calculator for Python.
|
|
8
9
|
|
|
9
|
-
**math_engine** is a powerful expression evaluation library designed for developers who need a **safe**, **configurable**, and **extendable** alternative to Python’s built-in `eval()` or other ad-hoc parsers.
|
|
10
|
+
**math_engine** is a powerful expression evaluation library designed for developers who need a **safe**, **configurable**, and **extendable** alternative to Python’s built-in `eval()` or other ad-hoc parsers.
|
|
10
11
|
It provides a complete pipeline:
|
|
11
12
|
|
|
12
|
-
|
|
13
13
|
* Tokenizer
|
|
14
14
|
* AST (Abstract Syntax Tree) parser
|
|
15
15
|
* Evaluator (numeric + equation solver)
|
|
@@ -19,7 +19,7 @@ It provides a complete pipeline:
|
|
|
19
19
|
* Scientific functions
|
|
20
20
|
* Strict error codes for reliable debugging and automated testing
|
|
21
21
|
|
|
22
|
-
**Version
|
|
22
|
+
**Version _0.3.2_** adds extensive non-decimal number support (hex, binary, octal), prefix-based type casting, improved settings management, expanded error reporting, and an optional programmer mode with bitwise operations and word-size simulation.
|
|
23
23
|
|
|
24
24
|
This library is ideal for:
|
|
25
25
|
|
|
@@ -44,12 +44,11 @@ This library is ideal for:
|
|
|
44
44
|
* Strong error handling with unique codes
|
|
45
45
|
* Settings system with presets
|
|
46
46
|
* Optional strict modes:
|
|
47
|
-
|
|
48
47
|
* `only_hex`
|
|
49
48
|
* `only_binary`
|
|
50
49
|
* `only_octal`
|
|
51
50
|
|
|
52
|
-
### Non-Decimal Support (0.2.1)
|
|
51
|
+
### Non-Decimal Support (≥ 0.2.1)
|
|
53
52
|
|
|
54
53
|
* Read binary `0b1101`
|
|
55
54
|
* Read octal `0o755`
|
|
@@ -62,9 +61,9 @@ This library is ideal for:
|
|
|
62
61
|
|
|
63
62
|
# Installation
|
|
64
63
|
|
|
65
|
-
```
|
|
64
|
+
```bash
|
|
66
65
|
pip install math-engine
|
|
67
|
-
|
|
66
|
+
````
|
|
68
67
|
|
|
69
68
|
---
|
|
70
69
|
|
|
@@ -95,11 +94,27 @@ math_engine.evaluate("octal: 64")
|
|
|
95
94
|
## Automatic Format Correction
|
|
96
95
|
|
|
97
96
|
```python
|
|
98
|
-
math_engine
|
|
99
|
-
|
|
97
|
+
import math_engine
|
|
98
|
+
|
|
99
|
+
settings = math_engine.load_all_settings()
|
|
100
|
+
settings["correct_output_format"] = True
|
|
101
|
+
math_engine.load_preset(settings)
|
|
102
|
+
|
|
103
|
+
math_engine.evaluate("bool: 3+3=6")
|
|
100
104
|
# True
|
|
101
105
|
```
|
|
102
106
|
|
|
107
|
+
## Reset all Settings to Default
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
import math_engine
|
|
111
|
+
|
|
112
|
+
reset_settings()
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
If a requested output type does not match the actual result, `correct_output_format=True` allows math_engine to fall back to a compatible type instead of raising an error.
|
|
117
|
+
|
|
103
118
|
---
|
|
104
119
|
|
|
105
120
|
# Prefix System (Casting Syntax)
|
|
@@ -131,14 +146,21 @@ math_engine.evaluate("hex: 3 + 3")
|
|
|
131
146
|
```python
|
|
132
147
|
vars = {
|
|
133
148
|
"A": 10,
|
|
134
|
-
"B": 5
|
|
149
|
+
"B": 5,
|
|
135
150
|
}
|
|
136
151
|
|
|
137
|
-
math_engine.evaluate("A + B",
|
|
152
|
+
math_engine.evaluate("A + B", variables=vars)
|
|
153
|
+
# Decimal('15')
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Alternatively, you can pass variables as keyword arguments:
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
math_engine.evaluate("A + B", A=10, B=5)
|
|
138
160
|
# Decimal('15')
|
|
139
161
|
```
|
|
140
162
|
|
|
141
|
-
Variables
|
|
163
|
+
Variables are mapped internally to a safe internal representation and are designed to be simple and predictable.
|
|
142
164
|
|
|
143
165
|
---
|
|
144
166
|
|
|
@@ -152,7 +174,7 @@ math_engine.evaluate("√(16)")
|
|
|
152
174
|
math_engine.evaluate("pi * 2")
|
|
153
175
|
```
|
|
154
176
|
|
|
155
|
-
All functions are processed by the internal ScientificEngine.
|
|
177
|
+
All functions are processed by the internal `ScientificEngine`, honoring your settings (for example, `use_degrees`).
|
|
156
178
|
|
|
157
179
|
---
|
|
158
180
|
|
|
@@ -181,58 +203,64 @@ math_engine.evaluate("0b1010 * 3")
|
|
|
181
203
|
# Decimal('30')
|
|
182
204
|
```
|
|
183
205
|
|
|
184
|
-
|
|
206
|
+
Non-decimal parsing respects the setting `allow_non_decimal`. If it is set to `False`, using `0b`, `0o`, or `0x` will raise a conversion error.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
# Bitwise Operations & Developer Mode (v0.3.x)
|
|
185
211
|
|
|
186
|
-
Math Engine
|
|
212
|
+
Math Engine can act as a **programmer's calculator**. It supports standard operator precedence and bitwise logic.
|
|
187
213
|
|
|
188
214
|
### New Operators
|
|
189
215
|
|
|
190
|
-
| Operator | Description | Example
|
|
191
|
-
|
|
|
192
|
-
| `&`
|
|
193
|
-
| `\|`
|
|
194
|
-
| `^`
|
|
195
|
-
| `<<`
|
|
196
|
-
| `>>`
|
|
197
|
-
| `**`
|
|
216
|
+
| Operator | Description | Example | Result |
|
|
217
|
+
| :------- | :---------- | :------- | :----- |
|
|
218
|
+
| `&` | Bitwise AND | `3 & 1` | `1` |
|
|
219
|
+
| `\|` | Bitwise OR | `1 \| 2` | `3` |
|
|
220
|
+
| `^` | Bitwise XOR | `3 ^ 1` | `2` |
|
|
221
|
+
| `<<` | Left Shift | `1 << 2` | `4` |
|
|
222
|
+
| `>>` | Right Shift | `8 >> 2` | `2` |
|
|
223
|
+
| `**` | Power | `2 ** 3` | `8` |
|
|
198
224
|
|
|
199
|
-
>
|
|
225
|
+
> Note: Since `^` is used for **XOR**, use `**` for exponentiation (power).
|
|
200
226
|
|
|
201
227
|
### Word Size & Overflow Simulation
|
|
202
228
|
|
|
203
229
|
You can simulate hardware constraints (like C++ `int8`, `uint16`, etc.) by setting a `word_size`.
|
|
204
230
|
|
|
205
|
-
* **`word_size: 0` (Default):** Python mode (
|
|
206
|
-
* **`word_size: 8/16/32/64`:** Enforces bit limits. Numbers will wrap around (overflow).
|
|
231
|
+
* **`word_size: 0` (Default):** Python mode (arbitrary precision, no overflow).
|
|
232
|
+
* **`word_size: 8/16/32/64`:** Enforces bit limits. Numbers will wrap around (overflow) accordingly.
|
|
207
233
|
|
|
208
234
|
### Signed vs. Unsigned Mode
|
|
209
235
|
|
|
210
|
-
When `word_size > 0`, you can
|
|
236
|
+
When `word_size > 0`, you can control how values are interpreted via `signed_mode`:
|
|
211
237
|
|
|
212
|
-
* **`True` (Default):**
|
|
213
|
-
* **`False`:**
|
|
238
|
+
* **`True` (Default):** Use **Two's Complement** for negative values.
|
|
239
|
+
* **`False`:** Treat all values as unsigned.
|
|
214
240
|
|
|
215
|
-
**Example: 8-
|
|
241
|
+
**Example: 8-bit Simulation**
|
|
216
242
|
|
|
217
243
|
```python
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
244
|
+
import math_engine
|
|
245
|
+
|
|
246
|
+
settings = math_engine.load_all_settings()
|
|
247
|
+
settings["word_size"] = 8
|
|
248
|
+
settings["signed_mode"] = True
|
|
223
249
|
math_engine.load_preset(settings)
|
|
224
250
|
|
|
225
|
-
# Calculation: 127 + 1
|
|
226
|
-
# Mathematically 128, but in 8-bit signed this overflows to -128.
|
|
227
251
|
math_engine.evaluate("127 + 1")
|
|
252
|
+
# In 8-bit signed arithmetic this overflows to -128
|
|
228
253
|
# Decimal('-128')
|
|
254
|
+
```
|
|
229
255
|
|
|
230
|
-
|
|
231
|
-
|
|
256
|
+
Hex output respects the current word size and signedness:
|
|
257
|
+
|
|
258
|
+
```python
|
|
232
259
|
math_engine.evaluate("hex: -1")
|
|
233
|
-
#
|
|
260
|
+
# Hex representation consistent with word_size / signed_mode configuration
|
|
234
261
|
```
|
|
235
|
-
|
|
262
|
+
|
|
263
|
+
### Force-only-hex Mode
|
|
236
264
|
|
|
237
265
|
```python
|
|
238
266
|
settings = math_engine.load_all_settings()
|
|
@@ -243,39 +271,58 @@ math_engine.evaluate("FF + 3")
|
|
|
243
271
|
# Decimal('258')
|
|
244
272
|
```
|
|
245
273
|
|
|
246
|
-
Input validation ensures safety.
|
|
274
|
+
Input validation ensures safety and prevents mixing incompatible formats in strict modes.
|
|
247
275
|
|
|
248
276
|
---
|
|
249
277
|
|
|
250
278
|
# Settings System
|
|
251
279
|
|
|
252
|
-
You
|
|
280
|
+
You can inspect and modify settings programmatically.
|
|
281
|
+
|
|
282
|
+
### Load Current Settings
|
|
283
|
+
|
|
284
|
+
```python
|
|
285
|
+
import math_engine
|
|
286
|
+
|
|
287
|
+
settings = math_engine.load_all_settings()
|
|
288
|
+
print(settings)
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Apply a Full Preset
|
|
292
|
+
|
|
293
|
+
This is a plain Python `dict` (not JSON):
|
|
253
294
|
|
|
254
295
|
```python
|
|
255
296
|
preset = {
|
|
256
297
|
"decimal_places": 2,
|
|
257
|
-
"use_degrees":
|
|
258
|
-
"allow_augmented_assignment":
|
|
259
|
-
"fractions":
|
|
260
|
-
"allow_non_decimal":
|
|
261
|
-
"debug":
|
|
262
|
-
"correct_output_format":
|
|
298
|
+
"use_degrees": False,
|
|
299
|
+
"allow_augmented_assignment": True,
|
|
300
|
+
"fractions": False,
|
|
301
|
+
"allow_non_decimal": True,
|
|
302
|
+
"debug": False,
|
|
303
|
+
"correct_output_format": True,
|
|
263
304
|
"default_output_format": "decimal:",
|
|
264
|
-
"only_hex":
|
|
265
|
-
"only_binary":
|
|
266
|
-
"only_octal":
|
|
267
|
-
# New in
|
|
268
|
-
"word_size": 0,
|
|
269
|
-
"signed_mode":
|
|
305
|
+
"only_hex": False,
|
|
306
|
+
"only_binary": False,
|
|
307
|
+
"only_octal": False,
|
|
308
|
+
# New in 0.3.0
|
|
309
|
+
"word_size": 0, # 0 = unlimited, or 8, 16, 32, 64
|
|
310
|
+
"signed_mode": True, # True = Two's Complement, False = Unsigned
|
|
270
311
|
}
|
|
271
312
|
|
|
272
313
|
math_engine.load_preset(preset)
|
|
273
314
|
```
|
|
274
315
|
|
|
275
|
-
|
|
316
|
+
### Change a Single Setting
|
|
276
317
|
|
|
277
318
|
```python
|
|
278
|
-
math_engine.
|
|
319
|
+
math_engine.change_setting("decimal_places", 10)
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
You can also read a single setting:
|
|
323
|
+
|
|
324
|
+
```python
|
|
325
|
+
decimal_places = math_engine.load_one_setting("decimal_places")
|
|
279
326
|
```
|
|
280
327
|
|
|
281
328
|
---
|
|
@@ -292,10 +339,15 @@ Every error is a custom exception with:
|
|
|
292
339
|
Example:
|
|
293
340
|
|
|
294
341
|
```python
|
|
342
|
+
import math_engine
|
|
343
|
+
from math_engine import error as E
|
|
344
|
+
|
|
295
345
|
try:
|
|
296
346
|
math_engine.evaluate("1/0")
|
|
297
|
-
except
|
|
298
|
-
print(e.code)
|
|
347
|
+
except E.CalculationError as e:
|
|
348
|
+
print(e.code) # 3003
|
|
349
|
+
print(e.message) # "Division by zero"
|
|
350
|
+
print(e.equation) # "1/0"
|
|
299
351
|
```
|
|
300
352
|
|
|
301
353
|
### Example Error Codes
|
|
@@ -309,6 +361,9 @@ except math_engine.error.CalculationError as e:
|
|
|
309
361
|
| 8000 | Conversion to int failed |
|
|
310
362
|
| 8006 | Output conversion error |
|
|
311
363
|
|
|
364
|
+
For a complete list of all error codes and their meanings, please see the **[Error Codes Reference](https://github.com/JanTeske06/math_engine/blob/master/ERRORS.md)**.
|
|
365
|
+
|
|
366
|
+
---
|
|
312
367
|
---
|
|
313
368
|
|
|
314
369
|
# Testing and Reliability
|
|
@@ -320,18 +375,21 @@ math_engine is designed with testing in mind:
|
|
|
320
375
|
* Unit-test friendly behavior
|
|
321
376
|
* No reliance on Python’s runtime execution
|
|
322
377
|
|
|
323
|
-
|
|
378
|
+
Example with `pytest`:
|
|
324
379
|
|
|
325
380
|
```python
|
|
326
381
|
import pytest
|
|
382
|
+
import math_engine
|
|
327
383
|
from math_engine import error as E
|
|
328
384
|
|
|
329
|
-
def
|
|
385
|
+
def test_division_by_zero_error_code():
|
|
330
386
|
with pytest.raises(E.CalculationError) as exc:
|
|
331
387
|
math_engine.evaluate("1/0")
|
|
332
388
|
assert exc.value.code == "3003"
|
|
333
389
|
```
|
|
334
390
|
|
|
391
|
+
You can also test more advanced behavior (non-decimal, strict modes, bitwise operations, etc.) in the same way.
|
|
392
|
+
|
|
335
393
|
---
|
|
336
394
|
|
|
337
395
|
# Performance
|
|
@@ -353,7 +411,7 @@ Future updates focus on:
|
|
|
353
411
|
|
|
354
412
|
### Calculator Applications
|
|
355
413
|
|
|
356
|
-
Build full scientific calculators, both GUI and command line.
|
|
414
|
+
Build full scientific or programmer calculators, both GUI and command line.
|
|
357
415
|
|
|
358
416
|
### Education
|
|
359
417
|
|
|
@@ -363,7 +421,7 @@ Great for learning about lexers, parsers, ASTs, and expression evaluation.
|
|
|
363
421
|
|
|
364
422
|
Safe math evaluation inside larger apps.
|
|
365
423
|
|
|
366
|
-
### Security-
|
|
424
|
+
### Security-Sensitive Input
|
|
367
425
|
|
|
368
426
|
Rejects arbitrary Python code and ensures controlled evaluation.
|
|
369
427
|
|
|
@@ -378,7 +436,6 @@ Conversion between hex/bin/decimal is easy and reliable.
|
|
|
378
436
|
* Non-decimal output formatting upgrades
|
|
379
437
|
* Strict type-matching modes
|
|
380
438
|
* Function overloading
|
|
381
|
-
* Bitwise operators (`&`, `|`, `^`, `<<`, `>>`)
|
|
382
439
|
* Memory/register system
|
|
383
440
|
* Speed optimization via caching
|
|
384
441
|
* User-defined functions
|
|
@@ -398,9 +455,6 @@ MIT License
|
|
|
398
455
|
Contributions are welcome.
|
|
399
456
|
Feel free to submit issues or PRs on GitHub:
|
|
400
457
|
|
|
401
|
-
```
|
|
458
|
+
```text
|
|
402
459
|
https://github.com/JanTeske06/math_engine
|
|
403
460
|
```
|
|
404
|
-
|
|
405
|
-
---
|
|
406
|
-
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: math-engine
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: A fast and secure mathematical expression evaluator.
|
|
5
5
|
Author-email: Jan Teske <jan.teske.06@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/JanTeske06/math_engine
|
|
@@ -12,18 +12,18 @@ Requires-Python: >=3.8
|
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
|
|
16
|
+
# Math Engine 0.3.2
|
|
16
17
|
|
|
17
18
|
[](https://pypi.org/project/math-engine/)
|
|
18
19
|
[](https://opensource.org/licenses/MIT)
|
|
19
20
|
[](https://pypi.org/project/math-engine/)
|
|
20
21
|
|
|
21
|
-
A fast, safe, configurable expression parser and calculator for Python
|
|
22
|
+
A fast, safe, configurable expression parser and calculator for Python.
|
|
22
23
|
|
|
23
|
-
**math_engine** is a powerful expression evaluation library designed for developers who need a **safe**, **configurable**, and **extendable** alternative to Python’s built-in `eval()` or other ad-hoc parsers.
|
|
24
|
+
**math_engine** is a powerful expression evaluation library designed for developers who need a **safe**, **configurable**, and **extendable** alternative to Python’s built-in `eval()` or other ad-hoc parsers.
|
|
24
25
|
It provides a complete pipeline:
|
|
25
26
|
|
|
26
|
-
|
|
27
27
|
* Tokenizer
|
|
28
28
|
* AST (Abstract Syntax Tree) parser
|
|
29
29
|
* Evaluator (numeric + equation solver)
|
|
@@ -33,7 +33,7 @@ It provides a complete pipeline:
|
|
|
33
33
|
* Scientific functions
|
|
34
34
|
* Strict error codes for reliable debugging and automated testing
|
|
35
35
|
|
|
36
|
-
**Version
|
|
36
|
+
**Version _0.3.2_** adds extensive non-decimal number support (hex, binary, octal), prefix-based type casting, improved settings management, expanded error reporting, and an optional programmer mode with bitwise operations and word-size simulation.
|
|
37
37
|
|
|
38
38
|
This library is ideal for:
|
|
39
39
|
|
|
@@ -58,12 +58,11 @@ This library is ideal for:
|
|
|
58
58
|
* Strong error handling with unique codes
|
|
59
59
|
* Settings system with presets
|
|
60
60
|
* Optional strict modes:
|
|
61
|
-
|
|
62
61
|
* `only_hex`
|
|
63
62
|
* `only_binary`
|
|
64
63
|
* `only_octal`
|
|
65
64
|
|
|
66
|
-
### Non-Decimal Support (0.2.1)
|
|
65
|
+
### Non-Decimal Support (≥ 0.2.1)
|
|
67
66
|
|
|
68
67
|
* Read binary `0b1101`
|
|
69
68
|
* Read octal `0o755`
|
|
@@ -76,9 +75,9 @@ This library is ideal for:
|
|
|
76
75
|
|
|
77
76
|
# Installation
|
|
78
77
|
|
|
79
|
-
```
|
|
78
|
+
```bash
|
|
80
79
|
pip install math-engine
|
|
81
|
-
|
|
80
|
+
````
|
|
82
81
|
|
|
83
82
|
---
|
|
84
83
|
|
|
@@ -109,11 +108,27 @@ math_engine.evaluate("octal: 64")
|
|
|
109
108
|
## Automatic Format Correction
|
|
110
109
|
|
|
111
110
|
```python
|
|
112
|
-
math_engine
|
|
113
|
-
|
|
111
|
+
import math_engine
|
|
112
|
+
|
|
113
|
+
settings = math_engine.load_all_settings()
|
|
114
|
+
settings["correct_output_format"] = True
|
|
115
|
+
math_engine.load_preset(settings)
|
|
116
|
+
|
|
117
|
+
math_engine.evaluate("bool: 3+3=6")
|
|
114
118
|
# True
|
|
115
119
|
```
|
|
116
120
|
|
|
121
|
+
## Reset all Settings to Default
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
import math_engine
|
|
125
|
+
|
|
126
|
+
reset_settings()
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
If a requested output type does not match the actual result, `correct_output_format=True` allows math_engine to fall back to a compatible type instead of raising an error.
|
|
131
|
+
|
|
117
132
|
---
|
|
118
133
|
|
|
119
134
|
# Prefix System (Casting Syntax)
|
|
@@ -145,14 +160,21 @@ math_engine.evaluate("hex: 3 + 3")
|
|
|
145
160
|
```python
|
|
146
161
|
vars = {
|
|
147
162
|
"A": 10,
|
|
148
|
-
"B": 5
|
|
163
|
+
"B": 5,
|
|
149
164
|
}
|
|
150
165
|
|
|
151
|
-
math_engine.evaluate("A + B",
|
|
166
|
+
math_engine.evaluate("A + B", variables=vars)
|
|
167
|
+
# Decimal('15')
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Alternatively, you can pass variables as keyword arguments:
|
|
171
|
+
|
|
172
|
+
```python
|
|
173
|
+
math_engine.evaluate("A + B", A=10, B=5)
|
|
152
174
|
# Decimal('15')
|
|
153
175
|
```
|
|
154
176
|
|
|
155
|
-
Variables
|
|
177
|
+
Variables are mapped internally to a safe internal representation and are designed to be simple and predictable.
|
|
156
178
|
|
|
157
179
|
---
|
|
158
180
|
|
|
@@ -166,7 +188,7 @@ math_engine.evaluate("√(16)")
|
|
|
166
188
|
math_engine.evaluate("pi * 2")
|
|
167
189
|
```
|
|
168
190
|
|
|
169
|
-
All functions are processed by the internal ScientificEngine.
|
|
191
|
+
All functions are processed by the internal `ScientificEngine`, honoring your settings (for example, `use_degrees`).
|
|
170
192
|
|
|
171
193
|
---
|
|
172
194
|
|
|
@@ -195,58 +217,64 @@ math_engine.evaluate("0b1010 * 3")
|
|
|
195
217
|
# Decimal('30')
|
|
196
218
|
```
|
|
197
219
|
|
|
198
|
-
|
|
220
|
+
Non-decimal parsing respects the setting `allow_non_decimal`. If it is set to `False`, using `0b`, `0o`, or `0x` will raise a conversion error.
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
# Bitwise Operations & Developer Mode (v0.3.x)
|
|
199
225
|
|
|
200
|
-
Math Engine
|
|
226
|
+
Math Engine can act as a **programmer's calculator**. It supports standard operator precedence and bitwise logic.
|
|
201
227
|
|
|
202
228
|
### New Operators
|
|
203
229
|
|
|
204
|
-
| Operator | Description | Example
|
|
205
|
-
|
|
|
206
|
-
| `&`
|
|
207
|
-
| `\|`
|
|
208
|
-
| `^`
|
|
209
|
-
| `<<`
|
|
210
|
-
| `>>`
|
|
211
|
-
| `**`
|
|
230
|
+
| Operator | Description | Example | Result |
|
|
231
|
+
| :------- | :---------- | :------- | :----- |
|
|
232
|
+
| `&` | Bitwise AND | `3 & 1` | `1` |
|
|
233
|
+
| `\|` | Bitwise OR | `1 \| 2` | `3` |
|
|
234
|
+
| `^` | Bitwise XOR | `3 ^ 1` | `2` |
|
|
235
|
+
| `<<` | Left Shift | `1 << 2` | `4` |
|
|
236
|
+
| `>>` | Right Shift | `8 >> 2` | `2` |
|
|
237
|
+
| `**` | Power | `2 ** 3` | `8` |
|
|
212
238
|
|
|
213
|
-
>
|
|
239
|
+
> Note: Since `^` is used for **XOR**, use `**` for exponentiation (power).
|
|
214
240
|
|
|
215
241
|
### Word Size & Overflow Simulation
|
|
216
242
|
|
|
217
243
|
You can simulate hardware constraints (like C++ `int8`, `uint16`, etc.) by setting a `word_size`.
|
|
218
244
|
|
|
219
|
-
* **`word_size: 0` (Default):** Python mode (
|
|
220
|
-
* **`word_size: 8/16/32/64`:** Enforces bit limits. Numbers will wrap around (overflow).
|
|
245
|
+
* **`word_size: 0` (Default):** Python mode (arbitrary precision, no overflow).
|
|
246
|
+
* **`word_size: 8/16/32/64`:** Enforces bit limits. Numbers will wrap around (overflow) accordingly.
|
|
221
247
|
|
|
222
248
|
### Signed vs. Unsigned Mode
|
|
223
249
|
|
|
224
|
-
When `word_size > 0`, you can
|
|
250
|
+
When `word_size > 0`, you can control how values are interpreted via `signed_mode`:
|
|
225
251
|
|
|
226
|
-
* **`True` (Default):**
|
|
227
|
-
* **`False`:**
|
|
252
|
+
* **`True` (Default):** Use **Two's Complement** for negative values.
|
|
253
|
+
* **`False`:** Treat all values as unsigned.
|
|
228
254
|
|
|
229
|
-
**Example: 8-
|
|
255
|
+
**Example: 8-bit Simulation**
|
|
230
256
|
|
|
231
257
|
```python
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
258
|
+
import math_engine
|
|
259
|
+
|
|
260
|
+
settings = math_engine.load_all_settings()
|
|
261
|
+
settings["word_size"] = 8
|
|
262
|
+
settings["signed_mode"] = True
|
|
237
263
|
math_engine.load_preset(settings)
|
|
238
264
|
|
|
239
|
-
# Calculation: 127 + 1
|
|
240
|
-
# Mathematically 128, but in 8-bit signed this overflows to -128.
|
|
241
265
|
math_engine.evaluate("127 + 1")
|
|
266
|
+
# In 8-bit signed arithmetic this overflows to -128
|
|
242
267
|
# Decimal('-128')
|
|
268
|
+
```
|
|
243
269
|
|
|
244
|
-
|
|
245
|
-
|
|
270
|
+
Hex output respects the current word size and signedness:
|
|
271
|
+
|
|
272
|
+
```python
|
|
246
273
|
math_engine.evaluate("hex: -1")
|
|
247
|
-
#
|
|
274
|
+
# Hex representation consistent with word_size / signed_mode configuration
|
|
248
275
|
```
|
|
249
|
-
|
|
276
|
+
|
|
277
|
+
### Force-only-hex Mode
|
|
250
278
|
|
|
251
279
|
```python
|
|
252
280
|
settings = math_engine.load_all_settings()
|
|
@@ -257,39 +285,58 @@ math_engine.evaluate("FF + 3")
|
|
|
257
285
|
# Decimal('258')
|
|
258
286
|
```
|
|
259
287
|
|
|
260
|
-
Input validation ensures safety.
|
|
288
|
+
Input validation ensures safety and prevents mixing incompatible formats in strict modes.
|
|
261
289
|
|
|
262
290
|
---
|
|
263
291
|
|
|
264
292
|
# Settings System
|
|
265
293
|
|
|
266
|
-
You
|
|
294
|
+
You can inspect and modify settings programmatically.
|
|
295
|
+
|
|
296
|
+
### Load Current Settings
|
|
297
|
+
|
|
298
|
+
```python
|
|
299
|
+
import math_engine
|
|
300
|
+
|
|
301
|
+
settings = math_engine.load_all_settings()
|
|
302
|
+
print(settings)
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Apply a Full Preset
|
|
306
|
+
|
|
307
|
+
This is a plain Python `dict` (not JSON):
|
|
267
308
|
|
|
268
309
|
```python
|
|
269
310
|
preset = {
|
|
270
311
|
"decimal_places": 2,
|
|
271
|
-
"use_degrees":
|
|
272
|
-
"allow_augmented_assignment":
|
|
273
|
-
"fractions":
|
|
274
|
-
"allow_non_decimal":
|
|
275
|
-
"debug":
|
|
276
|
-
"correct_output_format":
|
|
312
|
+
"use_degrees": False,
|
|
313
|
+
"allow_augmented_assignment": True,
|
|
314
|
+
"fractions": False,
|
|
315
|
+
"allow_non_decimal": True,
|
|
316
|
+
"debug": False,
|
|
317
|
+
"correct_output_format": True,
|
|
277
318
|
"default_output_format": "decimal:",
|
|
278
|
-
"only_hex":
|
|
279
|
-
"only_binary":
|
|
280
|
-
"only_octal":
|
|
281
|
-
# New in
|
|
282
|
-
"word_size": 0,
|
|
283
|
-
"signed_mode":
|
|
319
|
+
"only_hex": False,
|
|
320
|
+
"only_binary": False,
|
|
321
|
+
"only_octal": False,
|
|
322
|
+
# New in 0.3.0
|
|
323
|
+
"word_size": 0, # 0 = unlimited, or 8, 16, 32, 64
|
|
324
|
+
"signed_mode": True, # True = Two's Complement, False = Unsigned
|
|
284
325
|
}
|
|
285
326
|
|
|
286
327
|
math_engine.load_preset(preset)
|
|
287
328
|
```
|
|
288
329
|
|
|
289
|
-
|
|
330
|
+
### Change a Single Setting
|
|
290
331
|
|
|
291
332
|
```python
|
|
292
|
-
math_engine.
|
|
333
|
+
math_engine.change_setting("decimal_places", 10)
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
You can also read a single setting:
|
|
337
|
+
|
|
338
|
+
```python
|
|
339
|
+
decimal_places = math_engine.load_one_setting("decimal_places")
|
|
293
340
|
```
|
|
294
341
|
|
|
295
342
|
---
|
|
@@ -306,10 +353,15 @@ Every error is a custom exception with:
|
|
|
306
353
|
Example:
|
|
307
354
|
|
|
308
355
|
```python
|
|
356
|
+
import math_engine
|
|
357
|
+
from math_engine import error as E
|
|
358
|
+
|
|
309
359
|
try:
|
|
310
360
|
math_engine.evaluate("1/0")
|
|
311
|
-
except
|
|
312
|
-
print(e.code)
|
|
361
|
+
except E.CalculationError as e:
|
|
362
|
+
print(e.code) # 3003
|
|
363
|
+
print(e.message) # "Division by zero"
|
|
364
|
+
print(e.equation) # "1/0"
|
|
313
365
|
```
|
|
314
366
|
|
|
315
367
|
### Example Error Codes
|
|
@@ -323,6 +375,9 @@ except math_engine.error.CalculationError as e:
|
|
|
323
375
|
| 8000 | Conversion to int failed |
|
|
324
376
|
| 8006 | Output conversion error |
|
|
325
377
|
|
|
378
|
+
For a complete list of all error codes and their meanings, please see the **[Error Codes Reference](https://github.com/JanTeske06/math_engine/blob/master/ERRORS.md)**.
|
|
379
|
+
|
|
380
|
+
---
|
|
326
381
|
---
|
|
327
382
|
|
|
328
383
|
# Testing and Reliability
|
|
@@ -334,18 +389,21 @@ math_engine is designed with testing in mind:
|
|
|
334
389
|
* Unit-test friendly behavior
|
|
335
390
|
* No reliance on Python’s runtime execution
|
|
336
391
|
|
|
337
|
-
|
|
392
|
+
Example with `pytest`:
|
|
338
393
|
|
|
339
394
|
```python
|
|
340
395
|
import pytest
|
|
396
|
+
import math_engine
|
|
341
397
|
from math_engine import error as E
|
|
342
398
|
|
|
343
|
-
def
|
|
399
|
+
def test_division_by_zero_error_code():
|
|
344
400
|
with pytest.raises(E.CalculationError) as exc:
|
|
345
401
|
math_engine.evaluate("1/0")
|
|
346
402
|
assert exc.value.code == "3003"
|
|
347
403
|
```
|
|
348
404
|
|
|
405
|
+
You can also test more advanced behavior (non-decimal, strict modes, bitwise operations, etc.) in the same way.
|
|
406
|
+
|
|
349
407
|
---
|
|
350
408
|
|
|
351
409
|
# Performance
|
|
@@ -367,7 +425,7 @@ Future updates focus on:
|
|
|
367
425
|
|
|
368
426
|
### Calculator Applications
|
|
369
427
|
|
|
370
|
-
Build full scientific calculators, both GUI and command line.
|
|
428
|
+
Build full scientific or programmer calculators, both GUI and command line.
|
|
371
429
|
|
|
372
430
|
### Education
|
|
373
431
|
|
|
@@ -377,7 +435,7 @@ Great for learning about lexers, parsers, ASTs, and expression evaluation.
|
|
|
377
435
|
|
|
378
436
|
Safe math evaluation inside larger apps.
|
|
379
437
|
|
|
380
|
-
### Security-
|
|
438
|
+
### Security-Sensitive Input
|
|
381
439
|
|
|
382
440
|
Rejects arbitrary Python code and ensures controlled evaluation.
|
|
383
441
|
|
|
@@ -392,7 +450,6 @@ Conversion between hex/bin/decimal is easy and reliable.
|
|
|
392
450
|
* Non-decimal output formatting upgrades
|
|
393
451
|
* Strict type-matching modes
|
|
394
452
|
* Function overloading
|
|
395
|
-
* Bitwise operators (`&`, `|`, `^`, `<<`, `>>`)
|
|
396
453
|
* Memory/register system
|
|
397
454
|
* Speed optimization via caching
|
|
398
455
|
* User-defined functions
|
|
@@ -412,9 +469,6 @@ MIT License
|
|
|
412
469
|
Contributions are welcome.
|
|
413
470
|
Feel free to submit issues or PRs on GitHub:
|
|
414
471
|
|
|
415
|
-
```
|
|
472
|
+
```text
|
|
416
473
|
https://github.com/JanTeske06/math_engine
|
|
417
474
|
```
|
|
418
|
-
|
|
419
|
-
---
|
|
420
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|