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
f5c283f7
Commit
f5c283f7
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
b8e78260
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 @
f5c283f7
...
...
@@ -332,6 +332,7 @@ class CArgDeclNode(Node):
# default ExprNode or None
# 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
# kw_only boolean Is a keyword-only argument
is_self_arg
=
0
...
...
@@ -1051,9 +1052,12 @@ class DefNode(FuncDefNode):
arg_addrs
=
[]
arg_formats
=
[]
default_seen
=
0
kw_only_args
=
[]
for
arg
in
self
.
args
:
arg_entry
=
arg
.
entry
if
arg
.
is_generic
:
if
arg
.
kw_only
:
kw_only_args
.
append
(
arg_entry
)
if
arg
.
default
:
code
.
putln
(
"%s = %s;"
%
(
...
...
@@ -1062,7 +1066,7 @@ class DefNode(FuncDefNode):
if
not
default_seen
:
arg_formats
.
append
(
"|"
)
default_seen
=
1
elif
default_seen
:
elif
default_seen
and
not
arg
.
kw_only
:
error
(
arg
.
pos
,
"Non-default argument following default argument"
)
if
arg
.
needs_conversion
:
arg_addrs
.
append
(
"&"
+
arg
.
hdr_cname
)
...
...
@@ -1076,6 +1080,18 @@ class DefNode(FuncDefNode):
error
(
arg
.
pos
,
"Cannot convert Python object argument to type '%s' (when parsing input arguments)"
%
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
,
""
)
has_starargs
=
self
.
star_arg
is
not
None
or
self
.
starstar_arg
is
not
None
if
has_starargs
:
...
...
@@ -1086,7 +1102,6 @@ class DefNode(FuncDefNode):
code
.
put
(
'if (unlikely(!PyArg_ParseTupleAndKeywords(%s))) '
%
pt_argstring
)
error_return_code
=
"return %s;"
%
self
.
error_value
()
if
has_starargs
:
code
.
putln
(
"{"
)
code
.
put_xdecref
(
Naming
.
args_cname
,
py_object_type
)
...
...
@@ -1097,7 +1112,33 @@ class DefNode(FuncDefNode):
code
.
putln
(
"}"
)
else
:
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
):
if
self
.
star_arg
or
self
.
starstar_arg
:
code
.
put_xdecref
(
Naming
.
args_cname
,
py_object_type
)
...
...
@@ -1128,7 +1169,7 @@ class DefNode(FuncDefNode):
star_arg_addr
,
starstar_arg_addr
,
self
.
error_value
()))
def
generate_argument_conversion_code
(
self
,
code
):
# Generate code to convert arguments from
# signature type to declared type, if needed.
...
...
Cython/Compiler/Parsing.py
View file @
f5c283f7
...
...
@@ -1529,15 +1529,15 @@ def p_c_func_options(s):
c_arg_list_terminators
=
(
'*'
,
'**'
,
'.'
,
')'
)
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
=
[]
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
==
','
:
s
.
next
()
if
s
.
sy
in
c_arg_list_terminators
:
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
def
p_optional_ellipsis
(
s
):
...
...
@@ -1547,7 +1547,7 @@ def p_optional_ellipsis(s):
else
:
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
()
not_none
=
0
default
=
None
...
...
@@ -1569,7 +1569,8 @@ def p_c_arg_decl(s, in_pyfunc, cmethod_flag = 0):
base_type
=
base_type
,
declarator
=
declarator
,
not_none
=
not_none
,
default
=
default
)
default
=
default
,
kw_only
=
kw_only
)
def
p_cdef_statement
(
s
,
level
,
visibility
=
'private'
):
pos
=
s
.
position
()
...
...
@@ -1771,12 +1772,20 @@ def p_def_statement(s):
starstar_arg
=
None
if
s
.
sy
==
'*'
:
s
.
next
()
star_arg
=
p_py_arg_decl
(
s
)
if
s
.
sy
==
','
:
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
()
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
==
'**'
:
s
.
next
()
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