Commit c25a6167 authored by Stefan Behnel's avatar Stefan Behnel

allow struct constructors to coerce directly to Python dicts without intermediate assignment

parent 460177f4
...@@ -32,6 +32,9 @@ Bugs fixed ...@@ -32,6 +32,9 @@ Bugs fixed
* Relative cimports could accidentally fall back to trying an absolute cimport * Relative cimports could accidentally fall back to trying an absolute cimport
on failure. on failure.
* The result of calling a C struct constructor no longer requires an intermediate
assignment when coercing to a Python dict.
* Runtime reported file paths of source files (e.g for profiling and tracing) * Runtime reported file paths of source files (e.g for profiling and tracing)
are now relative to the build root directory instead of the main source file. are now relative to the build root directory instead of the main source file.
......
...@@ -7164,6 +7164,13 @@ class DictNode(ExprNode): ...@@ -7164,6 +7164,13 @@ class DictNode(ExprNode):
def coerce_to(self, dst_type, env): def coerce_to(self, dst_type, env):
if dst_type.is_pyobject: if dst_type.is_pyobject:
self.release_errors() self.release_errors()
if self.type.is_struct_or_union:
if not dict_type.subtype_of(dst_type):
error(self.pos, "Cannot interpret struct as non-dict type '%s'" % dst_type)
return DictNode(self.pos, key_value_pairs=[
DictItemNode(item.pos, key=item.key.coerce_to_pyobject(env),
value=item.value.coerce_to_pyobject(env))
for item in self.key_value_pairs])
if not self.type.subtype_of(dst_type): if not self.type.subtype_of(dst_type):
error(self.pos, "Cannot interpret dict as type '%s'" % dst_type) error(self.pos, "Cannot interpret dict as type '%s'" % dst_type)
elif dst_type.is_struct_or_union: elif dst_type.is_struct_or_union:
......
...@@ -13,6 +13,17 @@ def test_constructor(x, y, color): ...@@ -13,6 +13,17 @@ def test_constructor(x, y, color):
cdef Point p = Point(x, y, color) cdef Point p = Point(x, y, color)
return p return p
def return_constructor(x, y, color):
"""
>>> sorted(return_constructor(1,2,255).items())
[('color', 255), ('x', 1.0), ('y', 2.0)]
>>> try: return_constructor(1, None, 255)
... except TypeError: pass
"""
return Point(x, y, color)
def test_constructor_kwds(x, y, color): def test_constructor_kwds(x, y, color):
""" """
>>> sorted(test_constructor_kwds(1.25, 2.5, 128).items()) >>> sorted(test_constructor_kwds(1.25, 2.5, 128).items())
...@@ -25,6 +36,19 @@ def test_constructor_kwds(x, y, color): ...@@ -25,6 +36,19 @@ def test_constructor_kwds(x, y, color):
cdef Point p = Point(x=x, y=y, color=color) cdef Point p = Point(x=x, y=y, color=color)
return p return p
def return_constructor_kwds(x, y, color):
"""
>>> sorted(return_constructor_kwds(1.25, 2.5, 128).items())
[('color', 128), ('x', 1.25), ('y', 2.5)]
>>> return_constructor_kwds(1.25, 2.5, None)
Traceback (most recent call last):
...
TypeError: an integer is required
"""
return Point(x=x, y=y, color=color)
def test_dict_construction(x, y, color): def test_dict_construction(x, y, color):
""" """
>>> sorted(test_dict_construction(4, 5, 64).items()) >>> sorted(test_dict_construction(4, 5, 64).items())
......
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