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
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Gwenaël Samain
cython
Commits
b9539756
Commit
b9539756
authored
Sep 23, 2007
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
support for keyword-only arguments and required keywords (PEP 3102)
parent
779e488c
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
62 additions
and
12 deletions
+62
-12
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+45
-4
Cython/Compiler/Parsing.py
Cython/Compiler/Parsing.py
+17
-8
No files found.
Cython/Compiler/Nodes.py
View file @
b9539756
...
@@ -332,6 +332,7 @@ class CArgDeclNode(Node):
...
@@ -332,6 +332,7 @@ class CArgDeclNode(Node):
# default ExprNode or None
# default ExprNode or None
# default_entry Symtab.Entry Entry for the variable holding the default value
# default_entry Symtab.Entry Entry for the variable holding the default value
# is_self_arg boolean Is the "self" arg of an extension type method
# is_self_arg boolean Is the "self" arg of an extension type method
# kw_only boolean Is a keyword-only argument
is_self_arg
=
0
is_self_arg
=
0
...
@@ -1051,9 +1052,12 @@ class DefNode(FuncDefNode):
...
@@ -1051,9 +1052,12 @@ class DefNode(FuncDefNode):
arg_addrs
=
[]
arg_addrs
=
[]
arg_formats
=
[]
arg_formats
=
[]
default_seen
=
0
default_seen
=
0
kw_only_args
=
[]
for
arg
in
self
.
args
:
for
arg
in
self
.
args
:
arg_entry
=
arg
.
entry
arg_entry
=
arg
.
entry
if
arg
.
is_generic
:
if
arg
.
is_generic
:
if
arg
.
kw_only
:
kw_only_args
.
append
(
arg_entry
)
if
arg
.
default
:
if
arg
.
default
:
code
.
putln
(
code
.
putln
(
"%s = %s;"
%
(
"%s = %s;"
%
(
...
@@ -1062,7 +1066,7 @@ class DefNode(FuncDefNode):
...
@@ -1062,7 +1066,7 @@ class DefNode(FuncDefNode):
if
not
default_seen
:
if
not
default_seen
:
arg_formats
.
append
(
"|"
)
arg_formats
.
append
(
"|"
)
default_seen
=
1
default_seen
=
1
elif
default_seen
:
elif
default_seen
and
not
arg
.
kw_only
:
error
(
arg
.
pos
,
"Non-default argument following default argument"
)
error
(
arg
.
pos
,
"Non-default argument following default argument"
)
if
arg
.
needs_conversion
:
if
arg
.
needs_conversion
:
arg_addrs
.
append
(
"&"
+
arg
.
hdr_cname
)
arg_addrs
.
append
(
"&"
+
arg
.
hdr_cname
)
...
@@ -1076,6 +1080,18 @@ class DefNode(FuncDefNode):
...
@@ -1076,6 +1080,18 @@ class DefNode(FuncDefNode):
error
(
arg
.
pos
,
error
(
arg
.
pos
,
"Cannot convert Python object argument to type '%s' (when parsing input arguments)"
"Cannot convert Python object argument to type '%s' (when parsing input arguments)"
%
arg
.
type
)
%
arg
.
type
)
error_return_code
=
"return %s;"
%
self
.
error_value
()
if
kw_only_args
:
max_normal_args
=
len
(
self
.
args
)
-
len
(
kw_only_args
)
code
.
putln
(
"if (%s && PyTuple_GET_SIZE(%s) > %d) {"
%
(
Naming
.
args_cname
,
Naming
.
args_cname
,
max_normal_args
))
code
.
putln
(
'PyErr_Format(PyExc_TypeError, "function takes at most %d non-keyword arguments (%%d given)", PyTuple_GET_SIZE(%s));'
%
(
max_normal_args
,
Naming
.
args_cname
))
code
.
putln
(
error_return_code
)
code
.
putln
(
"}"
)
argformat
=
'"%s"'
%
string
.
join
(
arg_formats
,
""
)
argformat
=
'"%s"'
%
string
.
join
(
arg_formats
,
""
)
has_starargs
=
self
.
star_arg
is
not
None
or
self
.
starstar_arg
is
not
None
has_starargs
=
self
.
star_arg
is
not
None
or
self
.
starstar_arg
is
not
None
if
has_starargs
:
if
has_starargs
:
...
@@ -1086,7 +1102,6 @@ class DefNode(FuncDefNode):
...
@@ -1086,7 +1102,6 @@ class DefNode(FuncDefNode):
code
.
put
(
code
.
put
(
'if (unlikely(!PyArg_ParseTupleAndKeywords(%s))) '
%
'if (unlikely(!PyArg_ParseTupleAndKeywords(%s))) '
%
pt_argstring
)
pt_argstring
)
error_return_code
=
"return %s;"
%
self
.
error_value
()
if
has_starargs
:
if
has_starargs
:
code
.
putln
(
"{"
)
code
.
putln
(
"{"
)
code
.
put_xdecref
(
Naming
.
args_cname
,
py_object_type
)
code
.
put_xdecref
(
Naming
.
args_cname
,
py_object_type
)
...
@@ -1097,7 +1112,33 @@ class DefNode(FuncDefNode):
...
@@ -1097,7 +1112,33 @@ class DefNode(FuncDefNode):
code
.
putln
(
"}"
)
code
.
putln
(
"}"
)
else
:
else
:
code
.
putln
(
error_return_code
)
code
.
putln
(
error_return_code
)
# check that all required keywords were passed
required_keyword_entries
=
[]
kw_checks
=
[]
for
arg
in
self
.
args
:
if
arg
.
is_generic
and
arg
.
kw_only
and
not
arg
.
default
:
arg_entry
=
arg
.
entry
required_keyword_entries
.
append
(
arg_entry
)
kw_checks
.
append
(
"!"
+
arg_entry
.
cname
)
if
required_keyword_entries
:
kw_check
=
' || '
.
join
(
kw_checks
)
code
.
putln
(
"if (unlikely(%s)) {"
%
kw_check
)
for
entry
in
required_keyword_entries
:
kw_checks
.
pop
()
if
kw_checks
:
code
.
putln
(
'if (!%s) {'
%
entry
.
cname
)
code
.
putln
(
'PyErr_SetString(PyExc_TypeError, "keyword argument
\
'
%s
\
'
is required");'
%
(
entry
.
name
))
if
kw_checks
:
code
.
put
(
"} else "
)
if
has_starargs
:
code
.
put_xdecref
(
Naming
.
args_cname
,
py_object_type
)
code
.
put_xdecref
(
Naming
.
kwds_cname
,
py_object_type
)
self
.
generate_arg_xdecref
(
self
.
star_arg
,
code
)
self
.
generate_arg_xdecref
(
self
.
starstar_arg
,
code
)
code
.
putln
(
error_return_code
)
code
.
putln
(
"}"
)
def
put_stararg_decrefs
(
self
,
code
):
def
put_stararg_decrefs
(
self
,
code
):
if
self
.
star_arg
or
self
.
starstar_arg
:
if
self
.
star_arg
or
self
.
starstar_arg
:
code
.
put_xdecref
(
Naming
.
args_cname
,
py_object_type
)
code
.
put_xdecref
(
Naming
.
args_cname
,
py_object_type
)
...
@@ -1128,7 +1169,7 @@ class DefNode(FuncDefNode):
...
@@ -1128,7 +1169,7 @@ class DefNode(FuncDefNode):
star_arg_addr
,
star_arg_addr
,
starstar_arg_addr
,
starstar_arg_addr
,
self
.
error_value
()))
self
.
error_value
()))
def
generate_argument_conversion_code
(
self
,
code
):
def
generate_argument_conversion_code
(
self
,
code
):
# Generate code to convert arguments from
# Generate code to convert arguments from
# signature type to declared type, if needed.
# signature type to declared type, if needed.
...
...
Cython/Compiler/Parsing.py
View file @
b9539756
...
@@ -1520,15 +1520,15 @@ def p_c_func_options(s):
...
@@ -1520,15 +1520,15 @@ def p_c_func_options(s):
c_arg_list_terminators
=
(
'*'
,
'**'
,
'.'
,
')'
)
c_arg_list_terminators
=
(
'*'
,
'**'
,
'.'
,
')'
)
c_arg_list_trailers
=
(
'.'
,
'*'
,
'**'
)
c_arg_list_trailers
=
(
'.'
,
'*'
,
'**'
)
def
p_c_arg_list
(
s
,
in_pyfunc
,
cmethod_flag
=
0
):
def
p_c_arg_list
(
s
,
in_pyfunc
,
cmethod_flag
=
0
,
kw_only
=
0
):
args
=
[]
args
=
[]
if
s
.
sy
not
in
c_arg_list_terminators
:
if
s
.
sy
not
in
c_arg_list_terminators
:
args
.
append
(
p_c_arg_decl
(
s
,
in_pyfunc
,
cmethod_flag
))
args
.
append
(
p_c_arg_decl
(
s
,
in_pyfunc
,
cmethod_flag
,
kw_only
))
while
s
.
sy
==
','
:
while
s
.
sy
==
','
:
s
.
next
()
s
.
next
()
if
s
.
sy
in
c_arg_list_terminators
:
if
s
.
sy
in
c_arg_list_terminators
:
break
break
args
.
append
(
p_c_arg_decl
(
s
,
in_pyfunc
))
args
.
append
(
p_c_arg_decl
(
s
,
in_pyfunc
,
kw_only
=
kw_only
))
return
args
return
args
def
p_optional_ellipsis
(
s
):
def
p_optional_ellipsis
(
s
):
...
@@ -1538,7 +1538,7 @@ def p_optional_ellipsis(s):
...
@@ -1538,7 +1538,7 @@ def p_optional_ellipsis(s):
else
:
else
:
return
0
return
0
def
p_c_arg_decl
(
s
,
in_pyfunc
,
cmethod_flag
=
0
):
def
p_c_arg_decl
(
s
,
in_pyfunc
,
cmethod_flag
=
0
,
kw_only
=
0
):
pos
=
s
.
position
()
pos
=
s
.
position
()
not_none
=
0
not_none
=
0
default
=
None
default
=
None
...
@@ -1560,7 +1560,8 @@ def p_c_arg_decl(s, in_pyfunc, cmethod_flag = 0):
...
@@ -1560,7 +1560,8 @@ def p_c_arg_decl(s, in_pyfunc, cmethod_flag = 0):
base_type
=
base_type
,
base_type
=
base_type
,
declarator
=
declarator
,
declarator
=
declarator
,
not_none
=
not_none
,
not_none
=
not_none
,
default
=
default
)
default
=
default
,
kw_only
=
kw_only
)
def
p_cdef_statement
(
s
,
level
,
visibility
=
'private'
):
def
p_cdef_statement
(
s
,
level
,
visibility
=
'private'
):
pos
=
s
.
position
()
pos
=
s
.
position
()
...
@@ -1762,12 +1763,20 @@ def p_def_statement(s):
...
@@ -1762,12 +1763,20 @@ def p_def_statement(s):
starstar_arg
=
None
starstar_arg
=
None
if
s
.
sy
==
'*'
:
if
s
.
sy
==
'*'
:
s
.
next
()
s
.
next
()
star_arg
=
p_py_arg_decl
(
s
)
if
s
.
sy
==
','
:
if
s
.
sy
==
','
:
s
.
next
()
s
.
next
()
if
s
.
sy
==
'**'
:
if
s
.
sy
==
'IDENT'
:
args
.
extend
(
p_c_arg_list
(
s
,
in_pyfunc
=
1
,
kw_only
=
1
))
else
:
star_arg
=
p_py_arg_decl
(
s
)
if
s
.
sy
==
','
:
s
.
next
()
s
.
next
()
starstar_arg
=
p_py_arg_decl
(
s
)
if
s
.
sy
==
'**'
:
s
.
next
()
starstar_arg
=
p_py_arg_decl
(
s
)
elif
s
.
sy
==
'IDENT'
:
args
.
extend
(
p_c_arg_list
(
s
,
in_pyfunc
=
1
,
kw_only
=
1
))
elif
s
.
sy
==
'**'
:
elif
s
.
sy
==
'**'
:
s
.
next
()
s
.
next
()
starstar_arg
=
p_py_arg_decl
(
s
)
starstar_arg
=
p_py_arg_decl
(
s
)
...
...
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