Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RuntimeError: maximum recursion depth exceeded #1

Open
klwilson227 opened this issue Dec 9, 2018 · 2 comments
Open

RuntimeError: maximum recursion depth exceeded #1

klwilson227 opened this issue Dec 9, 2018 · 2 comments

Comments

@klwilson227
Copy link

  • Mongo Filter Evaluator version: 1.0
  • Python version: 2.7.4
  • Operating System: Centos7

Description

d = {... any data will do ...}
f = {"$and": [{any first filter}, {}]
DataConditionEvaluator(f,d).evaluate()

Leads to stack overrun...recursive calls.

Describe what you were trying to get done.

In the automated building for filter conditions it is common to use a {} empty filter when one part of the generation does not apply vs. simply removing the filter from the $and condition itself. This way one can see that a filter was returned for that part of the and however, it was a empty filter which should pass. Thus the $and logic remains syntactically correct. For example, a user supplied filter on the left and a entitlement filter on the right. If the user is entitled to see everything then syntactically a {} may be used as a replacement.

Tell us what happened, what went wrong, and what you expected to happen.

Exception RuntimeError: maximum recursion depth exceeded

What I Did

Paste the command(s) you ran and the output.
If there was a crash, please include the traceback here.

def test_filter_stream_and2e(self):
f = {'$and': [{'blah': 0.3}, {}]}
d = {u'blah': 0.3}
DataConditionEvaluator(f, d).evaluate()

File "/usr/lib/python2.7/site-packages/mongo_filter_evaluator/base.py", line 52, in c_and
for condition in body
File "/usr/lib/python2.7/site-packages/mongo_filter_evaluator/base.py", line 52, in
for condition in body
File "/usr/lib/python2.7/site-packages/mongo_filter_evaluator/base.py", line 27, in evaluate
return self.evaluate_logic('$and', condition)
File "/usr/lib/python2.7/site-packages/mongo_filter_evaluator/evaluator.py", line 98, in evaluate_logic
return getattr(self, 'c_%s' % keyword[1:])(body)
File "/usr/lib/python2.7/site-packages/mongo_filter_evaluator/base.py", line 47, in c_and
for (condition_keyword, condition_body) in body.items()
File "/usr/lib/python2.7/site-packages/mongo_filter_evaluator/base.py", line 47, in
for (condition_keyword, condition_body) in body.items()
File "/usr/lib/python2.7/site-packages/mongo_filter_evaluator/base.py", line 36, in evaluate_condition
for op_keyword, op_body in body.items()
File "/usr/lib/python2.7/site-packages/mongo_filter_evaluator/base.py", line 36, in
for op_keyword, op_body in body.items()
File "/usr/lib/python2.7/site-packages/mongo_filter_evaluator/evaluator.py", line 103, in evaluate_function
value=body,
File "/usr/lib/python2.7/site-packages/mongo_filter_evaluator/evaluator.py", line 13, in wrap_method
return (field in self.data) and f(self, field, value)
RuntimeError: maximum recursion depth exceeded

@klwilson227
Copy link
Author

OK, I found the bug. If evaluate is called, with a empty condition, the line of evaluate:
condition = condition if condition else self.condition

Will incorrectly set the leaf condition (aka empty condition) back to the original condition full condition.
I don't believe this is what was desired. Instead we should be checking if the condition was explicitly None. And only set the condition to the self.condition in that case of lazy evaluate call to get the right conditiontion on entry. It was not intended to replace a {} with the original condition in the leaf since this also evaluates to False, we get the bug.

I added a handler also for the empty dict to ensure that it returns quickly.

def evaluate(self, condition=None):
# This incorrectly resets a empty dict to the full dict.
# condition = condition if condition else self.condition
# Instead
# we only want to do this when the condition was explicitly not passed in.
if condition is None: condition = self.condition

    # If this is a empty condition, then we will simply return true.
    if isinstance(condition, dict) and not condition: return True
    return self.evaluate_logic('$and', condition)

@klwilson227
Copy link
Author

Pull Request: #2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant