cython-devel
changeset 2802:df9b7285ec6a
implement #470: non-dicts as **kwargs
| author | Stefan Behnel <scoder@users.berlios.de> |
|---|---|
| date | Thu Jan 14 08:36:13 2010 +0100 (2 years ago) |
| parents | b74db1985752 |
| children | 5d1ea5364347 |
| files | Cython/Compiler/ExprNodes.py tests/run/non_dict_kwargs_T470.pyx |
line diff
1.1 --- a/Cython/Compiler/ExprNodes.py Thu Jan 14 08:03:17 2010 +0100
1.2 +++ b/Cython/Compiler/ExprNodes.py Thu Jan 14 08:36:13 2010 +0100
1.3 @@ -2775,6 +2775,7 @@
1.4
1.5 def generate_result_code(self, code):
1.6 if self.type.is_error: return
1.7 + dict_temp = dict_ref = None
1.8 if self.keyword_args and self.starstar_arg:
1.9 code.put_error_if_neg(self.pos,
1.10 "PyDict_Update(%s, %s)" % (
1.11 @@ -2785,6 +2786,23 @@
1.12 keyword_code = self.keyword_args.py_result()
1.13 elif self.starstar_arg:
1.14 keyword_code = self.starstar_arg.py_result()
1.15 + if self.starstar_arg.type is not Builtin.dict_type:
1.16 + # CPython supports calling functions with non-dicts, so do we
1.17 + dict_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=False)
1.18 + dict_ref = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
1.19 + code.putln("if (unlikely(!PyDict_Check(%s))) {" % keyword_code)
1.20 + code.putln(
1.21 + "%s = PyObject_CallFunctionObjArgs((PyObject*)&PyDict_Type, %s, NULL); %s" % (
1.22 + dict_ref,
1.23 + keyword_code,
1.24 + code.error_goto_if_null(dict_ref, self.pos)))
1.25 + code.put_gotref(dict_ref)
1.26 + code.putln("%s = %s;" % (dict_temp, dict_ref))
1.27 + code.putln("} else {")
1.28 + code.putln("%s = 0;" % dict_ref)
1.29 + code.putln("%s = %s;" % (dict_temp, keyword_code))
1.30 + code.putln("}")
1.31 + keyword_code = dict_temp
1.32 else:
1.33 keyword_code = None
1.34 if not keyword_code:
1.35 @@ -2802,6 +2820,10 @@
1.36 call_code,
1.37 code.error_goto_if_null(self.result(), self.pos)))
1.38 code.put_gotref(self.py_result())
1.39 + if dict_ref is not None:
1.40 + code.funcstate.release_temp(dict_temp)
1.41 + code.put_xdecref_clear(dict_ref, py_object_type)
1.42 + code.funcstate.release_temp(dict_ref)
1.43
1.44
1.45 class AsTupleNode(ExprNode):
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/tests/run/non_dict_kwargs_T470.pyx Thu Jan 14 08:36:13 2010 +0100
2.3 @@ -0,0 +1,52 @@
2.4 +__doc__ = u"""
2.5 +>>> func(**{'a' : 7})
2.6 +True
2.7 +>>> func(**SubDict())
2.8 +True
2.9 +
2.10 +>>> call_non_dict_test()
2.11 +True
2.12 +>>> call_non_dict_test_kw()
2.13 +True
2.14 +
2.15 +>>> call_sub_dict_test()
2.16 +True
2.17 +>>> call_sub_dict_test_kw()
2.18 +True
2.19 +"""
2.20 +
2.21 +import sys
2.22 +
2.23 +if sys.version_info >= (2,6):
2.24 + __doc__ += u"""
2.25 +>>> func(**NonDict())
2.26 +True
2.27 +"""
2.28 +
2.29 +def func(**kwargs):
2.30 + return type(kwargs) is dict and kwargs['a'] == 7
2.31 +
2.32 +
2.33 +class NonDict(object):
2.34 + def __getitem__(self, k):
2.35 + assert k == 'a'
2.36 + return 7
2.37 + def keys(self):
2.38 + return ['a']
2.39 +
2.40 +def call_non_dict_test():
2.41 + return func(**NonDict())
2.42 +
2.43 +def call_non_dict_test_kw():
2.44 + return func(a=5, **NonDict())
2.45 +
2.46 +
2.47 +class SubDict(dict):
2.48 + def __init__(self):
2.49 + self['a'] = 7
2.50 +
2.51 +def call_sub_dict_test():
2.52 + return func(**SubDict())
2.53 +
2.54 +def call_sub_dict_test_kw():
2.55 + return func(a=5, **SubDict())
