sopel.tools.calculation#
Tools to help safely do calculations from user input
New in version 5.3.
Note
Most of this is internal machinery. eval_equation() is the “public”
part, used by Sopel’s built-in calc plugin.
- class sopel.tools.calculation.EquationEvaluator#
Specific subclass of
ExpressionEvaluatorfor simple mathThis presets the allowed operators to safeguard against user input that could try to do things that will adversely affect the running bot, while still letting users pass arbitrary mathematical expressions using the available (mostly arithmetic) operators.
- class sopel.tools.calculation.ExpressionEvaluator(
- bin_ops: dict[type[ast.operator], Callable] | None = None,
- unary_ops: dict[type[ast.unaryop], Callable] | None = None,
A generic class for evaluating limited forms of Python expressions.
Instances can pass
binary_opsandunary_opsarguments with dicts of the form{ast.Node, function}. When theast.Nodeused as key is found, it will be evaluated using the givenfunction.- exception Error#
Internal exception type for
ExpressionEvaluators.
- sopel.tools.calculation.eval_equation = <sopel.tools.calculation.EquationEvaluator object>#
Evaluates a Python equation expression and returns the result.
- Parameters:
Supports addition (+), subtraction (-), multiplication (*), division (/), power (**) and modulo (%).
- sopel.tools.calculation.guarded_mul(left: float, right: float) float#
Multiply two values, guarding against overly large inputs.
- Parameters:
left – the left operand
right – the right operand
- Raises:
ValueError – if the inputs are too large to handle safely
- sopel.tools.calculation.guarded_pow(num: float, exp: float) float#
Raise a number to a power, guarding against overly large inputs.
- Parameters:
num – base
exp – exponent
- Raises:
ValueError – if the inputs are too large to handle safely
- sopel.tools.calculation.pow_complexity(num: int, exp: int) float#
Estimate the worst case time
pow()takes to calculate.- Parameters:
num – base
exp – exponent
This function is based on experimental data from the time it takes to calculate
num**expin 32-bit CPython 2.7.6 on an Intel Core i7-2670QM laptop running Windows.It tries to implement this surface: x=exp, y=num
1e5
2e5
3e5
4e5
5e5
6e5
7e5
8e5
9e5
e1
0.03
0.09
0.16
0.25
0.35
0.46
0.60
0.73
0.88
e2
0.08
0.24
0.46
0.73
1.03
1.40
1.80
2.21
2.63
e3
0.15
0.46
0.87
1.39
1.99
2.63
3.35
4.18
5.15
e4
0.24
0.73
1.39
2.20
3.11
4.18
5.39
6.59
7.88
e5
0.34
1.03
2.00
3.12
4.48
5.97
7.56
9.37
11.34
e6
0.46
1.39
2.62
4.16
5.97
7.86
10.09
12.56
15.39
e7
0.60
1.79
3.34
5.39
7.60
10.16
13.00
16.23
19.44
e8
0.73
2.20
4.18
6.60
9.37
12.60
16.26
19.83
23.70
e9
0.87
2.62
5.15
7.93
11.34
15.44
19.40
23.66
28.58
For powers of 2 it tries to implement this surface:
1e7
2e7
3e7
4e7
5e7
6e7
7e7
8e7
9e7
1
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
2
0.21
0.44
0.71
0.92
1.20
1.49
1.66
1.95
2.23
4
0.43
0.91
1.49
1.96
2.50
3.13
3.54
4.10
4.77
8
0.70
1.50
2.24
3.16
3.83
4.66
5.58
6.56
7.67
The function numbers were selected by starting with the theoretical complexity of
exp * log2(num)**2and fiddling with the exponents until it more or less matched with the table.Because this function is based on a limited set of data it might not give accurate results outside these boundaries. The results derived from large
numandexpwere quite accurate for smallnumand very largeexpthough, except whennumwas a power of 2.