Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a6abc08

Browse files
committed
merge
2 parents d7a2258 + 212c992 commit a6abc08

7 files changed

Lines changed: 88 additions & 15 deletions

File tree

CHANGES.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ Features added
1313
Bugs fixed
1414
----------
1515

16+
* "obj[1,]" passed a single integer into the item getter instead of a tuple.
17+
1618
* Cyclic imports at module init time did not work in Py3.
1719

1820
* The names of C++ destructors for template classes were built incorrectly.

Cython/Compiler/ExprNodes.py

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8919,9 +8919,10 @@ class PrimaryCmpNode(ExprNode, CmpNode):
89198919
# Instead, we override all the framework methods
89208920
# which use it.
89218921

8922-
child_attrs = ['operand1', 'operand2', 'cascade']
8922+
child_attrs = ['operand1', 'operand2', 'coerced_operand2', 'cascade']
89238923

89248924
cascade = None
8925+
coerced_operand2 = None
89258926
is_memslice_nonecheck = False
89268927

89278928
def infer_type(self, env):
@@ -8999,9 +9000,11 @@ def analyse_types(self, env):
89999000
self.coerce_operands_to(common_type, env)
90009001

90019002
if self.cascade:
9002-
self.operand2 = self.cascade.optimise_comparison(
9003-
self.operand2.coerce_to_simple(env), env)
9003+
self.operand2 = self.operand2.coerce_to_simple(env)
90049004
self.cascade.coerce_cascaded_operands_to_temp(env)
9005+
operand2 = self.cascade.optimise_comparison(self.operand2, env)
9006+
if operand2 is not self.operand2:
9007+
self.coerced_operand2 = operand2
90059008
if self.is_python_result():
90069009
self.type = PyrexTypes.py_object_type
90079010
else:
@@ -9105,8 +9108,9 @@ def generate_evaluation_code(self, code):
91059108
self.generate_operation_code(code, self.result(),
91069109
self.operand1, self.operator, self.operand2)
91079110
if self.cascade:
9108-
self.cascade.generate_evaluation_code(code,
9109-
self.result(), self.operand2)
9111+
self.cascade.generate_evaluation_code(
9112+
code, self.result(), self.coerced_operand2 or self.operand2,
9113+
needs_evaluation=self.coerced_operand2 is not None)
91109114
self.operand1.generate_disposal_code(code)
91119115
self.operand1.free_temps(code)
91129116
self.operand2.generate_disposal_code(code)
@@ -9141,9 +9145,10 @@ class CascadedCmpNode(Node, CmpNode):
91419145
# operand2 ExprNode
91429146
# cascade CascadedCmpNode
91439147

9144-
child_attrs = ['operand2', 'cascade']
9148+
child_attrs = ['operand2', 'coerced_operand2', 'cascade']
91459149

91469150
cascade = None
9151+
coerced_operand2 = None
91479152
constant_result = constant_value_not_set # FIXME: where to calculate this?
91489153

91499154
def infer_type(self, env):
@@ -9170,7 +9175,9 @@ def optimise_comparison(self, operand1, env):
91709175
if not operand1.type.is_pyobject:
91719176
operand1 = operand1.coerce_to_pyobject(env)
91729177
if self.cascade:
9173-
self.operand2 = self.cascade.optimise_comparison(self.operand2, env)
9178+
operand2 = self.cascade.optimise_comparison(self.operand2, env)
9179+
if operand2 is not self.operand2:
9180+
self.coerced_operand2 = operand2
91749181
return operand1
91759182

91769183
def coerce_operands_to_pyobjects(self, env):
@@ -9186,18 +9193,24 @@ def coerce_cascaded_operands_to_temp(self, env):
91869193
self.operand2 = self.operand2.coerce_to_simple(env)
91879194
self.cascade.coerce_cascaded_operands_to_temp(env)
91889195

9189-
def generate_evaluation_code(self, code, result, operand1):
9196+
def generate_evaluation_code(self, code, result, operand1, needs_evaluation=False):
91909197
if self.type.is_pyobject:
91919198
code.putln("if (__Pyx_PyObject_IsTrue(%s)) {" % result)
91929199
code.put_decref(result, self.type)
91939200
else:
91949201
code.putln("if (%s) {" % result)
9202+
if needs_evaluation:
9203+
operand1.generate_evaluation_code(code)
91959204
self.operand2.generate_evaluation_code(code)
91969205
self.generate_operation_code(code, result,
91979206
operand1, self.operator, self.operand2)
91989207
if self.cascade:
91999208
self.cascade.generate_evaluation_code(
9200-
code, result, self.operand2)
9209+
code, result, self.coerced_operand2 or self.operand2,
9210+
needs_evaluation=self.coerced_operand2 is not None)
9211+
if needs_evaluation:
9212+
operand1.generate_disposal_code(code)
9213+
operand1.free_temps(code)
92019214
# Cascaded cmp result is always temp
92029215
self.operand2.generate_disposal_code(code)
92039216
self.operand2.free_temps(code)

Cython/Compiler/Parsing.pxd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ cpdef p_call_parse_args(PyrexScanner s, bint allow_genexp = *)
4949
cdef p_call_build_packed_args(pos, positional_args, keyword_args, star_arg, starstar_arg)
5050
cdef p_call(PyrexScanner s, function)
5151
cdef p_index(PyrexScanner s, base)
52-
cdef p_subscript_list(PyrexScanner s)
52+
cdef tuple p_subscript_list(PyrexScanner s)
5353
cdef p_subscript(PyrexScanner s)
5454
cdef p_slice_element(PyrexScanner s, follow_set)
5555
cdef expect_ellipsis(PyrexScanner s)

Cython/Compiler/Parsing.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -503,14 +503,14 @@ def p_index(s, base):
503503
# s.sy == '['
504504
pos = s.position()
505505
s.next()
506-
subscripts = p_subscript_list(s)
507-
if len(subscripts) == 1 and len(subscripts[0]) == 2:
506+
subscripts, is_single_value = p_subscript_list(s)
507+
if is_single_value and len(subscripts[0]) == 2:
508508
start, stop = subscripts[0]
509509
result = ExprNodes.SliceIndexNode(pos,
510510
base = base, start = start, stop = stop)
511511
else:
512512
indexes = make_slice_nodes(pos, subscripts)
513-
if len(indexes) == 1:
513+
if is_single_value:
514514
index = indexes[0]
515515
else:
516516
index = ExprNodes.TupleNode(pos, args = indexes)
@@ -520,13 +520,15 @@ def p_index(s, base):
520520
return result
521521

522522
def p_subscript_list(s):
523+
is_single_value = True
523524
items = [p_subscript(s)]
524525
while s.sy == ',':
526+
is_single_value = False
525527
s.next()
526528
if s.sy == ']':
527529
break
528530
items.append(p_subscript(s))
529-
return items
531+
return items, is_single_value
530532

531533
#subscript: '.' '.' '.' | test | [test] ':' [test] [':' [test]]
532534

@@ -2117,7 +2119,7 @@ def p_memoryviewslice_access(s, base_type_node):
21172119
# s.sy == '['
21182120
pos = s.position()
21192121
s.next()
2120-
subscripts = p_subscript_list(s)
2122+
subscripts, _ = p_subscript_list(s)
21212123
# make sure each entry in subscripts is a slice
21222124
for subscript in subscripts:
21232125
if len(subscript) < 2:

tests/run/cmp.pyx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,28 @@ def cascaded_c(double a, double b, double c):
3838
"""
3939
return a < b < c
4040

41+
def cascaded_mix_pyleft(a, double b, double c):
42+
"""
43+
>>> cascaded_mix_pyleft(1, 2, 3)
44+
True
45+
>>> cascaded_mix_pyleft(1, 2, -1)
46+
False
47+
>>> cascaded_mix_pyleft(10, 2, 3)
48+
False
49+
"""
50+
return a < b < c
51+
52+
def cascaded_mix_pyright(double a, double b, c):
53+
"""
54+
>>> cascaded_mix_pyright(1, 2, 3)
55+
True
56+
>>> cascaded_mix_pyright(1, 2, -1)
57+
False
58+
>>> cascaded_mix_pyright(10, 2, 3)
59+
False
60+
"""
61+
return a < b < c
62+
4163
def typed_cmp(list L):
4264
"""
4365
>>> typed_cmp([1,2,3])

tests/run/dict_getitem.pyx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ def test(dict d, index):
3030
"""
3131
return d[index]
3232

33+
def getitem_tuple(dict d, index):
34+
"""
35+
>>> d = {1: 1, (1,): 2}
36+
>>> getitem_tuple(d, 1)
37+
(1, 2)
38+
"""
39+
return d[index], d[index,]
40+
3341
def getitem_in_condition(dict d, key, expected_result):
3442
"""
3543
>>> d = dict(a=1, b=2)

tests/run/inop.pyx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,3 +376,29 @@ def test_inop_cascaded(x):
376376
False
377377
"""
378378
return 1 != x in [2]
379+
380+
def test_inop_cascaded_one():
381+
"""
382+
>>> test_inop_cascaded_one()
383+
False
384+
"""
385+
# copied from CPython's test_grammar.py
386+
return 1 < 1 > 1 == 1 >= 1 <= 1 != 1 in 1 not in 1 is 1 is not 1
387+
388+
def test_inop_cascaded_int_orig(int x):
389+
"""
390+
>>> test_inop_cascaded_int_orig(1)
391+
False
392+
"""
393+
return 1 < 1 > 1 == 1 >= 1 <= 1 != x in 1 not in 1 is 1 is not 1
394+
395+
def test_inop_cascaded_int(int x):
396+
"""
397+
>>> test_inop_cascaded_int(1)
398+
False
399+
>>> test_inop_cascaded_int(2)
400+
True
401+
>>> test_inop_cascaded_int(3)
402+
False
403+
"""
404+
return 1 != x in [1,2]

0 commit comments

Comments
 (0)