danthedeckie / simpleeval Goto Github PK
View Code? Open in Web Editor NEWSimple Safe Sandboxed Extensible Expression Evaluator for Python
License: Other
Simple Safe Sandboxed Extensible Expression Evaluator for Python
License: Other
I ran into this crash when investigating safeeval
's resiliency against lambda-based attacks.
Python 3.6.5 (default, Apr 3 2018, 21:02:01)
[GCC 4.2.1 Compatible Android Clang 5.0.300080 ] on linux
I'm using the Android app Termux, so the environment is a bit unusual, but this doesn't look like a platform-specific crash. Maybe this is caused by some change in ast
on Python 3.6?
>>> import simpleeval
>>> s = simpleeval.SimpleEval()
>>> s.eval('(lambda x: x+1)(3)')
Traceback (most recent call last):
...
simpleeval.FeatureNotAvailable: Sorry, Lambda is not available in this evaluator
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<python path>/site-packages/simpleeval.py", line 283, in eval
return self._eval(ast.parse(expr.strip()).body[0].value)
File "<python path>/site-packages/simpleeval.py", line 294, in _eval
return handler(node)
File "<python path>/site-packages/simpleeval.py", line 353, in _eval_call
func = self.functions[node.func.id]
AttributeError: 'Lambda' object has no attribute 'id'
s.eval('lambda x: x')
correctly raises FeatureNotAvailable
, only a lambda application causes this problem.
The file test_simpleeval.py is not in the package on PyPI.
It will be good to have it to test if the installation is correct.
With python3.4 no errors (s. #5), but when building for Debian wheezy, which only has python3.2 the following error occurs:
I: pybuild base:170: python3.2 setup.py test
running test
running build_py
running egg_info
creating /tmp/buildd/simpleeval-0.8.2/.pybuild/pythonX.Y_3.2/build/simpleeval.egg-info
writing /tmp/buildd/simpleeval-0.8.2/.pybuild/pythonX.Y_3.2/build/simpleeval.egg-info/PKG-INFO
writing top-level names to /tmp/buildd/simpleeval-0.8.2/.pybuild/pythonX.Y_3.2/build/simpleeval.egg-info/top_level.txt
writing dependency_links to /tmp/buildd/simpleeval-0.8.2/.pybuild/pythonX.Y_3.2/build/simpleeval.egg-info/dependency_links.txt
writing manifest file '/tmp/buildd/simpleeval-0.8.2/.pybuild/pythonX.Y_3.2/build/simpleeval.egg-info/SOURCES.txt'
reading manifest file '/tmp/buildd/simpleeval-0.8.2/.pybuild/pythonX.Y_3.2/build/simpleeval.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file '/tmp/buildd/simpleeval-0.8.2/.pybuild/pythonX.Y_3.2/build/simpleeval.egg-info/SOURCES.txt'
running build_ext
Traceback (most recent call last):
File "setup.py", line 22, in <module>
'Programming Language :: Python :: 3',
File "/usr/lib/python3.2/distutils/core.py", line 148, in setup
dist.run_commands()
File "/usr/lib/python3.2/distutils/dist.py", line 917, in run_commands
self.run_command(cmd)
File "/usr/lib/python3.2/distutils/dist.py", line 936, in run_command
cmd_obj.run()
File "/usr/lib/python3/dist-packages/setuptools/command/test.py", line 137, in run
self.with_project_on_sys_path(self.run_tests)
File "/usr/lib/python3/dist-packages/setuptools/command/test.py", line 117, in with_project_on_sys_path
func()
File "/usr/lib/python3/dist-packages/setuptools/command/test.py", line 146, in run_tests
testLoader = loader_class()
File "/usr/lib/python3.2/unittest/main.py", line 123, in __init__
self.parseArgs(argv)
File "/usr/lib/python3.2/unittest/main.py", line 191, in parseArgs
self.createTests()
File "/usr/lib/python3.2/unittest/main.py", line 198, in createTests
self.module)
File "/usr/lib/python3.2/unittest/loader.py", line 137, in loadTestsFromNames
suites = [self.loadTestsFromName(name, module) for name in names]
File "/usr/lib/python3.2/unittest/loader.py", line 137, in <listcomp>
suites = [self.loadTestsFromName(name, module) for name in names]
File "/usr/lib/python3.2/unittest/loader.py", line 96, in loadTestsFromName
module = __import__('.'.join(parts_copy))
File "/tmp/buildd/simpleeval-0.8.2/test_simpleeval.py", line 87
self.t('"Test Stuff!" + str(11)', u"Test Stuff!11")
^
SyntaxError: invalid syntax
Hi, first of all I want to thank you for the package. It comes very handy to my project. I have forked it, so I'm open to contribute.
I have some questions, what happens if I do:
import simpleeval
import math
simpleeval.DEFAULT_FUNCTIONS["sqrt"] = math.sqrt
print simpleeval.simple_eval("sqrt(25)")
>>> 5
It works, but, is that all right? Is it the supposed way I should do it? is there any risk?
I need it to support python3.8
Hi,
could you please ship licence file along with tarbal as usual in opensource projects?
Thanks for considering
These seem like useful omissions!
Why not allow functions such as range()
?
Hi,
I've noticed that the names
dictionary provided to simple_eval
was actually modified here:
It is a difficult side-effect to detect, so I would like to know if it is the expected behavior (meaning one should always copy actual data passed to names) or a bug to fix.
so you could do:
>>> s = SimpleEval()
>>> s('22 + 20')
42
which would be rather sweet.
Documentation on your simpleeval package (on github) has an explanation on how add ^
operator, but lacks an example of how operators
paramater work
is through a dict
with lambda
, just like functions
paramater work?
already tested the following and it was the only way I could make it work
s = SimpleEval()
s.operators[ast.BitOr] = op.or_
the problem with this is that Or
can not be added as or
Also custom functions that are not available in ast
package are trickier (could not make it work)
for example lets take operator juggler
:
1 juggler 7
returns 5
, since juggler
takes 1 from 7, and since the result is higher that 1, takes another 1 from the result (6) ending in 5
if the example does not make much sense is because I'm forcing it to be a custom operator
This triggers the fact that when any operator is added DEFAULT OPERATORS are ignored:
if anything is added through parameter operator=
a conditional on the constructor (__init__
) makes it imposible to append new operators to the default operators
Is this a feature? an optimization feature? maybe I am not using the package correctly
I thought the documentation could use something like:
adding operator
Or
would require the following:
simple_eval("True Or False", operators={"Or": lambda x, y: x | y})
returns
True
simple_eval("1 juggler 7", operators={"juggler": lambda x, y:
y - 2 *x if (y - x) > x else y - x })
returns
5
this becomes extremely handy when using complex operators for time series when comparisons are time wise (maybe sent in tuple form)
simple_eval("(t0, t1) crosses_above (s0, s1)",
operators={"crosses_above": lambda t, s: t[1] > s[1] if t[0] < s[0] else False})
returns True or False depending on the case
when:t[0, 1] = 2, 4
ands[0, 1] = 2.5, 3.5
;crosses_above
returnsTrue
when:t[0, 1] = 2, 3
ands[0, 1] = 2.5, 3.5
;crosses_above
returnsFalse
When this issue is clear to me I could open a fork and send the PR with the respective changes into the documentation
Also I am impressed at your work, wish you a wonderful day sir
Is there any plan on adding a method processing ast.Lamba
?
According to the source code, the FunctionNotDefined
exception has an attribute func_name
, and has had it since the initial commit. However, when using pip
to install the package, the same section looks like this:
class FunctionNotDefined(InvalidExpression):
""" sorry! That function isn't defined! """
def __init__(self, func_name, expression):
self.message = "Function '{0}' not defined," \
" for expression '{1}'.".format(func_name, expression)
self.__name__ = func_name
self.expression = expression
so the attribute is called __name__
.
The weird thing is, that the tar on PyPI DOES seem to contain the correct code (no diff with the github version.
What's going on here?
To reproduce, I did:
docker run --rm -it python:3.7.0-stretch bash
pip install simpleeval
grep -A6 'class FunctionNotDefined' /usr/local/lib/python3.7/site-packages/simpleeval.py
Such code is not support by EvalWithCompoundTypes
{i:i for i in range(3)}
Basically, it is should be easy to support such functionality with something like that Reskov@695bb68
I can do more tests and prepare PR if you agree in general
Expressions like not True
fail when they should work.
TestTryingToBreakOut is currently failing with
I: pybuild base:170: python2.7 setup.py test
running test
running egg_info
creating simpleeval.egg-info
writing simpleeval.egg-info/PKG-INFO
writing top-level names to simpleeval.egg-info/top_level.txt
writing dependency_links to simpleeval.egg-info/dependency_links.txt
writing manifest file 'simpleeval.egg-info/SOURCES.txt'
reading manifest file 'simpleeval.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'simpleeval.egg-info/SOURCES.txt'
running build_ext
test_bools_and_or (test_simpleeval.TestBasic) ... ok
test_comparisons (test_simpleeval.TestBasic) ... ok
test_default_conversions (test_simpleeval.TestBasic)
conversion between types ... ok
test_if_else (test_simpleeval.TestBasic)
x if y else z ... ok
test_maths_with_floats (test_simpleeval.TestBasic) ... ok
test_maths_with_ints (test_simpleeval.TestBasic)
simple maths expressions ... ok
test_mixed_comparisons (test_simpleeval.TestBasic) ... ok
test_load_file (test_simpleeval.TestFunctions)
add in a function which loads data from an external file. ... ok
test_randoms (test_simpleeval.TestFunctions)
test the rand() and randint() functions ... ok
test_dict (test_simpleeval.TestNames)
using a normal dict for names lookup ... ok
test_from_doc (test_simpleeval.TestNames)
the 'name first letter as value' example from the docs ... ok
test_func (test_simpleeval.TestNames)
using a function for 'names lookup' ... ok
test_none (test_simpleeval.TestNames)
what to do when names isn't defined, or is 'none' ... ok
test_import (test_simpleeval.TestTryingToBreakOut)
usual suspect. import ... ok
test_long_running (test_simpleeval.TestTryingToBreakOut)
exponent operations can take a long time. ... ok
test_python_stuff (test_simpleeval.TestTryingToBreakOut)
other various pythony things. ... ok
test_string_length (test_simpleeval.TestTryingToBreakOut) ... ERROR
test_basic_run (test_simpleeval.Test_simple_eval) ... ok
test_default_functions (test_simpleeval.Test_simple_eval) ... ok
======================================================================
ERROR: test_string_length (test_simpleeval.TestTryingToBreakOut)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/buildd/simpleeval-0.8.2/test_simpleeval.py", line 199, in test_string_length
self.t("'" + (50000 * "stuff") + "'", 0)
File "/tmp/buildd/simpleeval-0.8.2/test_simpleeval.py", line 24, in t
return self.assertEqual(self.s.eval(expr), shouldbe)
File "/tmp/buildd/simpleeval-0.8.2/simpleeval.py", line 209, in eval
return self._eval(ast.parse(expr).body[0].value)
File "/tmp/buildd/simpleeval-0.8.2/simpleeval.py", line 223, in _eval
node.id, len(node.s), MAX_STRING_LENGTH))
AttributeError: 'Str' object has no attribute 'id'
----------------------------------------------------------------------
Ran 19 tests in 0.009s
FAILED (errors=1)
Hi, is it possible to evaluate "Pi" or "e" in an expression ?
If not, would you have any idea on how to implement this ?
I'd like to have an operator like "?(number)". How would I go about doing this, and if I can't, is it planned and/or are there workarounds?
You might not understand why, but it's so that I can do things like FIBONACCI(2) would get the first 2 fibonacci numbers. it's like functions but as expressions.
I just ran:
pip install simpleeval
It was successfully installed (and works locally), but there was a warning from line 55:
Can't parse docstring in build/lib/simpleeval.py line 55: ParseError: bad input: type=0, value='', context=('', (56, 0))
is
and is not
should be part of the default operators.
How do I install with pip? (I've got a bad feeling I'm missing something really obvious)
simpleeval 0.9.10
So I just remembered that any valid assignment target can be used in a list comprehension! i.e. something like [... for foo[0] in ...]
is valid syntax.
>>> [x for x in ([None],) for x[0] in (15,)]
[[15]]
>>> EvalWithCompoundTypes('[x for x in ([None],) for x[0] in (15,)]')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "LIBPATH/simpleeval.py", line 539, in eval
return super(EvalWithCompoundTypes, self).eval(expr)
File "LIBPATH/simpleeval.py", line 332, in eval
return self._eval(ast.parse(expr.strip()).body[0].value)
File "LIBPATH/simpleeval.py", line 343, in _eval
return handler(node)
File "LIBPATH/simpleeval.py", line 597, in _eval_comprehension
do_generator()
File "LIBPATH/simpleeval.py", line 592, in do_generator
do_generator(gi+1)
File "LIBPATH/simpleeval.py", line 589, in do_generator
recurse_targets(g.target, i)
File "LIBPATH/simpleeval.py", line 579, in recurse_targets
for t, v in zip(target.elts, value):
AttributeError: 'Subscript' object has no attribute 'elts'
Hello,
congratulations on this fantastic library.
It has allowed me to develop a generic function with the following signature:
def calc_model (formula, ** kargs)
The native function eval (formula, kargs)
was giving me an error when the formula contained functions like math.log10 (x)
even after importing it.
Embedding the import just before the formula was not the solution either:
if ('math' in formula):
formula = 'import math; '+ formula
Finally, I had the solution with simpleeval defining a specific lambda function:
log10_lambda = {"log10": lambda x: math.log10(x)}
result = simple_eval (formula, names = kargs, functions = log10_lambda)
How can I increase or even completely disable the MAX_POWER limit value without editing the library source code?
I have some formulas that need it
Thanks in advance.
Perhaps I am misunderstanding how the expression evaluator should work, but consider the following:
formula = "0 <= 10 <= 5"
simple_eval(formula)
True
While 0 <= 10 should evaluate to True, 10 <= 5 should not. Perhaps the evaluation is being short-circuited? Is this intentional?
I also tested this with Python's built in eval function:
formula = "0 <= 10 <= 5"
eval(formula)
False
Hi! maybe this can help:
def safe_lambda(x, y):
return lambda z: simple_eval(y, names={x:z})
list(filter(safe_lambda('x', 'x > 2'), [1, 2, 3, 4, 5, 6]))
When you try to run the testsuite of simpleeval on python 3.8 you get following error on most tests:
[ 12s] ___________________ TestShortCircuiting.test_shortcircuit_if ___________________
[ 12s]
[ 12s] self = <simpleeval.SimpleEval object at 0xf66c0208>
[ 12s] node = <_ast.Constant object at 0xf66c02f8>
[ 12s]
[ 12s] def _eval(self, node):
[ 12s] """ The internal evaluator used on each node in the parsed tree. """
[ 12s]
[ 12s] try:
[ 12s] > handler = self.nodes[type(node)]
[ 12s] E KeyError: <class '_ast.Constant'>
[ 12s]
[ 12s] simpleeval.py:315: KeyError
[ 12s]
[ 12s] During handling of the above exception, another exception occurred:
[ 12s]
[ 12s] self = <test_simpleeval.TestShortCircuiting testMethod=test_shortcircuit_if>
[ 12s]
[ 12s] def test_shortcircuit_if(self):
[ 12s] x = []
[ 12s] def foo(y):
[ 12s] x.append(y)
[ 12s] return y
[ 12s] self.s.functions = {'foo': foo}
[ 12s] > self.t('foo(1) if foo(2) else foo(3)', 1)
[ 12s]
[ 12s] test_simpleeval.py:1001:
[ 12s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 12s] test_simpleeval.py:31: in t
[ 12s] return self.assertEqual(self.s.eval(expr), shouldbe)
[ 12s] simpleeval.py:309: in eval
[ 12s] return self._eval(ast.parse(expr.strip()).body[0].value)
[ 12s] simpleeval.py:320: in _eval
[ 12s] return handler(node)
[ 12s] simpleeval.py:372: in _eval_ifexp
[ 12s] return self._eval(node.body) if self._eval(node.test) \
[ 12s] simpleeval.py:320: in _eval
[ 12s] return handler(node)
[ 12s] simpleeval.py:386: in _eval_call
[ 12s] return func(
[ 12s] simpleeval.py:387: in <genexpr>
[ 12s] *(self._eval(a) for a in node.args),
[ 12s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 12s]
[ 12s] self = <simpleeval.SimpleEval object at 0xf66c0208>
[ 12s] node = <_ast.Constant object at 0xf66c02f8>
[ 12s]
[ 12s] def _eval(self, node):
[ 12s] """ The internal evaluator used on each node in the parsed tree. """
[ 12s]
[ 12s] try:
[ 12s] handler = self.nodes[type(node)]
[ 12s] except KeyError:
[ 12s] > raise FeatureNotAvailable("Sorry, {0} is not available in this "
[ 12s] "evaluator".format(type(node).__name__))
[ 12s] E simpleeval.FeatureNotAvailable: Sorry, Constant is not available in this evaluator
[ 12s]
[ 12s] simpleeval.py:317: FeatureNotAvailable
[ 12s] ======================== 64 failed, 16 passed in 4.37s =========================
The following statement successfully executes.
simpleeval.simple_eval("a = 2")
And returns 2.
I suggest that assignment operator is entirely disallowed as input to simple eval.
Because "a == 2" can be easily mistyped as "a = 2" and existence of variable "a" is not even checked in evaluation of this input.
If the user (source of untrusted code) can get access to a non-builtin function, such as a method defined on a non-builtin class, they can access the functions func_globals
or __globals__
property and see everything defined in that function's module. This includes other imported modules and often leads to access to sys
, and by extension, sys.modules
. This could allow an attacker to find sensitive data (usernames, passwords, PII) by crawling through the list of modules. Even if the sensitive information is not defined at top level, inspection of function objects will reveal any constants or default arguments used anywhere in the running system.
At a minimum, attribute lookup for attributes beginning with _
should be denied (plus the special case in python2 to deny func_*). Ideally, attribute lookup should have a configurable max-depth, or a whitelist of allowed types and classes.
Hi, in this issue you propose a solution for using simpleeval with Decimal type. That appears to no longer be working? I'm not quite sure why.
import decimal
import simpleeval
class DecimalEval(simpleeval.SimpleEval):
@staticmethod
def _eval_num(node):
return decimal.Decimal(node.n)
decimal.getcontext().prec = 1
print(DecimalEval().eval('0.1+0.2'))
print(type(DecimalEval().eval('0.1+0.2')))
This outputs
0.30000000000000004
<class 'float'>
Can you give some insight please?
For example
simple_eval(b'123456789')
or
simple_eval(bytes(string, 'ascii'))
When giving simpleeval an empty string it raises this error:
Traceback (most recent call last):
Traceback (most recent call last):
File "simpleeval.py", line 613, in simple_eval
return s.eval(expr)
File "simpleeval.py", line 334, in eval
return self._eval(parsed.body[0].value)
IndexError: list index out of range
I propose to either throw an appropriate error or maybe return something. Wether that'd be an empty string or None
is too philosophical for me but maybe there's an PIP on this? Anyways, something like this should suffice:
parsed = ast.parse(expr.strip())
if len(parsed.body) > 0:
# and evaluate if not empty:
return self._eval(parsed.body[0].value)
else:
return None
simple_eval("from", names={"from": 1})
raises SyntaxError: invalid syntax
I suppose most (if not all) keywords and names could be identified based on their position in the expression.
Can support by added for the implied multiplication, for example:
"2(3+4)"
If not, how can a random equation be edited at runtime to insert the '*' ?
Hi! This is what the PyPI page looks like to me (Chrome/Android):
IME with markdown, adding a long_description_content_type='<your_format>'
to your setup(...)
should make the page render correctly. (I'm not sure if it's supposed to be 'rst'
or 'reStructuredText'
though.) You might have to update your setuptools, some older versions don't recognize that parameter.
Using simple_eval
method expression like True\nFalse
is evaluated to True, False\nTrue
to False.
It looks like only the first statement is taken from AST for evaluation.
Line 328 in b47858d
I suggest that an exception must be raised in case where there are multiple statements to be sure that passed expression is evaluated correctly.
I'm having an issue when creating a python binary using Pyinstaller. It does not include the site
module , which is where help
comes from. This results in a NameError when importing simpleeval. As including site
seems like it would cause Pyinstaller significant issues it might be wise to check for it's existence before adding it to your excluded keywords list in simpleeval.
The relevant code is DISALLOW_FUNCTIONS = {type, isinstance, eval, getattr, setattr, help, repr, compile, open}
Here's a pyinstaller issue I was able to find that is related.
If you feel this is a pyinstaller issue I can recreate this issue over there.
Hi,
I'm trying to use simpleeval to evaluate expressions as XML attributes.
Since XML syntax uses "<" and ">" I cannot do this:
<Tag expr="3 > 1"/>
So I am trying to use something like this:
<Tag expr="3 GT 1"/>
Can this be done?
Hello,
First I want to thank you for this project,
I was trying to evaluate some class method calls using the method chaining syntax, but i got a weird result:
my code:
from __future__ import print_function
import simpleeval
class A(object):
def __init__(self):
self.a = "0"
def add(self, b):
self.a += "-add" + str(b)
return self
def sub(self, b):
self.a += "-sub" + str(b)
return self
def __str__(self):
return str(self.a)
x = A()
print(simpleeval.simple_eval("x.add(1).sub(2).sub(3)", names={"x": x}))
x = A()
print(x.add(1).sub(2).sub(3)) # expected output
the output:
0-add1-add1-sub2-add1-add1-sub2-sub3
0-add1-sub2-sub3
The first line is the output from simpleeval.
I have a project that I wanted to build to create a release. I've tried with py2exe and PyInstaller.
However, always after the building, it throws an error that says:
File "simpleeval.py", line 116, in <module>
NameError: name 'help' is not defined
[39588] Failed to execute script app
I was able to solve this by adding:
def help():
pass
right above the definition of DISALLOW_FUNCTIONS
, that was at the line 116.
I only did it because I've found another person with the same problem, that described this solution in this site.
It would be possible to add this in a release? Because the program works perfectly just with this little modification. But it is annoying to add this always when I want to build the project.
I don't know if there's another person that faced the same problem and has a better way to solve this. If so, I would like to know.
Here's a simple reproducer of the problem:
#!/usr/bin/env python3
from simpleeval import EvalWithCompoundTypes
s = EvalWithCompoundTypes(functions={"map": map, "str": str})
print(s.eval("list(map(str, [-1, 0, 1]))"))
The fix is to have SimpleEval._eval_name()
also look in self.functions
when it can't find node.is in self.names
. I can submit a pull request once my pending one is closed.
Example code:
import ast
from simpleeval import EvalWithCompoundTypes
e = EvalWithCompoundTypes()
try:
print(e.eval('[x if x == "2" else y for x in "123"]'))
except Exception as exc:
print(exc)
print(e.nodes[ast.Name])
print(e.eval('x'))
Result:
'y' is not defined for expression '[x if x == "2" else y for x in "123"]'
<function EvalWithCompoundTypes._eval_comprehension.<locals>.eval_names_extra at 0x1098f91e0>
1
Expected Result:
The second print statement should print something like <bound method SimpleEval._eval_name of <simpleeval.EvalWithCompoundTypes object at 0x10bf2f860>>
while the second evaluation should raise a NameNotDefined
exception.
Solution:
The _eval_comprehension
method changes the evaller for the ast.Name
node, but does not reset it in case of an exception. This can be easily solved by wrapping the call to do_generator
into a try...finally
construct.
Is it possible to get the list of names used in an expression? I'm looking for something like variables()
from https://github.com/Axiacore/py-expression-eval
I've seen https://stackoverflow.com/questions/33554036/how-to-get-all-variable-and-method-names-used-in-script but I have a feeling I need these names defined ahead of time as per the example.
Any type of guidance would be helpful!
I was surprised to find that None or None
evaluates as False
rather than None
as I was expecting. Looks like due to the implementation of _eval_boolop
at https://github.com/danthedeckie/simpleeval/blob/master/simpleeval.py#L363
Consider the following:
out = True
position = 3
expr = '(out and position <=6 and -10) or (out and position > 6 and -5) or (not out and 15)'
simple_eval(expr, names={'out': True, 'position': 3} )
gives the result
True
This is wrong. Using
eval(expr)
we get the correct result:
-10
Is this a bug? Or intentional?
This option has dropped support: pypa/setuptools#2769
Failing builds downstream, such as in our project: https://gitlab.com/meltano/sdk/-/issues/213
Pending one-liner PR here: #91
Tests fail with the following error when running on Python 3.8:
simpleeval.FeatureNotAvailable: Sorry, Constant is not available in this evaluator
I'm using simpleeval for evaluating template expressions, e.g.
{{ foo.bar }}
Because the engine (https://github.com/iivvoo/ate if anyone's interested ;) aims to be user (programmer) friendly it ignores leading/trailing whitespaces and passes them verbatim to simpleeval which sometimes results in an IndentationError
In [1]: from simpleeval import simple_eval
In [2]: simple_eval(" True")
File "<unknown>", line 1
True
^
IndentationError: unexpected indent
This is quite simple to work around but it makes me wonder if there's any need at all for simpleeval to be so strict about whitespace - is any form of indentation actually supported?
Hi,
I'm trying to get the safety of simpleeval to work with sqlalchemy's core query:
Something like:
tbl = Table('mytable', meta)
names = tbl.c._data
myexpr = 'mycol > 5'
se = simpleeval.EvalWithCompoundTypes(names=names)
safe_filter = se.eval(myexpr) # <-- I get an error
results = session.query(tbl).filter(safe_filter)
I'm getting this error on eval():
TypeError: Boolean value of this clause is not defined
For the record, this does work:
tbl = Table('mytable', meta)
names = tbl.c._data
myexpr = 'mycol > 5'
unsafe_filter = eval(myexpr, names)
results = session.query(tbl).filter(unsafe_filter)
It looks like eval() is returning: sqlalchemy.sql.elements.BinaryExpression, which breaks simpleeval...
Any hope of getting this to work? Am I doing something wrong?
Thanks!
Would be possible to support the decimal
module, such that e.g. simple_eval('0.1+0.2')
gives 0.3
instead of 0.30000000000000004
?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.