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
cc9f1333
Commit
cc9f1333
authored
Apr 15, 2010
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
support 'not None' and 'or None' on any Python argument
parent
12ad333d
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
100 additions
and
36 deletions
+100
-36
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+23
-11
tests/errors/e_notnone2.pyx
tests/errors/e_notnone2.pyx
+3
-3
tests/run/ext_type_none_arg.pyx
tests/run/ext_type_none_arg.pyx
+74
-22
No files found.
Cython/Compiler/Nodes.py
View file @
cc9f1333
...
...
@@ -1405,6 +1405,7 @@ class FuncDefNode(StatNode, BlockNode):
def
generate_arg_type_test
(
self
,
arg
,
code
):
# Generate type test for one argument.
if
arg
.
type
.
typeobj_is_available
():
code
.
globalstate
.
use_utility_code
(
arg_type_test_utility_code
)
typeptr_cname
=
arg
.
type
.
typeptr_cname
arg_code
=
"((PyObject *)%s)"
%
arg
.
entry
.
cname
code
.
putln
(
...
...
@@ -1419,6 +1420,15 @@ class FuncDefNode(StatNode, BlockNode):
error
(
arg
.
pos
,
"Cannot test type of extern C class "
"without type object name specification"
)
def
generate_arg_none_check
(
self
,
arg
,
code
):
# Generate None check for one argument.
code
.
globalstate
.
use_utility_code
(
arg_type_test_utility_code
)
code
.
putln
(
'if (unlikely(((PyObject *)%s) == Py_None)) {'
%
arg
.
entry
.
cname
)
code
.
putln
(
'''PyErr_Format(PyExc_TypeError, "Argument '%s' must not be None"); %s'''
%
(
arg
.
name
,
code
.
error_goto
(
arg
.
pos
)))
code
.
putln
(
'}'
)
def
generate_wrapper_functions
(
self
,
code
):
pass
...
...
@@ -1667,6 +1677,8 @@ class CFuncDefNode(FuncDefNode):
for
arg
in
self
.
type
.
args
:
if
arg
.
needs_type_test
:
self
.
generate_arg_type_test
(
arg
,
code
)
elif
arg
.
type
.
is_pyobject
and
not
arg
.
accept_none
:
self
.
generate_arg_none_check
(
arg
,
code
)
def
error_value
(
self
):
if
self
.
return_type
.
is_pyobject
:
...
...
@@ -1880,23 +1892,25 @@ class DefNode(FuncDefNode):
arg
.
needs_conversion
=
0
arg
.
needs_type_test
=
0
arg
.
is_generic
=
1
if
arg
.
type
.
is_
extension_type
or
arg
.
type
.
is_builtin_type
:
if
arg
.
type
.
is_
pyobject
:
if
arg
.
or_none
:
arg
.
accept_none
=
True
elif
arg
.
not_none
:
arg
.
accept_none
=
False
el
s
e
:
el
if
arg
.
type
.
is_extension_type
or
arg
.
type
.
is_builtin_typ
e
:
# default depends on compiler directive
arg
.
accept_none
=
allow_none_for_extension_args
else
:
# probably just a plain 'object'
arg
.
accept_none
=
True
else
:
arg
.
accept_none
=
True
# won't be used, but must be there
if
arg
.
not_none
:
error
(
self
.
pos
,
"Only
extensi
on type arguments can have 'not None'"
)
error
(
self
.
pos
,
"Only
Pyth
on type arguments can have 'not None'"
)
if
arg
.
or_none
:
error
(
self
.
pos
,
"Only
extensi
on type arguments can have 'or None'"
)
error
(
self
.
pos
,
"Only
Pyth
on type arguments can have 'or None'"
)
def
analyse_signature
(
self
,
env
):
any_type_tests_needed
=
0
if
self
.
entry
.
is_special
:
self
.
entry
.
trivial_signature
=
len
(
self
.
args
)
==
1
and
not
(
self
.
star_arg
or
self
.
starstar_arg
)
elif
not
env
.
directives
[
'always_allow_keywords'
]
and
not
(
self
.
star_arg
or
self
.
starstar_arg
):
...
...
@@ -1941,7 +1955,6 @@ class DefNode(FuncDefNode):
if
not
arg
.
type
.
same_as
(
arg
.
hdr_type
):
if
arg
.
hdr_type
.
is_pyobject
and
arg
.
type
.
is_pyobject
:
arg
.
needs_type_test
=
1
any_type_tests_needed
=
1
else
:
arg
.
needs_conversion
=
1
if
arg
.
needs_conversion
:
...
...
@@ -1959,9 +1972,6 @@ class DefNode(FuncDefNode):
if
arg
.
is_generic
and
\
(
arg
.
type
.
is_extension_type
or
arg
.
type
.
is_builtin_type
):
arg
.
needs_type_test
=
1
any_type_tests_needed
=
1
if
any_type_tests_needed
:
env
.
use_utility_code
(
arg_type_test_utility_code
)
def
bad_signature
(
self
):
sig
=
self
.
entry
.
signature
...
...
@@ -2657,6 +2667,8 @@ class DefNode(FuncDefNode):
for
arg
in
self
.
args
:
if
arg
.
needs_type_test
:
self
.
generate_arg_type_test
(
arg
,
code
)
elif
not
arg
.
accept_none
and
arg
.
type
.
is_pyobject
:
self
.
generate_arg_none_check
(
arg
,
code
)
def
error_value
(
self
):
return
self
.
entry
.
signature
.
error_value
...
...
tests/errors/e_notnone2.pyx
View file @
cc9f1333
def
eggs
(
int
x
not
None
,
y
not
None
):
def
eggs
(
int
x
not
None
,
char
*
y
not
None
):
pass
_ERRORS
=
u"""
1:0: Only
extensi
on type arguments can have 'not None'
1:0: Only
extensi
on type arguments can have 'not None'
1:0: Only
Pyth
on type arguments can have 'not None'
1:0: Only
Pyth
on type arguments can have 'not None'
"""
tests/run/ext_type_none_arg.pyx
View file @
cc9f1333
...
...
@@ -15,7 +15,7 @@ cdef attr(MyExtType x):
# defaults, without 'not/or None'
def
ext_default
(
MyExtType
x
):
def
ext_default
(
MyExtType
x
):
# currently behaves like 'or None'
"""
>>> ext_default(MyExtType())
123
...
...
@@ -76,7 +76,7 @@ cdef litem(list L, int item):
# defaults, without 'not/or None'
def
builtin_default
(
list
L
):
def
builtin_default
(
list
L
):
# currently behaves like 'or None'
"""
>>> builtin_default([123])
123
...
...
@@ -129,23 +129,75 @@ def builtin_not_none(list L not None):
return
litem
(
L
,
0
)
## builtin type 'object' (which includes None!) - currently unclear!
## def object_or_none(object o or None):
## """
## >>> object_or_none([])
## list
## >>> object_or_none(None)
## NoneType
## """
## return type(o).__name__
## def object_not_none(object o not None):
## """
## >>> object_not_none([123])
## 123
## >>> object_not_none(None)
## Traceback (most recent call last):
## TypeError: Argument 'o' has incorrect type (expected object, got NoneType)
## """
## return type(o).__name__
## builtin type 'object' - isinstance(None, object) is True!
def
object_default
(
object
o
):
# behaves like 'or None'
"""
>>> object_default(object())
'object'
>>> object_default([])
'list'
>>> object_default(None)
'NoneType'
"""
return
type
(
o
).
__name__
def
object_or_none
(
object
o
or
None
):
"""
>>> object_or_none(object())
'object'
>>> object_or_none([])
'list'
>>> object_or_none(None)
'NoneType'
"""
return
type
(
o
).
__name__
def
object_not_none
(
object
o
not
None
):
"""
>>> object_not_none(object())
'object'
>>> object_not_none([])
'list'
>>> object_not_none(None)
Traceback (most recent call last):
TypeError: Argument 'o' must not be None
"""
return
type
(
o
).
__name__
## untyped 'object' - isinstance(None, object) is True!
def
notype_default
(
o
):
# behaves like 'or None'
"""
>>> notype_default(object())
'object'
>>> notype_default([])
'list'
>>> notype_default(None)
'NoneType'
"""
return
type
(
o
).
__name__
def
notype_or_none
(
o
or
None
):
"""
>>> notype_or_none(object())
'object'
>>> notype_or_none([])
'list'
>>> notype_or_none(None)
'NoneType'
"""
return
type
(
o
).
__name__
def
notype_not_none
(
o
not
None
):
"""
>>> notype_not_none(object())
'object'
>>> notype_not_none([])
'list'
>>> notype_not_none(None)
Traceback (most recent call last):
TypeError: Argument 'o' must not be None
"""
return
type
(
o
).
__name__
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