Skip to content

Commit af1a39f

Browse files
committed
Makes operator checking deterministic in Query.filter.
The order of dictionary keys is not guaranteed between runs of code so `expression`s ending in '>=' or '<=' were sometimes matching for '='.
1 parent b6d3e74 commit af1a39f

File tree

1 file changed

+13
-9
lines changed

1 file changed

+13
-9
lines changed

gcloud/datastore/query.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,15 @@ class Query(object):
4545
:param dataset: The namespace to which to restrict results.
4646
"""
4747

48-
OPERATORS = {
49-
'<': datastore_pb.PropertyFilter.LESS_THAN,
50-
'<=': datastore_pb.PropertyFilter.LESS_THAN_OR_EQUAL,
51-
'>': datastore_pb.PropertyFilter.GREATER_THAN,
52-
'>=': datastore_pb.PropertyFilter.GREATER_THAN_OR_EQUAL,
53-
'=': datastore_pb.PropertyFilter.EQUAL,
54-
}
48+
# NOTE: Order is very important here since operators that end with
49+
# '<=' and '>=' also end with '='.
50+
OPERATORS = (
51+
('<=', datastore_pb.PropertyFilter.LESS_THAN_OR_EQUAL),
52+
('>=', datastore_pb.PropertyFilter.GREATER_THAN_OR_EQUAL),
53+
('<', datastore_pb.PropertyFilter.LESS_THAN),
54+
('>', datastore_pb.PropertyFilter.GREATER_THAN),
55+
('=', datastore_pb.PropertyFilter.EQUAL),
56+
)
5557
"""Mapping of operator strings and their protobuf equivalents."""
5658

5759
def __init__(self, kind=None, dataset=None, namespace=None):
@@ -132,10 +134,12 @@ def filter(self, expression, value):
132134
property_name, operator = None, None
133135
expression = expression.strip()
134136

135-
for operator_string in self.OPERATORS:
137+
for operator_string, pb_op_enum in self.OPERATORS:
136138
if expression.endswith(operator_string):
137-
operator = self.OPERATORS[operator_string]
139+
operator = pb_op_enum
138140
property_name = expression[0:-len(operator_string)].strip()
141+
# After one match, we move on since >= and <= conflict with =.
142+
break
139143

140144
if not operator or not property_name:
141145
raise ValueError('Invalid expression: "%s"' % expression)

0 commit comments

Comments
 (0)