Commit 20a16e25 authored by Robert Bradshaw's avatar Robert Bradshaw

Merge branch 'master' of github.com:cython/cython

parents c7c01809 82bdcfa9
...@@ -1986,16 +1986,15 @@ class OptimizeBuiltinCalls(Visitor.MethodDispatcherTransform): ...@@ -1986,16 +1986,15 @@ class OptimizeBuiltinCalls(Visitor.MethodDispatcherTransform):
is_temp = node.is_temp is_temp = node.is_temp
) )
PyObject_AsDouble_func_type = PyrexTypes.CFuncType( PySet_New_func_type = PyrexTypes.CFuncType(
PyrexTypes.c_double_type, [ Builtin.set_type, [
PyrexTypes.CFuncTypeArg("obj", PyrexTypes.py_object_type, None), PyrexTypes.CFuncTypeArg("it", PyrexTypes.py_object_type, None)
], ])
exception_value = "((double)-1)",
exception_check = True)
def _handle_simple_function_set(self, node, function, pos_args): def _handle_simple_function_set(self, node, function, pos_args):
if len(pos_args) == 1 and isinstance(pos_args[0], (ExprNodes.ListNode, if len(pos_args) != 1:
ExprNodes.TupleNode)): return node
if pos_args[0].is_sequence_constructor:
# We can optimise set([x,y,z]) safely into a set literal, # We can optimise set([x,y,z]) safely into a set literal,
# but only if we create all items before adding them - # but only if we create all items before adding them -
# adding an item may raise an exception if it is not # adding an item may raise an exception if it is not
...@@ -2012,7 +2011,39 @@ class OptimizeBuiltinCalls(Visitor.MethodDispatcherTransform): ...@@ -2012,7 +2011,39 @@ class OptimizeBuiltinCalls(Visitor.MethodDispatcherTransform):
for temp in temps[::-1]: for temp in temps[::-1]:
result = UtilNodes.EvalWithTempExprNode(temp, result) result = UtilNodes.EvalWithTempExprNode(temp, result)
return result return result
return node else:
# PySet_New(it) is better than a generic Python call to set(it)
return ExprNodes.PythonCapiCallNode(
node.pos, "PySet_New",
self.PySet_New_func_type,
args=pos_args,
is_temp=node.is_temp,
utility_code=UtilityCode.load_cached('pyset_compat', 'Builtins.c'),
py_name="set")
PyFrozenSet_New_func_type = PyrexTypes.CFuncType(
Builtin.frozenset_type, [
PyrexTypes.CFuncTypeArg("it", PyrexTypes.py_object_type, None)
])
def _handle_simple_function_frozenset(self, node, function, pos_args):
if len(pos_args) != 1:
return node
# PyFrozenSet_New(it) is better than a generic Python call to frozenset(it)
return ExprNodes.PythonCapiCallNode(
node.pos, "PyFrozenSet_New",
self.PyFrozenSet_New_func_type,
args=pos_args,
is_temp=node.is_temp,
utility_code=UtilityCode.load_cached('pyset_compat', 'Builtins.c'),
py_name="frozenset")
PyObject_AsDouble_func_type = PyrexTypes.CFuncType(
PyrexTypes.c_double_type, [
PyrexTypes.CFuncTypeArg("obj", PyrexTypes.py_object_type, None),
],
exception_value = "((double)-1)",
exception_check = True)
def _handle_simple_function_float(self, node, function, pos_args): def _handle_simple_function_float(self, node, function, pos_args):
"""Transform float() into either a C type cast or a faster C """Transform float() into either a C type cast or a faster C
......
...@@ -382,7 +382,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewItems(PyObject* d) { ...@@ -382,7 +382,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewItems(PyObject* d) {
#define PySet_New(iterable) \ #define PySet_New(iterable) \
PyObject_CallFunctionObjArgs((PyObject *)&PySet_Type, (iterable), NULL) PyObject_CallFunctionObjArgs((PyObject *)&PySet_Type, (iterable), NULL)
#define Pyx_PyFrozenSet_New(iterable) \ #define PyFrozenSet_New(iterable) \
PyObject_CallFunctionObjArgs((PyObject *)&PyFrozenSet_Type, (iterable), NULL) PyObject_CallFunctionObjArgs((PyObject *)&PyFrozenSet_Type, (iterable), NULL)
#define PySet_Size(anyset) \ #define PySet_Size(anyset) \
......
# Py2.3 doesn't have the 'set' builtin type, but Cython does :) # Py2.3 doesn't have the 'set' builtin type, but Cython does :)
_set = set _set = set
_frozenset = frozenset
cimport cython cimport cython
def cython_set(): def cython_set():
""" """
>>> cython_set() is _set >>> cython_set() is _set
...@@ -12,6 +14,16 @@ def cython_set(): ...@@ -12,6 +14,16 @@ def cython_set():
assert set is cython.set assert set is cython.set
return cython.set return cython.set
def cython_frozenset():
"""
>>> cython_frozenset() is _frozenset
True
"""
assert frozenset is cython.frozenset
return cython.frozenset
def cython_set_override(): def cython_set_override():
""" """
>>> cython_set_override() is _set >>> cython_set_override() is _set
...@@ -20,6 +32,16 @@ def cython_set_override(): ...@@ -20,6 +32,16 @@ def cython_set_override():
set = 1 set = 1
return cython.set return cython.set
def cython_frozenset_override():
"""
>>> cython_frozenset_override() is _frozenset
True
"""
frozenset = 1
return cython.frozenset
def test_set_literal(): def test_set_literal():
""" """
>>> type(test_set_literal()) is _set >>> type(test_set_literal()) is _set
...@@ -30,6 +52,7 @@ def test_set_literal(): ...@@ -30,6 +52,7 @@ def test_set_literal():
cdef set s1 = {1,'a',1,'b','a'} cdef set s1 = {1,'a',1,'b','a'}
return s1 return s1
def test_set_add(): def test_set_add():
""" """
>>> type(test_set_add()) is _set >>> type(test_set_add()) is _set
...@@ -45,6 +68,7 @@ def test_set_add(): ...@@ -45,6 +68,7 @@ def test_set_add():
s1.add((1,2)) s1.add((1,2))
return s1 return s1
def test_set_clear(): def test_set_clear():
""" """
>>> type(test_set_clear()) is _set >>> type(test_set_clear()) is _set
...@@ -57,6 +81,7 @@ def test_set_clear(): ...@@ -57,6 +81,7 @@ def test_set_clear():
s1.clear() s1.clear()
return s1 return s1
def test_set_clear_None(): def test_set_clear_None():
""" """
>>> test_set_clear_None() >>> test_set_clear_None()
...@@ -66,6 +91,7 @@ def test_set_clear_None(): ...@@ -66,6 +91,7 @@ def test_set_clear_None():
cdef set s1 = None cdef set s1 = None
s1.clear() s1.clear()
def test_set_list_comp(): def test_set_list_comp():
""" """
>>> type(test_set_list_comp()) is _set >>> type(test_set_list_comp()) is _set
...@@ -77,6 +103,19 @@ def test_set_list_comp(): ...@@ -77,6 +103,19 @@ def test_set_list_comp():
s1 = set([i%3 for i in range(5)]) s1 = set([i%3 for i in range(5)])
return s1 return s1
def test_frozenset_list_comp():
"""
>>> type(test_frozenset_list_comp()) is _frozenset
True
>>> sorted(test_frozenset_list_comp())
[0, 1, 2]
"""
cdef frozenset s1
s1 = frozenset([i%3 for i in range(5)])
return s1
def test_set_pop(): def test_set_pop():
""" """
>>> type(test_set_pop()) is _set >>> type(test_set_pop()) is _set
...@@ -90,6 +129,7 @@ def test_set_pop(): ...@@ -90,6 +129,7 @@ def test_set_pop():
two = s1.pop() two = s1.pop()
return s1 return s1
@cython.test_fail_if_path_exists("//SimpleCallNode//NameNode") @cython.test_fail_if_path_exists("//SimpleCallNode//NameNode")
def test_object_pop(s): def test_object_pop(s):
""" """
...@@ -101,6 +141,7 @@ def test_object_pop(s): ...@@ -101,6 +141,7 @@ def test_object_pop(s):
""" """
return s.pop() return s.pop()
def test_set_discard(): def test_set_discard():
""" """
>>> type(test_set_discard()) is _set >>> type(test_set_discard()) is _set
...@@ -117,6 +158,7 @@ def test_set_discard(): ...@@ -117,6 +158,7 @@ def test_set_discard():
s1.discard(3) s1.discard(3)
return s1 return s1
def test_set_sideeffect_unhashable_failure(): def test_set_sideeffect_unhashable_failure():
""" """
>>> test_set_sideeffect_unhashable_failure() >>> test_set_sideeffect_unhashable_failure()
...@@ -135,8 +177,31 @@ def test_set_sideeffect_unhashable_failure(): ...@@ -135,8 +177,31 @@ def test_set_sideeffect_unhashable_failure():
else: assert False, "expected exception not raised" else: assert False, "expected exception not raised"
return L return L
def test_frozenset_sideeffect_unhashable_failure():
"""
>>> test_frozenset_sideeffect_unhashable_failure()
[2, 4, 5]
"""
L = []
def sideeffect(x):
L.append(x)
return x
def unhashable_value(x):
L.append(x)
return set()
try:
s = frozenset([1,sideeffect(2),3,unhashable_value(4),sideeffect(5)])
except TypeError: pass
else: assert False, "expected exception not raised"
return L
@cython.test_assert_path_exists("//SetNode") @cython.test_assert_path_exists("//SetNode")
@cython.test_fail_if_path_exists("//SimpleCallNode") @cython.test_fail_if_path_exists(
"//SimpleCallNode",
"//PythonCapiCallNode"
)
def test_set_of_list(): def test_set_of_list():
""" """
>>> s = test_set_of_list() >>> s = test_set_of_list()
...@@ -147,6 +212,20 @@ def test_set_of_list(): ...@@ -147,6 +212,20 @@ def test_set_of_list():
""" """
return set([1, 2, 3]) return set([1, 2, 3])
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//SetNode")
def test_frozenset_of_list():
"""
>>> s = test_frozenset_of_list()
>>> isinstance(s, _frozenset)
True
>>> sorted(s)
[1, 2, 3]
"""
return frozenset([1, 2, 3])
@cython.test_assert_path_exists("//SetNode") @cython.test_assert_path_exists("//SetNode")
@cython.test_fail_if_path_exists("//SimpleCallNode") @cython.test_fail_if_path_exists("//SimpleCallNode")
def test_set_of_tuple(): def test_set_of_tuple():
...@@ -159,6 +238,52 @@ def test_set_of_tuple(): ...@@ -159,6 +238,52 @@ def test_set_of_tuple():
""" """
return set((1, 2, 3)) return set((1, 2, 3))
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists("//SetNode")
def test_frozenset_of_tuple():
"""
>>> s = test_frozenset_of_tuple()
>>> isinstance(s, _frozenset)
True
>>> sorted(s)
[1, 2, 3]
"""
return frozenset((1, 2, 3))
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists(
"//SimpleCallNode",
"//SetNode"
)
def test_set_of_iterable(x):
"""
>>> s = test_set_of_iterable([1, 2, 3])
>>> isinstance(s, _set)
True
>>> sorted(s)
[1, 2, 3]
"""
return set(x)
@cython.test_assert_path_exists("//PythonCapiCallNode")
@cython.test_fail_if_path_exists(
"//SimpleCallNode",
"//SetNode"
)
def test_frozenset_of_iterable(x):
"""
>>> s = test_frozenset_of_iterable([1, 2, 3])
>>> isinstance(s, _frozenset)
True
>>> sorted(s)
[1, 2, 3]
"""
return frozenset(x)
def sorted(it): def sorted(it):
# Py3 can't compare different types # Py3 can't compare different types
chars = [] chars = []
......
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