On 20/05/2013 10:07, Frank Millman wrote:
On 20/05/2013 09:55, Chris Angelico wrote:
Is it a requirement that they be able to key in a constraint as a
single string? We have a similar situation in one of the systems at
work, so we divided the input into three(ish) parts: pick a field,
pick an operator (legal operators vary according to field type -
integers can't be compared against regular expressions, timestamps can
use >= and < only), then enter the other operand. Sure, that cuts out
a few possibilities, but you get 99.9%+ of all usage and it's easy to
sanitize.

ChrisA


It is not a requirement, no. I just thought it would be a convenient
short-cut.

I had in mind something similar to your scheme above, so I guess I will
have to bite the bullet and implement it.


Can anyone see anything wrong with the following approach. I have not definitely decided to do it this way, but I have been experimenting and it seems to work.

I store the boolean test as a json'd list of 6-part tuples. Each element of the tuple is a string, defined as follows -

0 - for the first entry in the list, the word 'check' (a placeholder - it is discarded at evaluation time), for any subsequent entries the word 'and' or 'or'.

1 - left bracket - either '(' or ''.

2 - column name to check - it will be validated on entry.

3 - operator - must be one of '=', '!=', '<', '>', '<=', '>=', 'in', 'is', 'is not'. At evaluation time, '=' is changed to '=='.

4 - value to compare - at evaluation time I call str(literal_eval(value)) to ensure that it is safe.

5 - right bracket - either ')' or ''.

At evaluation time I loop through the list, construct the boolean test as a string, and call eval() on it.

Here are some examples -

check = []
check.append(('check', '', 'name', 'in', "('abc', 'xyz')", ''))

check = []
check.append(('check', '', 'value', '>=', '0', ''))

check = []
check.append(('check', '(', 'descr', 'is not', 'None', ''))
check.append(('and', '', 'alt', 'is', 'None', ')'))
check.append(('or', '(', 'descr', 'is', 'None', ''))
check.append(('and', '', 'alt', 'is not', 'None', ')'))

I don't plan to check the logic - I will just display the exception if it does not evaluate.

It seems safe to me. Can anyone see a problem with it?

Frank


--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to