Skip to content

Commit 9eb120d

Browse files
committed
Merge branch 'float_fix' into develop
PR #281 * float_fix: Add additional compliance tests for verifying float/boolean correctness Add support for proper bool/float comparison
2 parents 0cb6590 + 48a0295 commit 9eb120d

File tree

3 files changed

+98
-19
lines changed

3 files changed

+98
-19
lines changed

jmespath/visitor.py

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66

77

88
def _equals(x, y):
9-
if _is_special_integer_case(x, y):
9+
if _is_special_number_case(x, y):
1010
return False
1111
else:
1212
return x == y
1313

1414

15-
def _is_special_integer_case(x, y):
15+
def _is_special_number_case(x, y):
1616
# We need to special case comparing 0 or 1 to
1717
# True/False. While normally comparing any
1818
# integer other than 0/1 to True/False will always
@@ -29,23 +29,11 @@ def _is_special_integer_case(x, y):
2929
# Also need to consider that:
3030
# >>> 0 in [True, False]
3131
# True
32-
if _is_boolean_int(x):
32+
if _is_actual_number(x) and x in (0, 1):
3333
return isinstance(y, bool)
34-
elif _is_boolean_int(y):
34+
elif _is_actual_number(y) and y in (0, 1):
3535
return isinstance(x, bool)
3636

37-
def _is_boolean_int(num):
38-
"""
39-
For backwards compatibility, Python considers bool to be an int.
40-
This causes issues when doing type comparison with isinstance(x, int).
41-
This function ensures the value is an actual int respresenting a boolean.
42-
"""
43-
return (
44-
not isinstance(num, bool)
45-
and isinstance(num, int)
46-
and num in (0, 1)
47-
)
48-
4937

5038
def _is_comparable(x):
5139
# The spec doesn't officially support string types yet,
@@ -63,7 +51,7 @@ def _is_actual_number(x):
6351
# True
6452
# >>> isinstance(True, int)
6553
# True
66-
if x is True or x is False:
54+
if isinstance(x, bool):
6755
return False
6856
return isinstance(x, Number)
6957

@@ -269,7 +257,7 @@ def visit_and_expression(self, node, value):
269257

270258
def visit_not_expression(self, node, value):
271259
original_result = self.visit(node['children'][0], value)
272-
if type(original_result) is int and original_result == 0:
260+
if _is_actual_number(original_result) and original_result == 0:
273261
# Special case for 0, !0 should be false, not true.
274262
# 0 is not a special cased integer in jmespath.
275263
return False

tests/compliance/boolean.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@
7676
"False": false,
7777
"Number": 5,
7878
"EmptyList": [],
79-
"Zero": 0
79+
"Zero": 0,
80+
"ZeroFloat": 0.0
8081
},
8182
"cases": [
8283
{
@@ -198,6 +199,14 @@
198199
{
199200
"expression": "!!Zero",
200201
"result": true
202+
},
203+
{
204+
"expression": "Zero || Number",
205+
"result": 0
206+
},
207+
{
208+
"expression": "ZeroFloat || Number",
209+
"result": 0.0
201210
}
202211
]
203212
},

tests/compliance/filters.json

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,88 @@
265265
}
266266
]
267267
},
268+
{
269+
"given": {"foo": [
270+
{"key": true},
271+
{"key": false},
272+
{"key": 0},
273+
{"key": 0.0},
274+
{"key": 1},
275+
{"key": 1.0},
276+
{"key": [0]},
277+
{"key": null},
278+
{"key": [1]},
279+
{"key": []},
280+
{"key": {}},
281+
{"key": {"a":2}}
282+
]},
283+
"cases": [
284+
{
285+
"expression": "foo[?key == `true`]",
286+
"result": [{"key": true}]
287+
},
288+
{
289+
"expression": "foo[?key == `false`]",
290+
"result": [{"key": false}]
291+
},
292+
{
293+
"expression": "foo[?key]",
294+
"result": [
295+
{"key": true},
296+
{"key": 0},
297+
{"key": 0.0},
298+
{"key": 1},
299+
{"key": 1.0},
300+
{"key": [0]},
301+
{"key": [1]},
302+
{"key": {"a": 2}}
303+
]
304+
},
305+
{
306+
"expression": "foo[? !key]",
307+
"result": [
308+
{"key": false},
309+
{"key": null},
310+
{"key": []},
311+
{"key": {}}
312+
]
313+
},
314+
{
315+
"expression": "foo[? !!key]",
316+
"result": [
317+
{"key": true},
318+
{"key": 0},
319+
{"key": 0.0},
320+
{"key": 1},
321+
{"key": 1.0},
322+
{"key": [0]},
323+
{"key": [1]},
324+
{"key": {"a": 2}}
325+
]
326+
},
327+
{
328+
"expression": "foo[? `true`]",
329+
"result": [
330+
{"key": true},
331+
{"key": false},
332+
{"key": 0},
333+
{"key": 0.0},
334+
{"key": 1},
335+
{"key": 1.0},
336+
{"key": [0]},
337+
{"key": null},
338+
{"key": [1]},
339+
{"key": []},
340+
{"key": {}},
341+
{"key": {"a":2}}
342+
]
343+
},
344+
{
345+
"expression": "foo[? `false`]",
346+
"result": []
347+
}
348+
]
349+
},
268350
{
269351
"given": {"reservations": [
270352
{"instances": [

0 commit comments

Comments
 (0)