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
ExpressionEvaluator
for 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_ops
andunary_ops
arguments with dicts of the form{ast.Node, function}
. When theast.Node
used as key is found, it will be evaluated using the givenfunction
.- exception Error#
Internal exception type for
ExpressionEvaluator
s.
- 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**exp
in 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)**2
and 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
num
andexp
were quite accurate for smallnum
and very largeexp
though, except whennum
was a power of 2.