1
1
simpleeval (Simple Eval)
2
2
========================
3
3
4
- .. image :: https://github.com/danthedeckie/simpleeval/actions/workflows/ci.yml/badge.svg?branch=gh-actions-build
4
+ .. | build-status | image :: https://github.com/danthedeckie/simpleeval/actions/workflows/ci.yml/badge.svg?branch=gh-actions-build
5
5
:target: https://github.com/danthedeckie/simpleeval/actions/
6
6
:alt: Build Status
7
7
8
- .. image :: https://codecov.io/gh/danthedeckie/simpleeval/branch/master/graph/badge.svg?token=isRnN1yrca
8
+ .. | code-coverage | image :: https://codecov.io/gh/danthedeckie/simpleeval/branch/master/graph/badge.svg?token=isRnN1yrca
9
9
:target: https://codecov.io/gh/danthedeckie/simpleeval
10
- :alt: Code Coverage
10
+ :alt: Code Coverage Status
11
11
12
- .. image :: https://badge.fury.io/py/simpleeval.svg
12
+ .. | pypi-version | image :: https://badge.fury.io/py/simpleeval.svg
13
13
:target: https://badge.fury.io/py/simpleeval
14
14
:alt: PyPI Version
15
15
16
- .. image :: https://img.shields.io/badge/code%20style-black-000000.svg
17
- :target: https://github.com/psf/black
16
+ .. | python-versions | image :: https://img.shields.io/badge/python-3.9_%7C_3.10_%7C_3.11_%7C_3.12_%7C_3.13_%7C_PyPy3.9_%7C_PyPy3.10-blue
17
+ :alt: Static Badge
18
18
19
- .. image :: https://img.shields.io/badge/linting-pylint-yellowgreen
20
- :target: https://github.com/PyCQA/pylint
19
+ .. |pypi-monthly-downloads | image :: https://img.shields.io/pypi/dm/SimpleEval
20
+ :alt: PyPI - Downloads
21
+
22
+ .. |formatting-with-ruff | image :: https://img.shields.io/badge/-ruff-black?logo=lightning&logoColor=%2300ff00&link=https%3A%2F%2Fdocs.astral.sh%2Fruff%2F
23
+ :alt: Static Badge
24
+
25
+ |build-status | |code-coverage | |pypi-version | |python-versions | |pypi-monthly-downloads | |formatting-with-ruff |
21
26
22
27
23
28
A single file library for easily adding evaluatable expressions into
@@ -157,7 +162,7 @@ The ``^`` operator is often mistaken for a exponent operator, not the bitwise
157
162
operation that it is in python, so if you want ``3 ^ 2 `` to equal ``9 ``, you can
158
163
replace the operator like this:
159
164
160
- .. code-block :: python
165
+ .. code-block :: pycon
161
166
162
167
>>> import ast
163
168
>>> from simpleeval import safe_power
@@ -200,15 +205,15 @@ If Expressions
200
205
201
206
You can use python style ``if x then y else z `` type expressions:
202
207
203
- .. code-block :: python
208
+ .. code-block :: pycon
204
209
205
210
>>> simple_eval("'equal' if x == y else 'not equal'",
206
211
names={"x": 1, "y": 2})
207
212
'not equal'
208
213
209
214
which, of course, can be nested:
210
215
211
- .. code-block :: python
216
+ .. code-block :: pycon
212
217
213
218
>>> simple_eval("'a' if 1 == 2 else 'b' if 2 == 3 else 'c'")
214
219
'c'
@@ -219,15 +224,15 @@ Functions
219
224
220
225
You can define functions which you'd like the expresssions to have access to:
221
226
222
- .. code-block :: python
227
+ .. code-block :: pycon
223
228
224
229
>>> simple_eval("double(21)", functions={"double": lambda x:x*2})
225
230
42
226
231
227
232
You can define "real" functions to pass in rather than lambdas, of course too,
228
233
and even re-name them so that expressions can be shorter
229
234
230
- .. code-block :: python
235
+ .. code-block :: pycon
231
236
232
237
>>> def double(x):
233
238
return x * 2
@@ -246,13 +251,13 @@ are provided in the ``DEFAULT_FUNCTIONS`` dict:
246
251
+----------------+--------------------------------------------------+
247
252
| ``float(x) `` | Convert ``x `` to a ``float ``. |
248
253
+----------------+--------------------------------------------------+
249
- | ``str(x) `` | Convert ``x `` to a ``str `` (`` unicode `` in py2) |
254
+ | ``str(x) `` | Convert ``x `` to a ``str `` |
250
255
+----------------+--------------------------------------------------+
251
256
252
257
If you want to provide a list of functions, but want to keep these as well,
253
258
then you can do a normal python ``.copy() `` & ``.update ``:
254
259
255
- .. code-block :: python
260
+ .. code-block :: pycon
256
261
257
262
>>> my_functions = simpleeval.DEFAULT_FUNCTIONS.copy()
258
263
>>> my_functions.update(
@@ -267,15 +272,15 @@ Names
267
272
Sometimes it's useful to have variables available, which in python terminology
268
273
are called 'names'.
269
274
270
- .. code-block :: python
275
+ .. code-block :: pycon
271
276
272
277
>>> simple_eval("a + b", names={"a": 11, "b": 100})
273
278
111
274
279
275
280
You can also hand the handling of names over to a function, if you prefer:
276
281
277
282
278
- .. code-block :: python
283
+ .. code-block :: pycon
279
284
280
285
>>> def name_handler(node):
281
286
return ord(node.id[0].lower(a))-96
@@ -284,9 +289,34 @@ You can also hand the handling of names over to a function, if you prefer:
284
289
3
285
290
286
291
That was a bit of a silly example, but you could use this for pulling values
287
- from a database or file, say, or doing some kind of caching system.
292
+ from a database or file, looking up spreadsheet cells, say, or doing some kind of caching system.
288
293
289
- The two default names that are provided are ``True `` and ``False ``. So if you want to provide your own names, but want ``True `` and ``False `` to keep working, either provide them yourself, or ``.copy() `` and ``.update `` the ``DEFAULT_NAMES ``. (See functions example above).
294
+ In general, when it attempts to find a variable by name, if it cannot find one,
295
+ then it will look in the ``functions `` for a function of that name. If you want your name handler
296
+ function to return an "I can't find that name!", then it should raise a ``simpleeval.NameNotDefined ``
297
+ exception. Eg:
298
+
299
+ .. code-block :: pycon
300
+
301
+ >>> def name_handler(node):
302
+ ... if node.id[0] == 'a':
303
+ ... return 21
304
+ ... raise NameNotDefined(node.id[0], "Not found")
305
+ ...
306
+ ... simple_eval('a + a', names=name_handler, functions={"b": 100})
307
+
308
+ 42
309
+
310
+ >>> simple_eval('a + b', names=name_handler, functions={'b': 100})
311
+ 121
312
+
313
+ (Note: in that example, putting a number directly into the ``functions `` dict was done just to
314
+ show the fall-back to functions. Normally only put actual callables in there.)
315
+
316
+
317
+ The two default names that are provided are ``True `` and ``False ``. So if you want to provide
318
+ your own names, but want ``True `` and ``False `` to keep working, either provide them yourself,
319
+ or ``.copy() `` and ``.update `` the ``DEFAULT_NAMES ``. (See functions example above).
290
320
291
321
Creating an Evaluator Class
292
322
---------------------------
@@ -296,7 +326,7 @@ evaluations, you can create a SimpleEval object, and pass it expressions each
296
326
time (which should be a bit quicker, and certainly more convenient for some use
297
327
cases):
298
328
299
- .. code-block :: python
329
+ .. code-block :: pycon
300
330
301
331
>>> s = SimpleEval()
302
332
@@ -375,7 +405,7 @@ comprehensions.
375
405
Since the primary intention of this library is short expressions - an extra 'sweetener' is
376
406
enabled by default. You can access a dict (or similar's) keys using the .attr syntax:
377
407
378
- .. code-block :: python
408
+ .. code-block :: pycon
379
409
380
410
>>> simple_eval("foo.bar", names={"foo": {"bar": 42}})
381
411
42
@@ -405,8 +435,7 @@ and then use ``EvalNoMethods`` instead of the ``SimpleEval`` class.
405
435
Other...
406
436
--------
407
437
408
- The library supports python 3 - but should be mostly compatible (and tested before 0.9.11)
409
- with python 2.7 as well.
438
+ The library supports Python 3.9 and higher.
410
439
411
440
Object attributes that start with ``_ `` or ``func_ `` are disallowed by default.
412
441
If you really need that (BE CAREFUL!), then modify the module global
0 commit comments