Certain packages like SQLAlchemy and RethinkDB (the latter I happen to be using) require predicate expressions to be passed into functions as arguments. For example, RethinkDB's filter
method (https://rethinkdb.com/api/python/filter/) requires the first parameter to be a ReQL syntax expression and not a string.
However, I would like to build this expression programmatically based on a REST API query string I receive. For example, I might receive a query string such as:
/?filter=name%3D%3DNick&filter=score%3D%3DA,score%3D%3DB
In this case, I would like to convert this query string into the predicate:
r.row['name'] == 'Nick' & (r.row['score'] == 'A' | r.row['score'] == 'B')
I can generate this predicate as a string using a recursive function I wrote:
def process_filters(data):
if isinstance(data, list):
return ' & '.join([process_filters(val) for val in data])
elif ',' in data:
or_filters = data.split(',')
return '(' + \
' | '.join(['(r.row["' + val.split('==', 1)[0] + '"] == ' + val.split('==', 1)[1] + ')' for val in or_filters]) + \
')'
else:
parts = data.split('==', 1)
return '(r.row["' + parts[0] + '"] == ' + parts[1] + ')'
This function gives me the desired predicate as a string. However, RethinkDB will not process this argument as a string.
r.filter(process_filters(query_string))
The above command will not work properly because r.filter
requires an expression, e.g.:
r.filter(r.row['name'] == 'Nick')
Not: r.filter("r.row['name'] == 'Nick'")
How do I convert the argument to an expression while still maintaining the flexibility to build the predicate programmatically from a string as I have?
Edit: eval
actually does work, but as a commenter pointed out, this is generally frowned upon. I do believe in this particular case it may be the "best" solution, but I look forward to more ideas…