Commit 3e544076 authored by Stefan Behnel's avatar Stefan Behnel

merge

parents d0697c2f f5911810
...@@ -1094,11 +1094,11 @@ class StringNode(PyConstNode): ...@@ -1094,11 +1094,11 @@ class StringNode(PyConstNode):
self.check_for_coercion_error(dst_type, fail=True) self.check_for_coercion_error(dst_type, fail=True)
# this will be a unicode string in Py3, so make sure we can decode it # this will be a unicode string in Py3, so make sure we can decode it
if self.value.encoding: if self.value.encoding and self.unicode_value is None:
encoding = self.value.encoding encoding = self.value.encoding
try: try:
self.value.decode(encoding) self.value.decode(encoding)
except UnicodeDecodeError: except (UnicodeDecodeError, AttributeError):
error(self.pos, "String decoding as '%s' failed. Consider using a byte string or unicode string explicitly, or adjust the source code encoding." % encoding) error(self.pos, "String decoding as '%s' failed. Consider using a byte string or unicode string explicitly, or adjust the source code encoding." % encoding)
return self return self
......
...@@ -1280,6 +1280,53 @@ class EarlyReplaceBuiltinCalls(Visitor.EnvTransform): ...@@ -1280,6 +1280,53 @@ class EarlyReplaceBuiltinCalls(Visitor.EnvTransform):
gen_expr_node.pos, loop = loop_node, result_node = result_ref, gen_expr_node.pos, loop = loop_node, result_node = result_ref,
expr_scope = gen_expr_node.expr_scope, orig_func = is_any and 'any' or 'all') expr_scope = gen_expr_node.expr_scope, orig_func = is_any and 'any' or 'all')
def _handle_simple_function_sorted(self, node, pos_args):
"""Transform sorted(genexpr) into [listcomp].sort(). CPython
just reads the iterable into a list and calls .sort() on it.
Expanding the iterable in a listcomp is still faster.
"""
if len(pos_args) != 1:
return node
if not isinstance(pos_args[0], ExprNodes.GeneratorExpressionNode):
return node
gen_expr_node = pos_args[0]
loop_node = gen_expr_node.loop
yield_expression, yield_stat_node = self._find_single_yield_expression(loop_node)
if yield_expression is None:
return node
result_node = UtilNodes.ResultRefNode(
pos = loop_node.pos, type = Builtin.list_type, may_hold_none=False)
target = ExprNodes.ListNode(node.pos, args = [])
append_node = ExprNodes.ComprehensionAppendNode(
yield_expression.pos, expr = yield_expression,
target = ExprNodes.CloneNode(target))
Visitor.recursively_replace_node(loop_node, yield_stat_node, append_node)
listcomp_node = ExprNodes.ComprehensionNode(
gen_expr_node.pos, loop = loop_node, target = target,
append = append_node, type = Builtin.list_type,
expr_scope = gen_expr_node.expr_scope,
has_local_scope = True)
listcomp_assign_node = Nodes.SingleAssignmentNode(
node.pos, lhs = result_node, rhs = listcomp_node, first = True)
sort_method = ExprNodes.AttributeNode(
node.pos, obj = result_node, attribute = EncodedString('sort'),
# entry ? type ?
needs_none_check = False)
sort_node = Nodes.ExprStatNode(
node.pos, expr = ExprNodes.SimpleCallNode(
node.pos, function = sort_method, args = []))
sort_node.analyse_declarations(self.current_env())
return UtilNodes.TempResultFromStatNode(
result_node,
Nodes.StatListNode(node.pos, stats = [ listcomp_assign_node, sort_node ]))
def _handle_simple_function_sum(self, node, pos_args): def _handle_simple_function_sum(self, node, pos_args):
"""Transform sum(genexpr) into an equivalent inlined aggregation loop. """Transform sum(genexpr) into an equivalent inlined aggregation loop.
""" """
......
...@@ -1448,9 +1448,10 @@ class TransformBuiltinMethods(EnvTransform): ...@@ -1448,9 +1448,10 @@ class TransformBuiltinMethods(EnvTransform):
error(self.pos, "Builtin 'locals()' called with wrong number of args, expected 0, got %d" % len(node.args)) error(self.pos, "Builtin 'locals()' called with wrong number of args, expected 0, got %d" % len(node.args))
return node return node
pos = node.pos pos = node.pos
items = [ExprNodes.DictItemNode(pos, items = [ ExprNodes.DictItemNode(pos,
key=ExprNodes.StringNode(pos, value=var), key=ExprNodes.StringNode(pos, value=var, unicode_value=var),
value=ExprNodes.NameNode(pos, name=var)) for var in lenv.entries] value=ExprNodes.NameNode(pos, name=var))
for var in lenv.entries ]
return ExprNodes.DictNode(pos, key_value_pairs=items) return ExprNodes.DictNode(pos, key_value_pairs=items)
# cython.foo # cython.foo
......
...@@ -120,9 +120,10 @@ class ResultRefNode(AtomicExprNode): ...@@ -120,9 +120,10 @@ class ResultRefNode(AtomicExprNode):
subexprs = [] subexprs = []
lhs_of_first_assignment = False lhs_of_first_assignment = False
def __init__(self, expression=None, pos=None, type=None): def __init__(self, expression=None, pos=None, type=None, may_hold_none=True):
self.expression = expression self.expression = expression
self.pos = None self.pos = None
self.may_hold_none = may_hold_none
if expression is not None: if expression is not None:
self.pos = expression.pos self.pos = expression.pos
if hasattr(expression, "type"): if hasattr(expression, "type"):
...@@ -141,6 +142,11 @@ class ResultRefNode(AtomicExprNode): ...@@ -141,6 +142,11 @@ class ResultRefNode(AtomicExprNode):
if self.expression is not None: if self.expression is not None:
return self.expression.infer_type(env) return self.expression.infer_type(env)
def may_be_none(self):
if not self.type.is_pyobject:
return False
return self.may_hold_none
def _DISABLED_may_be_none(self): def _DISABLED_may_be_none(self):
# not sure if this is safe - the expression may not be the # not sure if this is safe - the expression may not be the
# only value that gets assigned # only value that gets assigned
......
...@@ -62,6 +62,8 @@ VER_DEP_MODULES = { ...@@ -62,6 +62,8 @@ VER_DEP_MODULES = {
]), ]),
(2,4) : (operator.le, lambda x: x in ['run.extern_builtins_T258' (2,4) : (operator.le, lambda x: x in ['run.extern_builtins_T258'
]), ]),
(2,3) : (operator.le, lambda x: x in ['run.builtin_sorted'
]),
(2,6) : (operator.lt, lambda x: x in ['run.print_function', (2,6) : (operator.lt, lambda x: x in ['run.print_function',
'run.cython3', 'run.cython3',
]), ]),
...@@ -1151,6 +1153,8 @@ def main(): ...@@ -1151,6 +1153,8 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
try: try:
main() main()
except SystemExit: # <= Py2.4 ...
raise
except Exception: except Exception:
traceback.print_exc() traceback.print_exc()
try: try:
......
cimport cython
@cython.test_fail_if_path_exists("//GeneratorExpressionNode",
"//ComprehensionNode//NoneCheckNode")
@cython.test_assert_path_exists("//ComprehensionNode")
def sorted_genexp():
"""
>>> sorted_genexp()
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
"""
return sorted(i*i for i in range(10,0,-1))
@cython.test_assert_path_exists("//SimpleCallNode//SimpleCallNode")
def sorted_list():
"""
>>> sorted_list()
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
"""
return sorted(list(range(10,0,-1)))
...@@ -17,6 +17,19 @@ def print_function(*args): ...@@ -17,6 +17,19 @@ def print_function(*args):
""" """
print(*args) # this isn't valid Py2 syntax print(*args) # this isn't valid Py2 syntax
def locals_function(a, b=2):
"""
>>> items = list(locals_function(1).items())
>>> items.sort()
>>> for item in items:
... print('%s = %r' % item)
a = 1
b = 2
x = 'abc'
"""
x = 'abc'
return locals()
def exec3_function(cmd): def exec3_function(cmd):
""" """
>>> exec3_function('a = 1+1')['a'] >>> exec3_function('a = 1+1')['a']
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment