Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
cython
Commits
77cbab3a
Commit
77cbab3a
authored
Oct 13, 2011
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Plain Diff
merged fix for ticket #717 into master
parents
6bfb6480
847ef5d1
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
127 additions
and
78 deletions
+127
-78
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+103
-62
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+5
-2
Cython/Compiler/Optimize.py
Cython/Compiler/Optimize.py
+4
-5
Cython/Compiler/Parsing.py
Cython/Compiler/Parsing.py
+13
-7
tests/run/non_dict_kwargs_T470.pyx
tests/run/non_dict_kwargs_T470.pyx
+2
-2
No files found.
Cython/Compiler/ExprNodes.py
View file @
77cbab3a
...
@@ -3722,11 +3722,10 @@ class GeneralCallNode(CallNode):
...
@@ -3722,11 +3722,10 @@ class GeneralCallNode(CallNode):
# function ExprNode
# function ExprNode
# positional_args ExprNode Tuple of positional arguments
# positional_args ExprNode Tuple of positional arguments
# keyword_args ExprNode or None Dict of keyword arguments
# keyword_args ExprNode or None Dict of keyword arguments
# starstar_arg ExprNode or None Dict of extra keyword args
type
=
py_object_type
type
=
py_object_type
subexprs
=
[
'function'
,
'positional_args'
,
'keyword_args'
,
'starstar_arg'
]
subexprs
=
[
'function'
,
'positional_args'
,
'keyword_args'
]
nogil_check
=
Node
.
gil_error
nogil_check
=
Node
.
gil_error
...
@@ -3734,15 +3733,14 @@ class GeneralCallNode(CallNode):
...
@@ -3734,15 +3733,14 @@ class GeneralCallNode(CallNode):
function
=
self
.
function
.
compile_time_value
(
denv
)
function
=
self
.
function
.
compile_time_value
(
denv
)
positional_args
=
self
.
positional_args
.
compile_time_value
(
denv
)
positional_args
=
self
.
positional_args
.
compile_time_value
(
denv
)
keyword_args
=
self
.
keyword_args
.
compile_time_value
(
denv
)
keyword_args
=
self
.
keyword_args
.
compile_time_value
(
denv
)
starstar_arg
=
self
.
starstar_arg
.
compile_time_value
(
denv
)
try
:
try
:
keyword_args
.
update
(
starstar_arg
)
return
function
(
*
positional_args
,
**
keyword_args
)
return
function
(
*
positional_args
,
**
keyword_args
)
except
Exception
,
e
:
except
Exception
,
e
:
self
.
compile_time_value_error
(
e
)
self
.
compile_time_value_error
(
e
)
def
explicit_args_kwds
(
self
):
def
explicit_args_kwds
(
self
):
if
self
.
starstar_arg
or
not
isinstance
(
self
.
positional_args
,
TupleNode
):
if
(
self
.
keyword_args
and
not
isinstance
(
self
.
keyword_args
,
DictNode
)
or
not
isinstance
(
self
.
positional_args
,
TupleNode
)):
raise
CompileError
(
self
.
pos
,
raise
CompileError
(
self
.
pos
,
'Compile-time keyword arguments must be explicit.'
)
'Compile-time keyword arguments must be explicit.'
)
return
self
.
positional_args
.
args
,
self
.
keyword_args
return
self
.
positional_args
.
args
,
self
.
keyword_args
...
@@ -3754,8 +3752,6 @@ class GeneralCallNode(CallNode):
...
@@ -3754,8 +3752,6 @@ class GeneralCallNode(CallNode):
self
.
positional_args
.
analyse_types
(
env
)
self
.
positional_args
.
analyse_types
(
env
)
if
self
.
keyword_args
:
if
self
.
keyword_args
:
self
.
keyword_args
.
analyse_types
(
env
)
self
.
keyword_args
.
analyse_types
(
env
)
if
self
.
starstar_arg
:
self
.
starstar_arg
.
analyse_types
(
env
)
if
not
self
.
function
.
type
.
is_pyobject
:
if
not
self
.
function
.
type
.
is_pyobject
:
if
self
.
function
.
type
.
is_error
:
if
self
.
function
.
type
.
is_error
:
self
.
type
=
error_type
self
.
type
=
error_type
...
@@ -3766,9 +3762,6 @@ class GeneralCallNode(CallNode):
...
@@ -3766,9 +3762,6 @@ class GeneralCallNode(CallNode):
self
.
function
=
self
.
function
.
coerce_to_pyobject
(
env
)
self
.
function
=
self
.
function
.
coerce_to_pyobject
(
env
)
self
.
positional_args
=
\
self
.
positional_args
=
\
self
.
positional_args
.
coerce_to_pyobject
(
env
)
self
.
positional_args
.
coerce_to_pyobject
(
env
)
if
self
.
starstar_arg
:
self
.
starstar_arg
=
\
self
.
starstar_arg
.
coerce_to_pyobject
(
env
)
function
=
self
.
function
function
=
self
.
function
if
function
.
is_name
and
function
.
type_entry
:
if
function
.
is_name
and
function
.
type_entry
:
# We are calling an extension type constructor. As long
# We are calling an extension type constructor. As long
...
@@ -3782,37 +3775,16 @@ class GeneralCallNode(CallNode):
...
@@ -3782,37 +3775,16 @@ class GeneralCallNode(CallNode):
def
generate_result_code
(
self
,
code
):
def
generate_result_code
(
self
,
code
):
if
self
.
type
.
is_error
:
return
if
self
.
type
.
is_error
:
return
kwargs_call_function
=
"PyEval_CallObjectWithKeywords"
if
self
.
keyword_args
:
if
self
.
keyword_args
and
self
.
starstar_arg
:
kwargs
=
self
.
keyword_args
.
py_result
()
code
.
put_error_if_neg
(
self
.
pos
,
"PyDict_Update(%s, %s)"
%
(
self
.
keyword_args
.
py_result
(),
self
.
starstar_arg
.
py_result
()))
keyword_code
=
self
.
keyword_args
.
py_result
()
elif
self
.
keyword_args
:
keyword_code
=
self
.
keyword_args
.
py_result
()
elif
self
.
starstar_arg
:
keyword_code
=
self
.
starstar_arg
.
py_result
()
if
self
.
starstar_arg
.
type
is
not
Builtin
.
dict_type
:
# CPython supports calling functions with non-dicts, so do we
code
.
globalstate
.
use_utility_code
(
kwargs_call_utility_code
)
kwargs_call_function
=
"__Pyx_PyEval_CallObjectWithKeywords"
else
:
keyword_code
=
None
if
not
keyword_code
:
call_code
=
"PyObject_Call(%s, %s, NULL)"
%
(
self
.
function
.
py_result
(),
self
.
positional_args
.
py_result
())
else
:
else
:
call_code
=
"%s(%s, %s, %s)"
%
(
kwargs
=
'NULL'
kwargs_call_function
,
self
.
function
.
py_result
(),
self
.
positional_args
.
py_result
(),
keyword_code
)
code
.
putln
(
code
.
putln
(
"%s =
%s
; %s"
%
(
"%s =
PyObject_Call(%s, %s, %s)
; %s"
%
(
self
.
result
(),
self
.
result
(),
call_code
,
self
.
function
.
py_result
(),
self
.
positional_args
.
py_result
(),
kwargs
,
code
.
error_goto_if_null
(
self
.
result
(),
self
.
pos
)))
code
.
error_goto_if_null
(
self
.
result
(),
self
.
pos
)))
code
.
put_gotref
(
self
.
py_result
())
code
.
put_gotref
(
self
.
py_result
())
...
@@ -5280,6 +5252,7 @@ class DictItemNode(ExprNode):
...
@@ -5280,6 +5252,7 @@ class DictItemNode(ExprNode):
def
__iter__
(
self
):
def
__iter__
(
self
):
return
iter
([
self
.
key
,
self
.
value
])
return
iter
([
self
.
key
,
self
.
value
])
class
ModuleNameMixin
(
object
):
class
ModuleNameMixin
(
object
):
def
set_mod_name
(
self
,
env
):
def
set_mod_name
(
self
,
env
):
self
.
module_name
=
env
.
global_scope
().
qualified_name
self
.
module_name
=
env
.
global_scope
().
qualified_name
...
@@ -5372,36 +5345,66 @@ class Py3ClassNode(ExprNode):
...
@@ -5372,36 +5345,66 @@ class Py3ClassNode(ExprNode):
code
.
put_gotref
(
self
.
py_result
())
code
.
put_gotref
(
self
.
py_result
())
class
KeywordArgsNode
(
ExprNode
):
class
KeywordArgsNode
(
ExprNode
):
#
Helper class for keyword arguments
#
Helper class for keyword arguments.
#
#
#
keyword_args ExprNode or None Keyword arguments
#
starstar_arg DictNode
#
starstar_arg ExprNode or None Extra arguments
#
keyword_args [DictItemNode]
subexprs
=
[
'keyword_args'
,
'starstar_arg'
]
subexprs
=
[
'starstar_arg'
,
'keyword_args'
]
is_temp
=
1
type
=
dict_type
def
calculate_constant_result
(
self
):
result
=
dict
(
self
.
starstar_arg
.
constant_result
)
for
item
in
self
.
keyword_args
:
key
,
value
=
item
.
constant_result
if
key
in
result
:
raise
ValueError
(
"duplicate keyword argument found: %s"
%
key
)
result
[
key
]
=
value
self
.
constant_result
=
result
def
compile_time_value
(
self
,
denv
):
result
=
self
.
starstar_arg
.
compile_time_value
(
denv
)
pairs
=
[
(
item
.
key
.
compile_time_value
(
denv
),
item
.
value
.
compile_time_value
(
denv
))
for
item
in
self
.
keyword_args
]
try
:
result
=
dict
(
result
)
for
key
,
value
in
pairs
:
if
key
in
result
:
raise
ValueError
(
"duplicate keyword argument found: %s"
%
key
)
result
[
key
]
=
value
except
Exception
,
e
:
self
.
compile_time_value_error
(
e
)
return
result
def
type_dependencies
(
self
,
env
):
return
()
def
infer_type
(
self
,
env
):
return
dict_type
def
analyse_types
(
self
,
env
):
def
analyse_types
(
self
,
env
):
if
self
.
keyword_args
:
self
.
keyword_args
.
analyse_types
(
env
)
if
self
.
starstar_arg
:
self
.
starstar_arg
.
analyse_types
(
env
)
self
.
starstar_arg
.
analyse_types
(
env
)
# make sure we have a Python object as **kwargs mapping
self
.
starstar_arg
=
self
.
starstar_arg
.
coerce_to_pyobject
(
env
).
as_none_safe_node
(
self
.
starstar_arg
=
\
# FIXME: CPython's error message starts with the runtime function name
self
.
starstar_arg
.
coerce_to_pyobject
(
env
)
'argument after ** must be a mapping, not NoneType'
)
self
.
type
=
py_object_type
for
item
in
self
.
keyword_args
:
self
.
is_temp
=
1
item
.
analyse_types
(
env
)
def
may_be_none
(
self
):
return
False
gil_message
=
"Constructing
Keyword Args
"
gil_message
=
"Constructing
Python dict
"
def
generate_result_code
(
self
,
code
):
def
generate_evaluation_code
(
self
,
code
):
if
self
.
keyword_args
and
self
.
starstar_arg
:
code
.
mark_pos
(
self
.
pos
)
code
.
put_error_if_neg
(
self
.
pos
,
self
.
allocate_temp_result
(
code
)
"PyDict_Update(%s, %s)"
%
(
self
.
starstar_arg
.
generate_evaluation_code
(
code
)
self
.
keyword_args
.
py_result
(),
if
self
.
starstar_arg
.
type
is
not
Builtin
.
dict_type
:
self
.
starstar_arg
.
py_result
()))
# CPython supports calling functions with non-dicts, so do we
code
.
putln
(
'if (likely(PyDict_Check(%s))) {'
%
self
.
starstar_arg
.
py_result
())
if
self
.
keyword_args
:
if
self
.
keyword_args
:
code
.
putln
(
"%s = %s;"
%
(
self
.
result
(),
self
.
keyword_args
.
result
()))
code
.
put_incref
(
self
.
keyword_args
.
result
(),
self
.
keyword_args
.
ctype
())
elif
self
.
starstar_arg
:
code
.
putln
(
code
.
putln
(
"%s = PyDict_Copy(%s); %s"
%
(
"%s = PyDict_Copy(%s); %s"
%
(
self
.
result
(),
self
.
result
(),
...
@@ -5409,11 +5412,49 @@ class KeywordArgsNode(ExprNode):
...
@@ -5409,11 +5412,49 @@ class KeywordArgsNode(ExprNode):
code
.
error_goto_if_null
(
self
.
result
(),
self
.
pos
)))
code
.
error_goto_if_null
(
self
.
result
(),
self
.
pos
)))
code
.
put_gotref
(
self
.
py_result
())
code
.
put_gotref
(
self
.
py_result
())
else
:
else
:
code
.
putln
(
"%s = %s;"
%
(
self
.
result
(),
self
.
starstar_arg
.
py_result
()))
code
.
put_incref
(
self
.
result
(),
py_object_type
)
if
self
.
starstar_arg
.
type
is
not
Builtin
.
dict_type
:
code
.
putln
(
'} else {'
)
code
.
putln
(
code
.
putln
(
"%s = PyDict_New(); %s"
%
(
"%s = PyObject_CallFunctionObjArgs("
"(PyObject*)&PyDict_Type, %s, NULL); %s"
%
(
self
.
result
(),
self
.
result
(),
self
.
starstar_arg
.
py_result
(),
code
.
error_goto_if_null
(
self
.
result
(),
self
.
pos
)))
code
.
error_goto_if_null
(
self
.
result
(),
self
.
pos
)))
code
.
put_gotref
(
self
.
py_result
())
code
.
put_gotref
(
self
.
py_result
())
code
.
putln
(
'}'
)
self
.
starstar_arg
.
generate_disposal_code
(
code
)
self
.
starstar_arg
.
free_temps
(
code
)
if
not
self
.
keyword_args
:
return
code
.
globalstate
.
use_utility_code
(
Nodes
.
raise_double_keywords_utility_code
)
for
item
in
self
.
keyword_args
:
item
.
generate_evaluation_code
(
code
)
code
.
putln
(
"if (unlikely(PyDict_GetItem(%s, %s))) {"
%
(
self
.
result
(),
item
.
key
.
py_result
()))
# FIXME: find out function name at runtime!
code
.
putln
(
'__Pyx_RaiseDoubleKeywordsError("function", %s); %s'
%
(
item
.
key
.
py_result
(),
code
.
error_goto
(
self
.
pos
)))
code
.
putln
(
"}"
)
code
.
put_error_if_neg
(
self
.
pos
,
"PyDict_SetItem(%s, %s, %s)"
%
(
self
.
result
(),
item
.
key
.
py_result
(),
item
.
value
.
py_result
()))
item
.
generate_disposal_code
(
code
)
item
.
free_temps
(
code
)
def
annotate
(
self
,
code
):
self
.
starstar_arg
.
annotate
(
code
)
for
item
in
self
.
keyword_args
:
item
.
annotate
(
code
)
class
PyClassMetaclassNode
(
ExprNode
):
class
PyClassMetaclassNode
(
ExprNode
):
# Helper class holds Python3 metaclass object
# Helper class holds Python3 metaclass object
...
...
Cython/Compiler/Nodes.py
View file @
77cbab3a
...
@@ -3386,9 +3386,12 @@ class PyClassDefNode(ClassDefNode):
...
@@ -3386,9 +3386,12 @@ class PyClassDefNode(ClassDefNode):
# find metaclass" dance at runtime
# find metaclass" dance at runtime
self
.
metaclass
=
item
.
value
self
.
metaclass
=
item
.
value
del
keyword_args
.
key_value_pairs
[
i
]
del
keyword_args
.
key_value_pairs
[
i
]
if
starstar_arg
or
(
keyword_args
and
keyword_args
.
key_value_pairs
)
:
if
starstar_arg
:
self
.
mkw
=
ExprNodes
.
KeywordArgsNode
(
self
.
mkw
=
ExprNodes
.
KeywordArgsNode
(
pos
,
keyword_args
=
keyword_args
,
starstar_arg
=
starstar_arg
)
pos
,
keyword_args
=
keyword_args
and
keyword_args
.
key_value_pairs
or
[],
starstar_arg
=
starstar_arg
)
elif
keyword_args
and
keyword_args
.
key_value_pairs
:
self
.
mkw
=
keyword_args
else
:
else
:
self
.
mkw
=
ExprNodes
.
NullNode
(
pos
)
self
.
mkw
=
ExprNodes
.
NullNode
(
pos
)
if
self
.
metaclass
is
None
:
if
self
.
metaclass
is
None
:
...
...
Cython/Compiler/Optimize.py
View file @
77cbab3a
...
@@ -1638,9 +1638,6 @@ class EarlyReplaceBuiltinCalls(Visitor.EnvTransform):
...
@@ -1638,9 +1638,6 @@ class EarlyReplaceBuiltinCalls(Visitor.EnvTransform):
return
node
return
node
if
not
isinstance
(
kwargs
,
ExprNodes
.
DictNode
):
if
not
isinstance
(
kwargs
,
ExprNodes
.
DictNode
):
return
node
return
node
if
node
.
starstar_arg
:
# we could optimize this by updating the kw dict instead
return
node
return
kwargs
return
kwargs
...
@@ -1663,11 +1660,13 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
...
@@ -1663,11 +1660,13 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
arg_tuple
=
node
.
positional_args
arg_tuple
=
node
.
positional_args
if
not
isinstance
(
arg_tuple
,
ExprNodes
.
TupleNode
):
if
not
isinstance
(
arg_tuple
,
ExprNodes
.
TupleNode
):
return
node
return
node
if
node
.
starstar_arg
:
keyword_args
=
node
.
keyword_args
if
keyword_args
and
not
isinstance
(
keyword_args
,
ExprNodes
.
DictNode
):
# can't handle **kwargs
return
node
return
node
args
=
arg_tuple
.
args
args
=
arg_tuple
.
args
return
self
.
_dispatch_to_handler
(
return
self
.
_dispatch_to_handler
(
node
,
function
,
args
,
node
.
keyword_args
)
node
,
function
,
args
,
keyword_args
)
def
visit_SimpleCallNode
(
self
,
node
):
def
visit_SimpleCallNode
(
self
,
node
):
self
.
visitchildren
(
node
)
self
.
visitchildren
(
node
)
...
...
Cython/Compiler/Parsing.py
View file @
77cbab3a
...
@@ -440,7 +440,8 @@ def p_call_parse_args(s, allow_genexp = True):
...
@@ -440,7 +440,8 @@ def p_call_parse_args(s, allow_genexp = True):
s
.
expect
(
')'
)
s
.
expect
(
')'
)
return
positional_args
,
keyword_args
,
star_arg
,
starstar_arg
return
positional_args
,
keyword_args
,
star_arg
,
starstar_arg
def
p_call_build_packed_args
(
pos
,
positional_args
,
keyword_args
,
star_arg
):
def
p_call_build_packed_args
(
pos
,
positional_args
,
keyword_args
,
star_arg
,
starstar_arg
=
None
):
arg_tuple
=
None
arg_tuple
=
None
keyword_dict
=
None
keyword_dict
=
None
if
positional_args
or
not
star_arg
:
if
positional_args
or
not
star_arg
:
...
@@ -454,11 +455,17 @@ def p_call_build_packed_args(pos, positional_args, keyword_args, star_arg):
...
@@ -454,11 +455,17 @@ def p_call_build_packed_args(pos, positional_args, keyword_args, star_arg):
operand2
=
star_arg_tuple
)
operand2
=
star_arg_tuple
)
else
:
else
:
arg_tuple
=
star_arg_tuple
arg_tuple
=
star_arg_tuple
if
keyword_args
:
if
keyword_args
or
starstar_arg
:
keyword_args
=
[
ExprNodes
.
DictItemNode
(
pos
=
key
.
pos
,
key
=
key
,
value
=
value
)
keyword_args
=
[
ExprNodes
.
DictItemNode
(
pos
=
key
.
pos
,
key
=
key
,
value
=
value
)
for
key
,
value
in
keyword_args
]
for
key
,
value
in
keyword_args
]
keyword_dict
=
ExprNodes
.
DictNode
(
pos
,
if
starstar_arg
:
key_value_pairs
=
keyword_args
)
keyword_dict
=
ExprNodes
.
KeywordArgsNode
(
pos
,
starstar_arg
=
starstar_arg
,
keyword_args
=
keyword_args
)
else
:
keyword_dict
=
ExprNodes
.
DictNode
(
pos
,
key_value_pairs
=
keyword_args
)
return
arg_tuple
,
keyword_dict
return
arg_tuple
,
keyword_dict
def
p_call
(
s
,
function
):
def
p_call
(
s
,
function
):
...
@@ -474,12 +481,11 @@ def p_call(s, function):
...
@@ -474,12 +481,11 @@ def p_call(s, function):
args
=
positional_args
)
args
=
positional_args
)
else
:
else
:
arg_tuple
,
keyword_dict
=
p_call_build_packed_args
(
arg_tuple
,
keyword_dict
=
p_call_build_packed_args
(
pos
,
positional_args
,
keyword_args
,
star_arg
)
pos
,
positional_args
,
keyword_args
,
star_arg
,
starstar_arg
)
return
ExprNodes
.
GeneralCallNode
(
pos
,
return
ExprNodes
.
GeneralCallNode
(
pos
,
function
=
function
,
function
=
function
,
positional_args
=
arg_tuple
,
positional_args
=
arg_tuple
,
keyword_args
=
keyword_dict
,
keyword_args
=
keyword_dict
)
starstar_arg
=
starstar_arg
)
#lambdef: 'lambda' [varargslist] ':' test
#lambdef: 'lambda' [varargslist] ':' test
...
...
tests/run/non_dict_kwargs_T470.pyx
View file @
77cbab3a
...
@@ -40,7 +40,7 @@ def call_non_dict_test():
...
@@ -40,7 +40,7 @@ def call_non_dict_test():
return
func
(
**
NonDict
())
return
func
(
**
NonDict
())
def
call_non_dict_test_kw
():
def
call_non_dict_test_kw
():
return
func
(
a
=
5
,
**
NonDict
())
return
func
(
b
=
5
,
**
NonDict
())
class
SubDict
(
dict
):
class
SubDict
(
dict
):
...
@@ -51,4 +51,4 @@ def call_sub_dict_test():
...
@@ -51,4 +51,4 @@ def call_sub_dict_test():
return
func
(
**
SubDict
())
return
func
(
**
SubDict
())
def
call_sub_dict_test_kw
():
def
call_sub_dict_test_kw
():
return
func
(
a
=
5
,
**
SubDict
())
return
func
(
b
=
5
,
**
SubDict
())
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment