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
5302d443
Commit
5302d443
authored
Jul 18, 2014
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Plain Diff
merge
parents
e300c8d6
604a6296
Changes
32
Hide whitespace changes
Inline
Side-by-side
Showing
32 changed files
with
594 additions
and
105 deletions
+594
-105
CHANGES.rst
CHANGES.rst
+28
-14
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+33
-10
Cython/Compiler/ModuleNode.py
Cython/Compiler/ModuleNode.py
+3
-1
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+80
-13
Cython/Compiler/Options.py
Cython/Compiler/Options.py
+2
-0
Cython/Compiler/ParseTreeTransforms.py
Cython/Compiler/ParseTreeTransforms.py
+27
-10
Cython/Compiler/Parsing.pxd
Cython/Compiler/Parsing.pxd
+1
-0
Cython/Compiler/Parsing.py
Cython/Compiler/Parsing.py
+19
-6
Cython/Compiler/PyrexTypes.py
Cython/Compiler/PyrexTypes.py
+6
-2
Cython/Compiler/Symtab.py
Cython/Compiler/Symtab.py
+10
-7
Cython/Includes/libcpp/__init__.pxd
Cython/Includes/libcpp/__init__.pxd
+0
-2
Cython/Includes/libcpp/cast.pxd
Cython/Includes/libcpp/cast.pxd
+12
-0
Cython/Plex/Scanners.pxd
Cython/Plex/Scanners.pxd
+1
-1
Cython/Utils.py
Cython/Utils.py
+13
-0
docs/src/userguide/extension_types.rst
docs/src/userguide/extension_types.rst
+19
-11
docs/src/userguide/wrapping_CPlusPlus.rst
docs/src/userguide/wrapping_CPlusPlus.rst
+3
-2
runtests.py
runtests.py
+103
-13
tests/bugs.txt
tests/bugs.txt
+0
-1
tests/compile/builtinfuncs.pyx
tests/compile/builtinfuncs.pyx
+4
-2
tests/errors/e_cdef_closure.pyx
tests/errors/e_cdef_closure.pyx
+1
-6
tests/run/closure_self.pyx
tests/run/closure_self.pyx
+16
-0
tests/run/closure_tests_1.pyx
tests/run/closure_tests_1.pyx
+2
-0
tests/run/closure_tests_2.pyx
tests/run/closure_tests_2.pyx
+2
-0
tests/run/closure_tests_3.pyx
tests/run/closure_tests_3.pyx
+2
-0
tests/run/closure_tests_4.pyx
tests/run/closure_tests_4.pyx
+2
-0
tests/run/closures_T82.pyx
tests/run/closures_T82.pyx
+2
-0
tests/run/cpp_classes_def.pyx
tests/run/cpp_classes_def.pyx
+15
-0
tests/run/cpp_templates.pyx
tests/run/cpp_templates.pyx
+13
-0
tests/run/cpp_templates_helper.h
tests/run/cpp_templates_helper.h
+6
-0
tests/run/py2_super.pyx
tests/run/py2_super.pyx
+97
-0
tests/run/py3k_super.pyx
tests/run/py3k_super.pyx
+20
-4
tests/run/static_methods.pyx
tests/run/static_methods.pyx
+52
-0
No files found.
CHANGES.rst
View file @
5302d443
...
@@ -13,7 +13,9 @@ Features added
...
@@ -13,7 +13,9 @@ Features added
the module's Python namespace. Cpdef enums in pxd files export
the module's Python namespace. Cpdef enums in pxd files export
their values to their own module, iff it exists.
their values to their own module, iff it exists.
* Calls to ``slice()`` are translated to a straight C-API call.
* Allow @staticmethod decorator to declare static cdef methods.
This is especially useful for declaring "constructors" for
cdef classes that can take non-Python arguments.
* Taking a ``char*`` from a temporary Python string object is safer
* Taking a ``char*`` from a temporary Python string object is safer
in more cases and can be done inside of non-trivial expressions,
in more cases and can be done inside of non-trivial expressions,
...
@@ -21,16 +23,6 @@ Features added
...
@@ -21,16 +23,6 @@ Features added
is raised only when such a pointer is assigned to a variable and
is raised only when such a pointer is assigned to a variable and
would thus exceed the lifetime of the string itself.
would thus exceed the lifetime of the string itself.
* The "and"/"or" operators try to avoid unnecessary coercions of their
arguments. They now evaluate the truth value of each argument
independently and only coerce the final result of the whole expression
to the target type (e.g. the type on the left side of an assignment).
This also avoids reference counting overhead for Python values during
evaluation and generally improves the code flow in the generated C code.
* Cascaded assignments (a = b = ...) try to minimise the number of
type coercions.
* Generators have new properties ``__name__`` and ``__qualname__``
* Generators have new properties ``__name__`` and ``__qualname__``
that provide the plain/qualified name of the generator function
that provide the plain/qualified name of the generator function
(following CPython 3.5). See http://bugs.python.org/issue21205
(following CPython 3.5). See http://bugs.python.org/issue21205
...
@@ -46,9 +38,6 @@ Features added
...
@@ -46,9 +38,6 @@ Features added
* HTML output of annotated code uses Pygments for code highlighting
* HTML output of annotated code uses Pygments for code highlighting
and generally received a major overhaul by Matthias Bussonier.
and generally received a major overhaul by Matthias Bussonier.
* The Python expression "2 ** N" is optimised into bit shifting.
See http://bugs.python.org/issue21420
* Simple support for declaring Python object types in Python signature
* Simple support for declaring Python object types in Python signature
annotations. Currently requires setting the compiler directive
annotations. Currently requires setting the compiler directive
``annotation_typing=True``.
``annotation_typing=True``.
...
@@ -56,6 +45,29 @@ Features added
...
@@ -56,6 +45,29 @@ Features added
* New directive ``use_switch`` (defaults to True) to optionally disable
* New directive ``use_switch`` (defaults to True) to optionally disable
the optimization of chained if statement to C switch statements.
the optimization of chained if statement to C switch statements.
* Defines dynamic_cast et al. in `libcpp.cast`.
Optimizations
-------------
* The "and"/"or" operators try to avoid unnecessary coercions of their
arguments. They now evaluate the truth value of each argument
independently and only coerce the final result of the whole expression
to the target type (e.g. the type on the left side of an assignment).
This also avoids reference counting overhead for Python values during
evaluation and generally improves the code flow in the generated C code.
* Cascaded assignments (a = b = ...) try to minimise the number of
type coercions.
* The Python expression "2 ** N" is optimised into bit shifting.
See http://bugs.python.org/issue21420
* Cascaded assignments (a = b = ...) try to minimise the number of
type coercions.
* Calls to ``slice()`` are translated to a straight C-API call.
Bugs fixed
Bugs fixed
----------
----------
...
@@ -91,6 +103,8 @@ Bugs fixed
...
@@ -91,6 +103,8 @@ Bugs fixed
* Correctly handle ``from cython.submodule cimport name``.
* Correctly handle ``from cython.submodule cimport name``.
* Fix infinite recursion when using super with cpdef methods.
Other changes
Other changes
-------------
-------------
...
...
Cython/Compiler/ExprNodes.py
View file @
5302d443
...
@@ -4456,16 +4456,24 @@ class SimpleCallNode(CallNode):
...
@@ -4456,16 +4456,24 @@ class SimpleCallNode(CallNode):
return
func_type
return
func_type
def
analyse_c_function_call
(
self
,
env
):
def
analyse_c_function_call
(
self
,
env
):
if
self
.
function
.
type
is
error_type
:
func_type
=
self
.
function
.
type
if
func_type
is
error_type
:
self
.
type
=
error_type
self
.
type
=
error_type
return
return
if
self
.
self
:
if
func_type
.
is_cfunction
and
func_type
.
is_static_method
:
if
self
.
self
and
self
.
self
.
type
.
is_extension_type
:
# To support this we'd need to pass self to determine whether
# it was overloaded in Python space (possibly via a Cython
# superclass turning a cdef method into a cpdef one).
error
(
self
.
pos
,
"Cannot call a static method on an instance variable."
)
args
=
self
.
args
elif
self
.
self
:
args
=
[
self
.
self
]
+
self
.
args
args
=
[
self
.
self
]
+
self
.
args
else
:
else
:
args
=
self
.
args
args
=
self
.
args
if
self
.
function
.
type
.
is_cpp_class
:
if
func_
type
.
is_cpp_class
:
overloaded_entry
=
self
.
function
.
type
.
scope
.
lookup
(
"operator()"
)
overloaded_entry
=
self
.
function
.
type
.
scope
.
lookup
(
"operator()"
)
if
overloaded_entry
is
None
:
if
overloaded_entry
is
None
:
self
.
type
=
PyrexTypes
.
error_type
self
.
type
=
PyrexTypes
.
error_type
...
@@ -4515,7 +4523,7 @@ class SimpleCallNode(CallNode):
...
@@ -4515,7 +4523,7 @@ class SimpleCallNode(CallNode):
self
.
is_temp
=
1
self
.
is_temp
=
1
# check 'self' argument
# check 'self' argument
if
entry
and
entry
.
is_cmethod
and
func_type
.
args
:
if
entry
and
entry
.
is_cmethod
and
func_type
.
args
and
not
func_type
.
is_static_method
:
formal_arg
=
func_type
.
args
[
0
]
formal_arg
=
func_type
.
args
[
0
]
arg
=
args
[
0
]
arg
=
args
[
0
]
if
formal_arg
.
not_none
:
if
formal_arg
.
not_none
:
...
@@ -5302,10 +5310,12 @@ class AttributeNode(ExprNode):
...
@@ -5302,10 +5310,12 @@ class AttributeNode(ExprNode):
# C method of an extension type or builtin type. If successful,
# C method of an extension type or builtin type. If successful,
# creates a corresponding NameNode and returns it, otherwise
# creates a corresponding NameNode and returns it, otherwise
# returns None.
# returns None.
type
=
self
.
obj
.
analyse_as_extension_type
(
env
)
if
self
.
obj
.
is_string_literal
:
if
type
:
return
type
=
self
.
obj
.
analyse_as_type
(
env
)
if
type
and
(
type
.
is_extension_type
or
type
.
is_builtin_type
or
type
.
is_cpp_class
):
entry
=
type
.
scope
.
lookup_here
(
self
.
attribute
)
entry
=
type
.
scope
.
lookup_here
(
self
.
attribute
)
if
entry
and
entry
.
is_cmethod
:
if
entry
and
(
entry
.
is_cmethod
or
type
.
is_cpp_class
and
entry
.
type
.
is_cfunction
)
:
if
type
.
is_builtin_type
:
if
type
.
is_builtin_type
:
if
not
self
.
is_called
:
if
not
self
.
is_called
:
# must handle this as Python object
# must handle this as Python object
...
@@ -5314,9 +5324,22 @@ class AttributeNode(ExprNode):
...
@@ -5314,9 +5324,22 @@ class AttributeNode(ExprNode):
else
:
else
:
# Create a temporary entry describing the C method
# Create a temporary entry describing the C method
# as an ordinary function.
# as an ordinary function.
ubcm_entry
=
Symtab
.
Entry
(
entry
.
name
,
if
entry
.
func_cname
and
not
hasattr
(
entry
.
type
,
'op_arg_struct'
):
"%s->%s"
%
(
type
.
vtabptr_cname
,
entry
.
cname
),
cname
=
entry
.
func_cname
entry
.
type
)
if
entry
.
type
.
is_static_method
:
ctype
=
entry
.
type
elif
type
.
is_cpp_class
:
error
(
self
.
pos
,
"%s not a static member of %s"
%
(
entry
.
name
,
type
))
ctype
=
PyrexTypes
.
error_type
else
:
# Fix self type.
ctype
=
copy
.
copy
(
entry
.
type
)
ctype
.
args
=
ctype
.
args
[:]
ctype
.
args
[
0
]
=
PyrexTypes
.
CFuncTypeArg
(
'self'
,
type
,
'self'
,
None
)
else
:
cname
=
"%s->%s"
%
(
type
.
vtabptr_cname
,
entry
.
cname
)
ctype
=
entry
.
type
ubcm_entry
=
Symtab
.
Entry
(
entry
.
name
,
cname
,
ctype
)
ubcm_entry
.
is_cfunction
=
1
ubcm_entry
.
is_cfunction
=
1
ubcm_entry
.
func_cname
=
entry
.
func_cname
ubcm_entry
.
func_cname
=
entry
.
func_cname
ubcm_entry
.
is_unbound_cmethod
=
1
ubcm_entry
.
is_unbound_cmethod
=
1
...
...
Cython/Compiler/ModuleNode.py
View file @
5302d443
...
@@ -826,7 +826,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
...
@@ -826,7 +826,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
has_virtual_methods
=
False
has_virtual_methods
=
False
has_destructor
=
False
has_destructor
=
False
for
attr
in
scope
.
var_entries
:
for
attr
in
scope
.
var_entries
:
if
attr
.
type
.
is_cfunction
and
attr
.
name
!=
"<init>"
:
if
attr
.
type
.
is_cfunction
and
attr
.
type
.
is_static_method
:
code
.
put
(
"static "
)
elif
attr
.
type
.
is_cfunction
and
attr
.
name
!=
"<init>"
:
code
.
put
(
"virtual "
)
code
.
put
(
"virtual "
)
has_virtual_methods
=
True
has_virtual_methods
=
True
if
attr
.
cname
[
0
]
==
'~'
:
if
attr
.
cname
[
0
]
==
'~'
:
...
...
Cython/Compiler/Nodes.py
View file @
5302d443
...
@@ -27,6 +27,7 @@ from .Code import UtilityCode
...
@@ -27,6 +27,7 @@ from .Code import UtilityCode
from
.StringEncoding
import
EncodedString
,
escape_byte_string
,
split_string_literal
from
.StringEncoding
import
EncodedString
,
escape_byte_string
,
split_string_literal
from
.
import
Options
from
.
import
Options
from
.
import
DebugFlags
from
.
import
DebugFlags
from
Cython.Utils
import
LazyStr
absolute_path_length
=
0
absolute_path_length
=
0
...
@@ -616,7 +617,7 @@ class CFuncDeclaratorNode(CDeclaratorNode):
...
@@ -616,7 +617,7 @@ class CFuncDeclaratorNode(CDeclaratorNode):
func_type_args
=
[]
func_type_args
=
[]
for
i
,
arg_node
in
enumerate
(
self
.
args
):
for
i
,
arg_node
in
enumerate
(
self
.
args
):
name_declarator
,
type
=
arg_node
.
analyse
(
name_declarator
,
type
=
arg_node
.
analyse
(
env
,
nonempty
=
nonempty
,
is_self_arg
=
(
i
==
0
and
env
.
is_c_class_scope
))
env
,
nonempty
=
nonempty
,
is_self_arg
=
(
i
==
0
and
env
.
is_c_class_scope
and
'staticmethod'
not
in
env
.
directives
))
name
=
name_declarator
.
name
name
=
name_declarator
.
name
if
name
in
directive_locals
:
if
name
in
directive_locals
:
type_node
=
directive_locals
[
name
]
type_node
=
directive_locals
[
name
]
...
@@ -1293,6 +1294,8 @@ class CVarDefNode(StatNode):
...
@@ -1293,6 +1294,8 @@ class CVarDefNode(StatNode):
if
self
.
entry
is
not
None
:
if
self
.
entry
is
not
None
:
self
.
entry
.
is_overridable
=
self
.
overridable
self
.
entry
.
is_overridable
=
self
.
overridable
self
.
entry
.
directive_locals
=
copy
.
copy
(
self
.
directive_locals
)
self
.
entry
.
directive_locals
=
copy
.
copy
(
self
.
directive_locals
)
if
'staticmethod'
in
env
.
directives
:
type
.
is_static_method
=
True
else
:
else
:
if
self
.
directive_locals
:
if
self
.
directive_locals
:
error
(
self
.
pos
,
"Decorators can only be followed by functions"
)
error
(
self
.
pos
,
"Decorators can only be followed by functions"
)
...
@@ -1360,6 +1363,9 @@ class CppClassNode(CStructOrUnionDefNode, BlockNode):
...
@@ -1360,6 +1363,9 @@ class CppClassNode(CStructOrUnionDefNode, BlockNode):
# entry Entry
# entry Entry
# base_classes [CBaseTypeNode]
# base_classes [CBaseTypeNode]
# templates [string] or None
# templates [string] or None
# decorators [DecoratorNode] or None
decorators
=
None
def
declare
(
self
,
env
):
def
declare
(
self
,
env
):
if
self
.
templates
is
None
:
if
self
.
templates
is
None
:
...
@@ -1393,15 +1399,22 @@ class CppClassNode(CStructOrUnionDefNode, BlockNode):
...
@@ -1393,15 +1399,22 @@ class CppClassNode(CStructOrUnionDefNode, BlockNode):
if
scope
is
not
None
:
if
scope
is
not
None
:
scope
.
type
=
self
.
entry
.
type
scope
.
type
=
self
.
entry
.
type
defined_funcs
=
[]
defined_funcs
=
[]
def
func_attributes
(
attributes
):
for
attr
in
attributes
:
if
isinstance
(
attr
,
CFuncDefNode
):
yield
attr
elif
isinstance
(
attr
,
CompilerDirectivesNode
):
for
sub_attr
in
func_attributes
(
attr
.
body
.
stats
):
yield
sub_attr
if
self
.
attributes
is
not
None
:
if
self
.
attributes
is
not
None
:
if
self
.
in_pxd
and
not
env
.
in_cinclude
:
if
self
.
in_pxd
and
not
env
.
in_cinclude
:
self
.
entry
.
defined_in_pxd
=
1
self
.
entry
.
defined_in_pxd
=
1
for
attr
in
self
.
attributes
:
for
attr
in
self
.
attributes
:
attr
.
analyse_declarations
(
scope
)
attr
.
analyse_declarations
(
scope
)
if
isinstance
(
attr
,
CFuncDefNode
):
for
func
in
func_attributes
(
self
.
attributes
):
defined_funcs
.
append
(
attr
)
defined_funcs
.
append
(
func
)
if
self
.
templates
is
not
None
:
if
self
.
templates
is
not
None
:
attr
.
template_declaration
=
"template <typename %s>"
%
", typename "
.
join
(
self
.
templates
)
func
.
template_declaration
=
"template <typename %s>"
%
", typename "
.
join
(
self
.
templates
)
self
.
body
=
StatListNode
(
self
.
pos
,
stats
=
defined_funcs
)
self
.
body
=
StatListNode
(
self
.
pos
,
stats
=
defined_funcs
)
self
.
scope
=
scope
self
.
scope
=
scope
...
@@ -2143,8 +2156,10 @@ class CFuncDefNode(FuncDefNode):
...
@@ -2143,8 +2156,10 @@ class CFuncDefNode(FuncDefNode):
# inline_in_pxd whether this is an inline function in a pxd file
# inline_in_pxd whether this is an inline function in a pxd file
# template_declaration String or None Used for c++ class methods
# template_declaration String or None Used for c++ class methods
# is_const_method whether this is a const method
# is_const_method whether this is a const method
# is_static_method whether this is a static method
# is_c_class_method whether this is a cclass method
child_attrs
=
[
"base_type"
,
"declarator"
,
"body"
,
"py_func"
]
child_attrs
=
[
"base_type"
,
"declarator"
,
"body"
,
"py_func
_stat
"
]
inline_in_pxd
=
False
inline_in_pxd
=
False
decorators
=
None
decorators
=
None
...
@@ -2153,11 +2168,13 @@ class CFuncDefNode(FuncDefNode):
...
@@ -2153,11 +2168,13 @@ class CFuncDefNode(FuncDefNode):
override
=
None
override
=
None
template_declaration
=
None
template_declaration
=
None
is_const_method
=
False
is_const_method
=
False
py_func_stat
=
None
def
unqualified_name
(
self
):
def
unqualified_name
(
self
):
return
self
.
entry
.
name
return
self
.
entry
.
name
def
analyse_declarations
(
self
,
env
):
def
analyse_declarations
(
self
,
env
):
self
.
is_c_class_method
=
env
.
is_c_class_scope
if
self
.
directive_locals
is
None
:
if
self
.
directive_locals
is
None
:
self
.
directive_locals
=
{}
self
.
directive_locals
=
{}
self
.
directive_locals
.
update
(
env
.
directives
[
'locals'
])
self
.
directive_locals
.
update
(
env
.
directives
[
'locals'
])
...
@@ -2168,6 +2185,7 @@ class CFuncDefNode(FuncDefNode):
...
@@ -2168,6 +2185,7 @@ class CFuncDefNode(FuncDefNode):
base_type
=
PyrexTypes
.
error_type
base_type
=
PyrexTypes
.
error_type
else
:
else
:
base_type
=
self
.
base_type
.
analyse
(
env
)
base_type
=
self
.
base_type
.
analyse
(
env
)
self
.
is_static_method
=
'staticmethod'
in
env
.
directives
and
not
env
.
lookup_here
(
'staticmethod'
)
# The 2 here is because we need both function and argument names.
# The 2 here is because we need both function and argument names.
if
isinstance
(
self
.
declarator
,
CFuncDeclaratorNode
):
if
isinstance
(
self
.
declarator
,
CFuncDeclaratorNode
):
name_declarator
,
type
=
self
.
declarator
.
analyse
(
base_type
,
env
,
name_declarator
,
type
=
self
.
declarator
.
analyse
(
base_type
,
env
,
...
@@ -2229,6 +2247,7 @@ class CFuncDefNode(FuncDefNode):
...
@@ -2229,6 +2247,7 @@ class CFuncDefNode(FuncDefNode):
cname
=
name_declarator
.
cname
cname
=
name_declarator
.
cname
type
.
is_const_method
=
self
.
is_const_method
type
.
is_const_method
=
self
.
is_const_method
type
.
is_static_method
=
self
.
is_static_method
self
.
entry
=
env
.
declare_cfunction
(
self
.
entry
=
env
.
declare_cfunction
(
name
,
type
,
self
.
pos
,
name
,
type
,
self
.
pos
,
cname
=
cname
,
visibility
=
self
.
visibility
,
api
=
self
.
api
,
cname
=
cname
,
visibility
=
self
.
visibility
,
api
=
self
.
api
,
...
@@ -2241,7 +2260,7 @@ class CFuncDefNode(FuncDefNode):
...
@@ -2241,7 +2260,7 @@ class CFuncDefNode(FuncDefNode):
if
self
.
return_type
.
is_cpp_class
:
if
self
.
return_type
.
is_cpp_class
:
self
.
return_type
.
check_nullary_constructor
(
self
.
pos
,
"used as a return value"
)
self
.
return_type
.
check_nullary_constructor
(
self
.
pos
,
"used as a return value"
)
if
self
.
overridable
and
not
env
.
is_module_scope
:
if
self
.
overridable
and
not
env
.
is_module_scope
and
not
self
.
is_static_method
:
if
len
(
self
.
args
)
<
1
or
not
self
.
args
[
0
].
type
.
is_pyobject
:
if
len
(
self
.
args
)
<
1
or
not
self
.
args
[
0
].
type
.
is_pyobject
:
# An error will be produced in the cdef function
# An error will be produced in the cdef function
self
.
overridable
=
False
self
.
overridable
=
False
...
@@ -2251,8 +2270,17 @@ class CFuncDefNode(FuncDefNode):
...
@@ -2251,8 +2270,17 @@ class CFuncDefNode(FuncDefNode):
def
declare_cpdef_wrapper
(
self
,
env
):
def
declare_cpdef_wrapper
(
self
,
env
):
if
self
.
overridable
:
if
self
.
overridable
:
if
self
.
is_static_method
:
# TODO(robertwb): Finish this up, perhaps via more function refactoring.
error
(
self
.
pos
,
"static cpdef methods not yet supported"
)
name
=
self
.
entry
.
name
name
=
self
.
entry
.
name
py_func_body
=
self
.
call_self_node
(
is_module_scope
=
env
.
is_module_scope
)
py_func_body
=
self
.
call_self_node
(
is_module_scope
=
env
.
is_module_scope
)
if
self
.
is_static_method
:
from
.ExprNodes
import
NameNode
decorators
=
[
DecoratorNode
(
self
.
pos
,
decorator
=
NameNode
(
self
.
pos
,
name
=
'staticmethod'
))]
decorators
[
0
].
decorator
.
analyse_types
(
env
)
else
:
decorators
=
[]
self
.
py_func
=
DefNode
(
pos
=
self
.
pos
,
self
.
py_func
=
DefNode
(
pos
=
self
.
pos
,
name
=
self
.
entry
.
name
,
name
=
self
.
entry
.
name
,
args
=
self
.
args
,
args
=
self
.
args
,
...
@@ -2260,9 +2288,12 @@ class CFuncDefNode(FuncDefNode):
...
@@ -2260,9 +2288,12 @@ class CFuncDefNode(FuncDefNode):
starstar_arg
=
None
,
starstar_arg
=
None
,
doc
=
self
.
doc
,
doc
=
self
.
doc
,
body
=
py_func_body
,
body
=
py_func_body
,
decorators
=
decorators
,
is_wrapper
=
1
)
is_wrapper
=
1
)
self
.
py_func
.
is_module_scope
=
env
.
is_module_scope
self
.
py_func
.
is_module_scope
=
env
.
is_module_scope
self
.
py_func
.
analyse_declarations
(
env
)
self
.
py_func
.
analyse_declarations
(
env
)
self
.
py_func_stat
=
StatListNode
(
pos
=
self
.
pos
,
stats
=
[
self
.
py_func
])
self
.
py_func
.
type
=
PyrexTypes
.
py_object_type
self
.
entry
.
as_variable
=
self
.
py_func
.
entry
self
.
entry
.
as_variable
=
self
.
py_func
.
entry
self
.
entry
.
used
=
self
.
entry
.
as_variable
.
used
=
True
self
.
entry
.
used
=
self
.
entry
.
as_variable
.
used
=
True
# Reset scope entry the above cfunction
# Reset scope entry the above cfunction
...
@@ -2293,11 +2324,27 @@ class CFuncDefNode(FuncDefNode):
...
@@ -2293,11 +2324,27 @@ class CFuncDefNode(FuncDefNode):
arg_names
=
[
arg
.
name
for
arg
in
args
]
arg_names
=
[
arg
.
name
for
arg
in
args
]
if
is_module_scope
:
if
is_module_scope
:
cfunc
=
ExprNodes
.
NameNode
(
self
.
pos
,
name
=
self
.
entry
.
name
)
cfunc
=
ExprNodes
.
NameNode
(
self
.
pos
,
name
=
self
.
entry
.
name
)
call_arg_names
=
arg_names
skip_dispatch
=
Options
.
lookup_module_cpdef
elif
self
.
type
.
is_static_method
:
class_entry
=
self
.
entry
.
scope
.
parent_type
.
entry
class_node
=
ExprNodes
.
NameNode
(
self
.
pos
,
name
=
class_entry
.
name
)
class_node
.
entry
=
class_entry
cfunc
=
ExprNodes
.
AttributeNode
(
self
.
pos
,
obj
=
class_node
,
attribute
=
self
.
entry
.
name
)
# Calling static c(p)def methods on an instance disallowed.
# TODO(robertwb): Support by passing self to check for override?
skip_dispatch
=
True
else
:
else
:
self_arg
=
ExprNodes
.
NameNode
(
self
.
pos
,
name
=
arg_names
[
0
])
type_entry
=
self
.
type
.
args
[
0
].
type
.
entry
cfunc
=
ExprNodes
.
AttributeNode
(
self
.
pos
,
obj
=
self_arg
,
attribute
=
self
.
entry
.
name
)
type_arg
=
ExprNodes
.
NameNode
(
self
.
pos
,
name
=
type_entry
.
name
)
type_arg
.
entry
=
type_entry
cfunc
=
ExprNodes
.
AttributeNode
(
self
.
pos
,
obj
=
type_arg
,
attribute
=
self
.
entry
.
name
)
skip_dispatch
=
not
is_module_scope
or
Options
.
lookup_module_cpdef
skip_dispatch
=
not
is_module_scope
or
Options
.
lookup_module_cpdef
c_call
=
ExprNodes
.
SimpleCallNode
(
self
.
pos
,
function
=
cfunc
,
args
=
[
ExprNodes
.
NameNode
(
self
.
pos
,
name
=
n
)
for
n
in
arg_names
[
1
-
is_module_scope
:]],
wrapper_call
=
skip_dispatch
)
c_call
=
ExprNodes
.
SimpleCallNode
(
self
.
pos
,
function
=
cfunc
,
args
=
[
ExprNodes
.
NameNode
(
self
.
pos
,
name
=
n
)
for
n
in
arg_names
],
wrapper_call
=
skip_dispatch
)
return
ReturnStatNode
(
pos
=
self
.
pos
,
return_type
=
PyrexTypes
.
py_object_type
,
value
=
c_call
)
return
ReturnStatNode
(
pos
=
self
.
pos
,
return_type
=
PyrexTypes
.
py_object_type
,
value
=
c_call
)
def
declare_arguments
(
self
,
env
):
def
declare_arguments
(
self
,
env
):
...
@@ -2368,8 +2415,13 @@ class CFuncDefNode(FuncDefNode):
...
@@ -2368,8 +2415,13 @@ class CFuncDefNode(FuncDefNode):
header
=
self
.
return_type
.
declaration_code
(
entity
,
dll_linkage
=
dll_linkage
)
header
=
self
.
return_type
.
declaration_code
(
entity
,
dll_linkage
=
dll_linkage
)
#print (storage_class, modifiers, header)
#print (storage_class, modifiers, header)
needs_proto
=
self
.
is_c_class_method
if
self
.
template_declaration
:
if
self
.
template_declaration
:
if
needs_proto
:
code
.
globalstate
.
parts
[
'module_declarations'
].
putln
(
self
.
template_declaration
)
code
.
putln
(
self
.
template_declaration
)
code
.
putln
(
self
.
template_declaration
)
if
needs_proto
:
code
.
globalstate
.
parts
[
'module_declarations'
].
putln
(
"%s%s%s; /* proto*/"
%
(
storage_class
,
modifiers
,
header
))
code
.
putln
(
"%s%s%s {"
%
(
storage_class
,
modifiers
,
header
))
code
.
putln
(
"%s%s%s {"
%
(
storage_class
,
modifiers
,
header
))
def
generate_argument_declarations
(
self
,
env
,
code
):
def
generate_argument_declarations
(
self
,
env
,
code
):
...
@@ -2388,8 +2440,8 @@ class CFuncDefNode(FuncDefNode):
...
@@ -2388,8 +2440,8 @@ class CFuncDefNode(FuncDefNode):
def
generate_argument_parsing_code
(
self
,
env
,
code
):
def
generate_argument_parsing_code
(
self
,
env
,
code
):
i
=
0
i
=
0
used
=
0
used
=
0
scope
=
self
.
local_scope
if
self
.
type
.
optional_arg_count
:
if
self
.
type
.
optional_arg_count
:
scope
=
self
.
local_scope
code
.
putln
(
'if (%s) {'
%
Naming
.
optional_args_cname
)
code
.
putln
(
'if (%s) {'
%
Naming
.
optional_args_cname
)
for
arg
in
self
.
args
:
for
arg
in
self
.
args
:
if
arg
.
default
:
if
arg
.
default
:
...
@@ -2410,6 +2462,16 @@ class CFuncDefNode(FuncDefNode):
...
@@ -2410,6 +2462,16 @@ class CFuncDefNode(FuncDefNode):
code
.
putln
(
'}'
)
code
.
putln
(
'}'
)
code
.
putln
(
'}'
)
code
.
putln
(
'}'
)
# Move arguments into closure if required
def
put_into_closure
(
entry
):
if
entry
.
in_closure
and
not
arg
.
default
:
code
.
putln
(
'%s = %s;'
%
(
entry
.
cname
,
entry
.
original_cname
))
code
.
put_var_incref
(
entry
)
code
.
put_var_giveref
(
entry
)
for
arg
in
self
.
args
:
put_into_closure
(
scope
.
lookup_here
(
arg
.
name
))
def
generate_argument_conversion_code
(
self
,
code
):
def
generate_argument_conversion_code
(
self
,
code
):
pass
pass
...
@@ -2422,6 +2484,11 @@ class CFuncDefNode(FuncDefNode):
...
@@ -2422,6 +2484,11 @@ class CFuncDefNode(FuncDefNode):
elif
arg
.
type
.
is_pyobject
and
not
arg
.
accept_none
:
elif
arg
.
type
.
is_pyobject
and
not
arg
.
accept_none
:
self
.
generate_arg_none_check
(
arg
,
code
)
self
.
generate_arg_none_check
(
arg
,
code
)
def
generate_execution_code
(
self
,
code
):
super
(
CFuncDefNode
,
self
).
generate_execution_code
(
code
)
if
self
.
py_func_stat
:
self
.
py_func_stat
.
generate_execution_code
(
code
)
def
error_value
(
self
):
def
error_value
(
self
):
if
self
.
return_type
.
is_pyobject
:
if
self
.
return_type
.
is_pyobject
:
return
"0"
return
"0"
...
@@ -2877,10 +2944,10 @@ class DefNode(FuncDefNode):
...
@@ -2877,10 +2944,10 @@ class DefNode(FuncDefNode):
return
self
return
self
def
needs_assignment_synthesis
(
self
,
env
,
code
=
None
):
def
needs_assignment_synthesis
(
self
,
env
,
code
=
None
):
if
self
.
is_wrapper
or
self
.
specialized_cpdefs
or
self
.
entry
.
is_fused_specialized
:
return
False
if
self
.
is_staticmethod
:
if
self
.
is_staticmethod
:
return
True
return
True
if
self
.
is_wrapper
or
self
.
specialized_cpdefs
or
self
.
entry
.
is_fused_specialized
:
return
False
if
self
.
no_assignment_synthesis
:
if
self
.
no_assignment_synthesis
:
return
False
return
False
# Should enable for module level as well, that will require more testing...
# Should enable for module level as well, that will require more testing...
...
...
Cython/Compiler/Options.py
View file @
5302d443
...
@@ -209,6 +209,7 @@ directive_types = {
...
@@ -209,6 +209,7 @@ directive_types = {
'cfunc'
:
None
,
# decorators do not take directive value
'cfunc'
:
None
,
# decorators do not take directive value
'ccall'
:
None
,
'ccall'
:
None
,
'inline'
:
None
,
'inline'
:
None
,
'staticmethod'
:
None
,
'cclass'
:
None
,
'cclass'
:
None
,
'returns'
:
type
,
'returns'
:
type
,
'set_initial_path'
:
str
,
'set_initial_path'
:
str
,
...
@@ -225,6 +226,7 @@ directive_scopes = { # defaults to available everywhere
...
@@ -225,6 +226,7 @@ directive_scopes = { # defaults to available everywhere
# 'module', 'function', 'class', 'with statement'
# 'module', 'function', 'class', 'with statement'
'final'
:
(
'cclass'
,
'function'
),
'final'
:
(
'cclass'
,
'function'
),
'inline'
:
(
'function'
,),
'inline'
:
(
'function'
,),
'staticmethod'
:
(
'function'
,),
# FIXME: analysis currently lacks more specific function scope
'no_gc_clear'
:
(
'cclass'
,),
'no_gc_clear'
:
(
'cclass'
,),
'internal'
:
(
'cclass'
,),
'internal'
:
(
'cclass'
,),
'autotestdict'
:
(
'module'
,),
'autotestdict'
:
(
'module'
,),
...
...
Cython/Compiler/ParseTreeTransforms.py
View file @
5302d443
...
@@ -674,7 +674,7 @@ class InterpretCompilerDirectives(CythonTransform, SkipDeclarations):
...
@@ -674,7 +674,7 @@ class InterpretCompilerDirectives(CythonTransform, SkipDeclarations):
for
key
,
value
in
compilation_directive_defaults
.
items
():
for
key
,
value
in
compilation_directive_defaults
.
items
():
self
.
compilation_directive_defaults
[
unicode
(
key
)]
=
copy
.
deepcopy
(
value
)
self
.
compilation_directive_defaults
[
unicode
(
key
)]
=
copy
.
deepcopy
(
value
)
self
.
cython_module_names
=
set
()
self
.
cython_module_names
=
set
()
self
.
directive_names
=
{}
self
.
directive_names
=
{
'staticmethod'
:
'staticmethod'
}
self
.
parallel_directives
=
{}
self
.
parallel_directives
=
{}
def
check_directive_scope
(
self
,
pos
,
directive
,
scope
):
def
check_directive_scope
(
self
,
pos
,
directive
,
scope
):
...
@@ -951,11 +951,11 @@ class InterpretCompilerDirectives(CythonTransform, SkipDeclarations):
...
@@ -951,11 +951,11 @@ class InterpretCompilerDirectives(CythonTransform, SkipDeclarations):
for
name
,
value
in
directives
.
iteritems
():
for
name
,
value
in
directives
.
iteritems
():
if
name
==
'locals'
:
if
name
==
'locals'
:
node
.
directive_locals
=
value
node
.
directive_locals
=
value
elif
name
!=
'final'
:
elif
name
not
in
(
'final'
,
'staticmethod'
)
:
self
.
context
.
nonfatal_error
(
PostParseError
(
self
.
context
.
nonfatal_error
(
PostParseError
(
node
.
pos
,
node
.
pos
,
"Cdef functions can only take cython.locals() "
"Cdef functions can only take cython.locals()
,
"
"or final decorators, got %s."
%
name
))
"
staticmethod,
or final decorators, got %s."
%
name
))
body
=
Nodes
.
StatListNode
(
node
.
pos
,
stats
=
[
node
])
body
=
Nodes
.
StatListNode
(
node
.
pos
,
stats
=
[
node
])
return
self
.
visit_with_directives
(
body
,
directives
)
return
self
.
visit_with_directives
(
body
,
directives
)
...
@@ -966,6 +966,13 @@ class InterpretCompilerDirectives(CythonTransform, SkipDeclarations):
...
@@ -966,6 +966,13 @@ class InterpretCompilerDirectives(CythonTransform, SkipDeclarations):
body
=
Nodes
.
StatListNode
(
node
.
pos
,
stats
=
[
node
])
body
=
Nodes
.
StatListNode
(
node
.
pos
,
stats
=
[
node
])
return
self
.
visit_with_directives
(
body
,
directives
)
return
self
.
visit_with_directives
(
body
,
directives
)
def
visit_CppClassNode
(
self
,
node
):
directives
=
self
.
_extract_directives
(
node
,
'cppclass'
)
if
not
directives
:
return
self
.
visit_Node
(
node
)
body
=
Nodes
.
StatListNode
(
node
.
pos
,
stats
=
[
node
])
return
self
.
visit_with_directives
(
body
,
directives
)
def
visit_PyClassDefNode
(
self
,
node
):
def
visit_PyClassDefNode
(
self
,
node
):
directives
=
self
.
_extract_directives
(
node
,
'class'
)
directives
=
self
.
_extract_directives
(
node
,
'class'
)
if
not
directives
:
if
not
directives
:
...
@@ -979,18 +986,23 @@ class InterpretCompilerDirectives(CythonTransform, SkipDeclarations):
...
@@ -979,18 +986,23 @@ class InterpretCompilerDirectives(CythonTransform, SkipDeclarations):
# Split the decorators into two lists -- real decorators and directives
# Split the decorators into two lists -- real decorators and directives
directives
=
[]
directives
=
[]
realdecs
=
[]
realdecs
=
[]
both
=
[]
for
dec
in
node
.
decorators
:
for
dec
in
node
.
decorators
:
new_directives
=
self
.
try_to_parse_directives
(
dec
.
decorator
)
new_directives
=
self
.
try_to_parse_directives
(
dec
.
decorator
)
if
new_directives
is
not
None
:
if
new_directives
is
not
None
:
for
directive
in
new_directives
:
for
directive
in
new_directives
:
if
self
.
check_directive_scope
(
node
.
pos
,
directive
[
0
],
scope_name
):
if
self
.
check_directive_scope
(
node
.
pos
,
directive
[
0
],
scope_name
):
directives
.
append
(
directive
)
name
,
value
=
directive
if
self
.
directives
.
get
(
name
,
object
())
!=
value
:
directives
.
append
(
directive
)
if
directive
[
0
]
==
'staticmethod'
:
both
.
append
(
dec
)
else
:
else
:
realdecs
.
append
(
dec
)
realdecs
.
append
(
dec
)
if
realdecs
and
isinstance
(
node
,
(
Nodes
.
CFuncDefNode
,
Nodes
.
CClassDefNode
,
Nodes
.
CVarDefNode
)):
if
realdecs
and
isinstance
(
node
,
(
Nodes
.
CFuncDefNode
,
Nodes
.
CClassDefNode
,
Nodes
.
CVarDefNode
)):
raise
PostParseError
(
realdecs
[
0
].
pos
,
"Cdef functions/classes cannot take arbitrary decorators."
)
raise
PostParseError
(
realdecs
[
0
].
pos
,
"Cdef functions/classes cannot take arbitrary decorators."
)
else
:
else
:
node
.
decorators
=
realdecs
node
.
decorators
=
realdecs
+
both
# merge or override repeated directives
# merge or override repeated directives
optdict
=
{}
optdict
=
{}
directives
.
reverse
()
# Decorators coming first take precedence
directives
.
reverse
()
# Decorators coming first take precedence
...
@@ -2261,8 +2273,8 @@ class MarkClosureVisitor(CythonTransform):
...
@@ -2261,8 +2273,8 @@ class MarkClosureVisitor(CythonTransform):
def
visit_CFuncDefNode
(
self
,
node
):
def
visit_CFuncDefNode
(
self
,
node
):
self
.
visit_FuncDefNode
(
node
)
self
.
visit_FuncDefNode
(
node
)
if
node
.
needs_closure
:
if
node
.
needs_closure
and
node
.
overridable
:
error
(
node
.
pos
,
"closures inside cdef functions not yet supported"
)
error
(
node
.
pos
,
"closures inside c
p
def functions not yet supported"
)
return
node
return
node
def
visit_LambdaNode
(
self
,
node
):
def
visit_LambdaNode
(
self
,
node
):
...
@@ -2401,8 +2413,11 @@ class CreateClosureClasses(CythonTransform):
...
@@ -2401,8 +2413,11 @@ class CreateClosureClasses(CythonTransform):
return
node
return
node
def
visit_CFuncDefNode
(
self
,
node
):
def
visit_CFuncDefNode
(
self
,
node
):
self
.
visitchildren
(
node
)
if
not
node
.
overridable
:
return
node
return
self
.
visit_FuncDefNode
(
node
)
else
:
self
.
visitchildren
(
node
)
return
node
class
GilCheck
(
VisitorTransform
):
class
GilCheck
(
VisitorTransform
):
...
@@ -2705,6 +2720,8 @@ class TransformBuiltinMethods(EnvTransform):
...
@@ -2705,6 +2720,8 @@ class TransformBuiltinMethods(EnvTransform):
node
.
cdivision
=
True
node
.
cdivision
=
True
elif
function
==
u'set'
:
elif
function
==
u'set'
:
node
.
function
=
ExprNodes
.
NameNode
(
node
.
pos
,
name
=
EncodedString
(
'set'
))
node
.
function
=
ExprNodes
.
NameNode
(
node
.
pos
,
name
=
EncodedString
(
'set'
))
elif
function
==
u'staticmethod'
:
node
.
function
=
ExprNodes
.
NameNode
(
node
.
pos
,
name
=
EncodedString
(
'staticmethod'
))
elif
self
.
context
.
cython_scope
.
lookup_qualified_name
(
function
):
elif
self
.
context
.
cython_scope
.
lookup_qualified_name
(
function
):
pass
pass
else
:
else
:
...
...
Cython/Compiler/Parsing.pxd
View file @
5302d443
...
@@ -187,3 +187,4 @@ cdef p_doc_string(PyrexScanner s)
...
@@ -187,3 +187,4 @@ cdef p_doc_string(PyrexScanner s)
cdef
p_ignorable_statement
(
PyrexScanner
s
)
cdef
p_ignorable_statement
(
PyrexScanner
s
)
cdef
p_compiler_directive_comments
(
PyrexScanner
s
)
cdef
p_compiler_directive_comments
(
PyrexScanner
s
)
cdef
p_cpp_class_definition
(
PyrexScanner
s
,
pos
,
ctx
)
cdef
p_cpp_class_definition
(
PyrexScanner
s
,
pos
,
ctx
)
cdef
p_cpp_class_attribute
(
PyrexScanner
s
,
ctx
)
Cython/Compiler/Parsing.py
View file @
5302d443
...
@@ -3231,12 +3231,8 @@ def p_cpp_class_definition(s, pos, ctx):
...
@@ -3231,12 +3231,8 @@ def p_cpp_class_definition(s, pos, ctx):
body_ctx
=
Ctx
(
visibility
=
ctx
.
visibility
,
level
=
'cpp_class'
,
nogil
=
nogil
or
ctx
.
nogil
)
body_ctx
=
Ctx
(
visibility
=
ctx
.
visibility
,
level
=
'cpp_class'
,
nogil
=
nogil
or
ctx
.
nogil
)
body_ctx
.
templates
=
templates
body_ctx
.
templates
=
templates
while
s
.
sy
!=
'DEDENT'
:
while
s
.
sy
!=
'DEDENT'
:
if
s
.
systring
==
'cppclass'
:
if
s
.
sy
!=
'pass'
:
attributes
.
append
(
attributes
.
append
(
p_cpp_class_attribute
(
s
,
body_ctx
))
p_cpp_class_definition
(
s
,
s
.
position
(),
body_ctx
))
elif
s
.
sy
!=
'pass'
:
attributes
.
append
(
p_c_func_or_var_declaration
(
s
,
s
.
position
(),
body_ctx
))
else
:
else
:
s
.
next
()
s
.
next
()
s
.
expect_newline
(
"Expected a newline"
)
s
.
expect_newline
(
"Expected a newline"
)
...
@@ -3253,6 +3249,23 @@ def p_cpp_class_definition(s, pos, ctx):
...
@@ -3253,6 +3249,23 @@ def p_cpp_class_definition(s, pos, ctx):
attributes
=
attributes
,
attributes
=
attributes
,
templates
=
templates
)
templates
=
templates
)
def
p_cpp_class_attribute
(
s
,
ctx
):
decorators
=
None
if
s
.
sy
==
'@'
:
decorators
=
p_decorators
(
s
)
if
s
.
systring
==
'cppclass'
:
return
p_cpp_class_definition
(
s
,
s
.
position
(),
ctx
)
else
:
node
=
p_c_func_or_var_declaration
(
s
,
s
.
position
(),
ctx
)
if
decorators
is
not
None
:
tup
=
Nodes
.
CFuncDefNode
,
Nodes
.
CVarDefNode
,
Nodes
.
CClassDefNode
if
ctx
.
allow_struct_enum_decorator
:
tup
+=
Nodes
.
CStructOrUnionDefNode
,
Nodes
.
CEnumDefNode
if
not
isinstance
(
node
,
tup
):
s
.
error
(
"Decorators can only be followed by functions or classes"
)
node
.
decorators
=
decorators
return
node
#----------------------------------------------
#----------------------------------------------
#
#
...
...
Cython/Compiler/PyrexTypes.py
View file @
5302d443
...
@@ -2315,6 +2315,7 @@ class CFuncType(CType):
...
@@ -2315,6 +2315,7 @@ class CFuncType(CType):
# is_strict_signature boolean function refuses to accept coerced arguments
# is_strict_signature boolean function refuses to accept coerced arguments
# (used for optimisation overrides)
# (used for optimisation overrides)
# is_const_method boolean
# is_const_method boolean
# is_static_method boolean
is_cfunction
=
1
is_cfunction
=
1
original_sig
=
None
original_sig
=
None
...
@@ -2327,7 +2328,8 @@ class CFuncType(CType):
...
@@ -2327,7 +2328,8 @@ class CFuncType(CType):
def
__init__
(
self
,
return_type
,
args
,
has_varargs
=
0
,
def
__init__
(
self
,
return_type
,
args
,
has_varargs
=
0
,
exception_value
=
None
,
exception_check
=
0
,
calling_convention
=
""
,
exception_value
=
None
,
exception_check
=
0
,
calling_convention
=
""
,
nogil
=
0
,
with_gil
=
0
,
is_overridable
=
0
,
optional_arg_count
=
0
,
nogil
=
0
,
with_gil
=
0
,
is_overridable
=
0
,
optional_arg_count
=
0
,
is_const_method
=
False
,
templates
=
None
,
is_strict_signature
=
False
):
is_const_method
=
False
,
is_static_method
=
False
,
templates
=
None
,
is_strict_signature
=
False
):
self
.
return_type
=
return_type
self
.
return_type
=
return_type
self
.
args
=
args
self
.
args
=
args
self
.
has_varargs
=
has_varargs
self
.
has_varargs
=
has_varargs
...
@@ -2339,6 +2341,7 @@ class CFuncType(CType):
...
@@ -2339,6 +2341,7 @@ class CFuncType(CType):
self
.
with_gil
=
with_gil
self
.
with_gil
=
with_gil
self
.
is_overridable
=
is_overridable
self
.
is_overridable
=
is_overridable
self
.
is_const_method
=
is_const_method
self
.
is_const_method
=
is_const_method
self
.
is_static_method
=
is_static_method
self
.
templates
=
templates
self
.
templates
=
templates
self
.
is_strict_signature
=
is_strict_signature
self
.
is_strict_signature
=
is_strict_signature
...
@@ -2563,6 +2566,7 @@ class CFuncType(CType):
...
@@ -2563,6 +2566,7 @@ class CFuncType(CType):
is_overridable
=
self
.
is_overridable
,
is_overridable
=
self
.
is_overridable
,
optional_arg_count
=
self
.
optional_arg_count
,
optional_arg_count
=
self
.
optional_arg_count
,
is_const_method
=
self
.
is_const_method
,
is_const_method
=
self
.
is_const_method
,
is_static_method
=
self
.
is_static_method
,
templates
=
self
.
templates
)
templates
=
self
.
templates
)
result
.
from_fused
=
self
.
is_fused
result
.
from_fused
=
self
.
is_fused
...
@@ -3106,7 +3110,7 @@ class CppClassType(CType):
...
@@ -3106,7 +3110,7 @@ class CppClassType(CType):
# Need to do these *after* self.specializations[key] is set
# Need to do these *after* self.specializations[key] is set
# to avoid infinite recursion on circular references.
# to avoid infinite recursion on circular references.
specialized
.
base_classes
=
[
b
.
specialize
(
values
)
for
b
in
self
.
base_classes
]
specialized
.
base_classes
=
[
b
.
specialize
(
values
)
for
b
in
self
.
base_classes
]
specialized
.
scope
=
self
.
scope
.
specialize
(
values
)
specialized
.
scope
=
self
.
scope
.
specialize
(
values
,
specialized
)
if
self
.
namespace
is
not
None
:
if
self
.
namespace
is
not
None
:
specialized
.
namespace
=
self
.
namespace
.
specialize
(
values
)
specialized
.
namespace
=
self
.
namespace
.
specialize
(
values
)
return
specialized
return
specialized
...
...
Cython/Compiler/Symtab.py
View file @
5302d443
...
@@ -1947,11 +1947,12 @@ class CClassScope(ClassScope):
...
@@ -1947,11 +1947,12 @@ class CClassScope(ClassScope):
if
get_special_method_signature
(
name
)
and
not
self
.
parent_type
.
is_builtin_type
:
if
get_special_method_signature
(
name
)
and
not
self
.
parent_type
.
is_builtin_type
:
error
(
pos
,
"Special methods must be declared with 'def', not 'cdef'"
)
error
(
pos
,
"Special methods must be declared with 'def', not 'cdef'"
)
args
=
type
.
args
args
=
type
.
args
if
not
args
:
if
not
type
.
is_static_method
:
error
(
pos
,
"C method has no self argument"
)
if
not
args
:
elif
not
self
.
parent_type
.
assignable_from
(
args
[
0
].
type
):
error
(
pos
,
"C method has no self argument"
)
error
(
pos
,
"Self argument (%s) of C method '%s' does not match parent type (%s)"
%
elif
not
self
.
parent_type
.
assignable_from
(
args
[
0
].
type
):
(
args
[
0
].
type
,
name
,
self
.
parent_type
))
error
(
pos
,
"Self argument (%s) of C method '%s' does not match parent type (%s)"
%
(
args
[
0
].
type
,
name
,
self
.
parent_type
))
entry
=
self
.
lookup_here
(
name
)
entry
=
self
.
lookup_here
(
name
)
if
cname
is
None
:
if
cname
is
None
:
cname
=
c_safe_identifier
(
name
)
cname
=
c_safe_identifier
(
name
)
...
@@ -2106,7 +2107,8 @@ class CppClassScope(Scope):
...
@@ -2106,7 +2107,8 @@ class CppClassScope(Scope):
entry
=
self
.
declare
(
name
,
cname
,
type
,
pos
,
visibility
)
entry
=
self
.
declare
(
name
,
cname
,
type
,
pos
,
visibility
)
entry
.
is_variable
=
1
entry
.
is_variable
=
1
if
type
.
is_cfunction
and
self
.
type
:
if
type
.
is_cfunction
and
self
.
type
:
entry
.
func_cname
=
"%s::%s"
%
(
self
.
type
.
declaration_code
(
""
),
cname
)
if
not
self
.
type
.
templates
or
not
any
(
T
.
is_fused
for
T
in
self
.
type
.
templates
):
entry
.
func_cname
=
"%s::%s"
%
(
self
.
type
.
declaration_code
(
""
),
cname
)
if
name
!=
"this"
and
(
defining
or
name
!=
"<init>"
):
if
name
!=
"this"
and
(
defining
or
name
!=
"<init>"
):
self
.
var_entries
.
append
(
entry
)
self
.
var_entries
.
append
(
entry
)
if
type
.
is_pyobject
and
not
allow_pyobject
:
if
type
.
is_pyobject
and
not
allow_pyobject
:
...
@@ -2189,8 +2191,9 @@ class CppClassScope(Scope):
...
@@ -2189,8 +2191,9 @@ class CppClassScope(Scope):
utility_code
=
base_entry
.
utility_code
)
utility_code
=
base_entry
.
utility_code
)
entry
.
is_inherited
=
1
entry
.
is_inherited
=
1
def
specialize
(
self
,
values
):
def
specialize
(
self
,
values
,
type_entry
):
scope
=
CppClassScope
(
self
.
name
,
self
.
outer_scope
)
scope
=
CppClassScope
(
self
.
name
,
self
.
outer_scope
)
scope
.
type
=
type_entry
for
entry
in
self
.
entries
.
values
():
for
entry
in
self
.
entries
.
values
():
if
entry
.
is_type
:
if
entry
.
is_type
:
scope
.
declare_type
(
entry
.
name
,
scope
.
declare_type
(
entry
.
name
,
...
...
Cython/Includes/libcpp/__init__.pxd
View file @
5302d443
# empty file
cdef
extern
from
*
:
cdef
extern
from
*
:
ctypedef
bint
bool
ctypedef
bint
bool
Cython/Includes/libcpp/cast.pxd
0 → 100644
View file @
5302d443
# Defines the standard C++ cast operators.
#
# Due to type restrictions, these are only defined for pointer parameters,
# however that is the only case where they are significantly more interesting
# than the standard C cast operator which can be written "<T>(expression)" in
# Cython.
cdef
extern
from
*
:
cdef
T
dynamic_cast
[
T
](
void
*
)
except
+
# nullptr may also indicate failure
cdef
T
static_cast
[
T
](
void
*
)
cdef
T
reinterpret_cast
[
T
](
void
*
)
cdef
T
const_cast
[
T
](
void
*
)
Cython/Plex/Scanners.pxd
View file @
5302d443
...
@@ -24,7 +24,7 @@ cdef class Scanner:
...
@@ -24,7 +24,7 @@ cdef class Scanner:
cdef
public
list
queue
cdef
public
list
queue
cdef
public
bint
trace
cdef
public
bint
trace
cdef
public
cur_char
cdef
public
cur_char
cdef
public
int
input_state
cdef
public
long
input_state
cdef
public
level
cdef
public
level
...
...
Cython/Utils.py
View file @
5302d443
...
@@ -399,3 +399,16 @@ def print_bytes(s, end=b'\n', file=sys.stdout, flush=True):
...
@@ -399,3 +399,16 @@ def print_bytes(s, end=b'\n', file=sys.stdout, flush=True):
out
.
write
(
end
)
out
.
write
(
end
)
if
flush
:
if
flush
:
out
.
flush
()
out
.
flush
()
class
LazyStr
:
def
__init__
(
self
,
callback
):
self
.
callback
=
callback
def
__str__
(
self
):
return
self
.
callback
()
def
__repr__
(
self
):
return
self
.
callback
()
def
__add__
(
self
,
right
):
return
self
.
callback
()
+
right
def
__radd__
(
self
,
left
):
return
left
+
self
.
callback
()
docs/src/userguide/extension_types.rst
View file @
5302d443
...
@@ -345,7 +345,7 @@ functions, C methods are declared using :keyword:`cdef` or :keyword:`cpdef` inst
...
@@ -345,7 +345,7 @@ functions, C methods are declared using :keyword:`cdef` or :keyword:`cpdef` inst
:keyword:`def`. C methods are "virtual", and may be overridden in derived
:keyword:`def`. C methods are "virtual", and may be overridden in derived
extension types. In addition, :keyword:`cpdef` methods can even be overridden by python
extension types. In addition, :keyword:`cpdef` methods can even be overridden by python
methods when called as C method. This adds a little to their calling overhead
methods when called as C method. This adds a little to their calling overhead
compared to a :keyword:`cdef` methd::
compared to a :keyword:`cdef` meth
o
d::
# pets.pyx
# pets.pyx
cdef class Parrot:
cdef class Parrot:
...
@@ -382,21 +382,29 @@ method using the usual Python technique, i.e.::
...
@@ -382,21 +382,29 @@ method using the usual Python technique, i.e.::
Parrot.describe(self)
Parrot.describe(self)
`cdef` methods can be declared static by using the @staticmethod decorator.
This can be especially useful for constructing classes that take non-Python
compatible types.::
Forward-declaring extension types
cdef class OwnedPointer:
===================================
cdef void* ptr
Extension types can be forward-declared, like :keyword:`struct` and
cdef __dealloc__(self):
:keyword:`union` types. This will be necessary if you have two extension types
if ptr != NULL:
that need to refer to each other, e.g.::
free(ptr)
cdef class Shrubbery # forward declaration
@staticmethod
cdef create(void* ptr):
p = OwnedPointer()
p.ptr = ptr
return ptr
cdef class Shrubber:
cdef Shrubbery work_in_progress
cdef class Shrubbery:
Forward-declaring extension types
cdef Shrubber creator
===================================
Extension types can be forward-declared, like :keyword:`struct` and
:keyword:`union` types. This is usually necessary.
If you are forward-declaring an extension type that has a base class, you must
If you are forward-declaring an extension type that has a base class, you must
specify the base class in both the forward declaration and its subsequent
specify the base class in both the forward declaration and its subsequent
...
...
docs/src/userguide/wrapping_CPlusPlus.rst
View file @
5302d443
...
@@ -529,9 +529,10 @@ If the Rectangle class has a static member:
...
@@ -529,9 +529,10 @@ If the Rectangle class has a static member:
};
};
}
}
you can declare it
as a function living in the class namespace
, i.e.::
you can declare it
using the Python @staticmethod decorator
, i.e.::
cdef extern from "Rectangle.h" namespace "shapes::Rectangle":
cdef extern from "Rectangle.h" namespace "shapes":
@staticmethod
void do_something()
void do_something()
...
...
runtests.py
View file @
5302d443
...
@@ -115,6 +115,77 @@ def unpatch_inspect_isfunction():
...
@@ -115,6 +115,77 @@ def unpatch_inspect_isfunction():
else
:
else
:
inspect
.
isfunction
=
orig_isfunction
inspect
.
isfunction
=
orig_isfunction
def
def_to_cdef
(
source
):
'''
Converts the module-level def methods into cdef methods, i.e.
@decorator
def foo([args]):
"""
[tests]
"""
[body]
becomes
def foo([args]):
"""
[tests]
"""
return foo_c([args])
cdef foo_c([args]):
[body]
'''
output
=
[]
skip
=
False
def_node
=
re
.
compile
(
r'def (\
w+)
\(([^()*]*)\
):
').match
lines = iter(source.split('
\
n
'))
for line in lines:
if not line.strip():
output.append(line)
continue
if skip:
if line[0] != '
':
skip = False
else:
continue
if line[0] == '
@
':
skip = True
continue
m = def_node(line)
if m:
name = m.group(1)
args = m.group(2)
if args:
args_no_types = ", ".join(arg.split()[-1] for arg in args.split('
,
'))
else:
args_no_types = ""
output.append("def %s(%s):" % (name, args_no_types))
line = next(lines)
if '"""' in line:
has_docstring = True
output.append(line)
for line in lines:
output.append(line)
if '"""' in line:
break
else:
has_docstring = False
output.append(" return %s_c(%s)" % (name, args_no_types))
output.append('')
output.append("cdef %s_c(%s):" % (name, args))
if not has_docstring:
output.append(line)
else:
output.append(line)
return '
\
n
'.join(output)
def update_linetrace_extension(ext):
def update_linetrace_extension(ext):
ext.define_macros.append(('
CYTHON_TRACE
', 1))
ext.define_macros.append(('
CYTHON_TRACE
', 1))
return ext
return ext
...
@@ -331,7 +402,7 @@ def parse_tags(filepath):
...
@@ -331,7 +402,7 @@ def parse_tags(filepath):
if tag == 'tags':
if tag == 'tags':
tag = 'tag'
tag = 'tag'
print("WARNING: test tags use the 'tag' directive, not 'tags' (%s)" % filepath)
print("WARNING: test tags use the 'tag' directive, not 'tags' (%s)" % filepath)
if tag not in ('mode', 'tag', 'ticket', 'cython', 'distutils'):
if tag not in ('mode', 'tag', 'ticket', 'cython', 'distutils'
, 'preparse'
):
print("WARNING: unknown test directive '%s' found (%s)" % (tag, filepath))
print("WARNING: unknown test directive '%s' found (%s)" % (tag, filepath))
values = values.split(',')
values = values.split(',')
tags[tag].extend(filter(None, [value.strip() for value in values]))
tags[tag].extend(filter(None, [value.strip() for value in values]))
...
@@ -532,19 +603,25 @@ class TestBuilder(object):
...
@@ -532,19 +603,25 @@ class TestBuilder(object):
elif 'no-cpp' in tags['tag'] and 'cpp' in self.languages:
elif 'no-cpp' in tags['tag'] and 'cpp' in self.languages:
languages = list(languages)
languages = list(languages)
languages.remove('cpp')
languages.remove('cpp')
preparse_list = tags.get('preparse', ['id'])
tests = [ self.build_test(test_class, path, workdir, module, tags,
tests = [ self.build_test(test_class, path, workdir, module, tags,
language, expect_errors, warning_errors)
language, expect_errors, warning_errors, preparse)
for language in languages ]
for language in languages
for preparse in preparse_list ]
return tests
return tests
def build_test(self, test_class, path, workdir, module, tags,
def build_test(self, test_class, path, workdir, module, tags,
language, expect_errors, warning_errors):
language, expect_errors, warning_errors
, preparse
):
language_workdir = os.path.join(workdir, language)
language_workdir = os.path.join(workdir, language)
if not os.path.exists(language_workdir):
if not os.path.exists(language_workdir):
os.makedirs(language_workdir)
os.makedirs(language_workdir)
workdir = os.path.join(language_workdir, module)
workdir = os.path.join(language_workdir, module)
if preparse != 'id':
workdir += '_%s' % str(preparse)
return test_class(path, workdir, module, tags,
return test_class(path, workdir, module, tags,
language=language,
language=language,
preparse=preparse,
expect_errors=expect_errors,
expect_errors=expect_errors,
annotate=self.annotate,
annotate=self.annotate,
cleanup_workdir=self.cleanup_workdir,
cleanup_workdir=self.cleanup_workdir,
...
@@ -556,7 +633,7 @@ class TestBuilder(object):
...
@@ -556,7 +633,7 @@ class TestBuilder(object):
warning_errors=warning_errors)
warning_errors=warning_errors)
class CythonCompileTestCase(unittest.TestCase):
class CythonCompileTestCase(unittest.TestCase):
def __init__(self, test_directory, workdir, module, tags, language='c',
def __init__(self, test_directory, workdir, module, tags, language='c',
preparse='id',
expect_errors=False, annotate=False, cleanup_workdir=True,
expect_errors=False, annotate=False, cleanup_workdir=True,
cleanup_sharedlibs=True, cleanup_failures=True, cython_only=False,
cleanup_sharedlibs=True, cleanup_failures=True, cython_only=False,
fork=True, language_level=2, warning_errors=False):
fork=True, language_level=2, warning_errors=False):
...
@@ -565,6 +642,8 @@ class CythonCompileTestCase(unittest.TestCase):
...
@@ -565,6 +642,8 @@ class CythonCompileTestCase(unittest.TestCase):
self.workdir = workdir
self.workdir = workdir
self.module = module
self.module = module
self.language = language
self.language = language
self.preparse = preparse
self.name = module if self.preparse == "id" else "%s_%s" % (module, preparse)
self.expect_errors = expect_errors
self.expect_errors = expect_errors
self.annotate = annotate
self.annotate = annotate
self.cleanup_workdir = cleanup_workdir
self.cleanup_workdir = cleanup_workdir
...
@@ -577,7 +656,7 @@ class CythonCompileTestCase(unittest.TestCase):
...
@@ -577,7 +656,7 @@ class CythonCompileTestCase(unittest.TestCase):
unittest.TestCase.__init__(self)
unittest.TestCase.__init__(self)
def shortDescription(self):
def shortDescription(self):
return "
compiling
(
%
s
)
%
s
" % (self.language, self.
modul
e)
return "compiling (%s) %s" % (self.language, self.
nam
e)
def setUp(self):
def setUp(self):
from Cython.Compiler import Options
from Cython.Compiler import Options
...
@@ -660,11 +739,16 @@ class CythonCompileTestCase(unittest.TestCase):
...
@@ -660,11 +739,16 @@ class CythonCompileTestCase(unittest.TestCase):
if is_related(filename)]
if is_related(filename)]
def copy_files(self, test_directory, target_directory, file_list):
def copy_files(self, test_directory, target_directory, file_list):
# use symlink on Unix, copy on Windows
if self.preparse and self.preparse != 'id':
try:
preparse_func = globals()[self.preparse]
copy = os.symlink
def copy(src, dest):
except AttributeError:
open(dest, 'w').write(preparse_func(open(src).read()))
copy = shutil.copy
else:
# use symlink on Unix, copy on Windows
try:
copy = os.symlink
except AttributeError:
copy = shutil.copy
join = os.path.join
join = os.path.join
for filename in file_list:
for filename in file_list:
...
@@ -707,6 +791,12 @@ class CythonCompileTestCase(unittest.TestCase):
...
@@ -707,6 +791,12 @@ class CythonCompileTestCase(unittest.TestCase):
include_dirs.append(incdir)
include_dirs.append(incdir)
source = self.find_module_source_file(
source = self.find_module_source_file(
os.path.join(test_directory, module + '.pyx'))
os.path.join(test_directory, module + '.pyx'))
if self.preparse == 'id':
source = self.find_module_source_file(
os.path.join(test_directory, module + '.pyx'))
else:
self.copy_files(test_directory, targetdir, [module + '.pyx'])
source = os.path.join(targetdir, module + '.pyx')
target = os.path.join(targetdir, self.build_target_filename(module))
target = os.path.join(targetdir, self.build_target_filename(module))
if extra_compile_options is None:
if extra_compile_options is None:
...
@@ -903,7 +993,7 @@ class CythonRunTestCase(CythonCompileTestCase):
...
@@ -903,7 +993,7 @@ class CythonRunTestCase(CythonCompileTestCase):
if self.cython_only:
if self.cython_only:
return CythonCompileTestCase.shortDescription(self)
return CythonCompileTestCase.shortDescription(self)
else:
else:
return "
compiling
(
%
s
)
and
running
%
s
" % (self.language, self.
modul
e)
return "compiling (%s) and running %s" % (self.language, self.
nam
e)
def run(self, result=None):
def run(self, result=None):
if result is None:
if result is None:
...
@@ -1105,7 +1195,7 @@ class PartialTestResult(_TextTestResult):
...
@@ -1105,7 +1195,7 @@ class PartialTestResult(_TextTestResult):
class CythonUnitTestCase(CythonRunTestCase):
class CythonUnitTestCase(CythonRunTestCase):
def shortDescription(self):
def shortDescription(self):
return "
compiling
(
%
s
)
tests
in
%
s
" % (self.language, self.
modul
e)
return "compiling (%s) tests in %s" % (self.language, self.
nam
e)
def run_tests(self, result, ext_so_path):
def run_tests(self, result, ext_so_path):
module = import_ext(self.module, ext_so_path)
module = import_ext(self.module, ext_so_path)
...
...
tests/bugs.txt
View file @
5302d443
...
@@ -6,7 +6,6 @@ unsignedbehaviour_T184
...
@@ -6,7 +6,6 @@ unsignedbehaviour_T184
missing_baseclass_in_predecl_T262
missing_baseclass_in_predecl_T262
cfunc_call_tuple_args_T408
cfunc_call_tuple_args_T408
cpp_structs
cpp_structs
closure_inside_cdef_T554
genexpr_iterable_lookup_T600
genexpr_iterable_lookup_T600
generator_expressions_in_class
generator_expressions_in_class
for_from_pyvar_loop_T601
for_from_pyvar_loop_T601
...
...
tests/compile/builtinfuncs.pyx
View file @
5302d443
...
@@ -5,18 +5,20 @@ cdef int f() except -1:
...
@@ -5,18 +5,20 @@ cdef int f() except -1:
cdef
str
sstring
cdef
str
sstring
cdef
basestring
sustring
cdef
basestring
sustring
cdef
int
i
cdef
int
i
cdef
long
lng
cdef
Py_ssize_t
s
x
=
abs
(
y
)
x
=
abs
(
y
)
delattr
(
x
,
'spam'
)
delattr
(
x
,
'spam'
)
x
=
dir
(
y
)
x
=
dir
(
y
)
x
=
divmod
(
y
,
z
)
x
=
divmod
(
y
,
z
)
x
=
getattr
(
y
,
'spam'
)
x
=
getattr
(
y
,
'spam'
)
i
=
hasattr
(
y
,
'spam'
)
i
=
hasattr
(
y
,
'spam'
)
i
=
hash
(
y
)
lng
=
hash
(
y
)
x
=
intern
(
y
)
x
=
intern
(
y
)
i
=
isinstance
(
y
,
z
)
i
=
isinstance
(
y
,
z
)
i
=
issubclass
(
y
,
z
)
i
=
issubclass
(
y
,
z
)
x
=
iter
(
y
)
x
=
iter
(
y
)
i
=
len
(
x
)
s
=
len
(
x
)
x
=
open
(
y
,
z
)
x
=
open
(
y
,
z
)
x
=
pow
(
y
,
z
,
w
)
x
=
pow
(
y
,
z
,
w
)
x
=
pow
(
y
,
z
)
x
=
pow
(
y
,
z
)
...
...
tests/errors/e_cdef_closure.pyx
View file @
5302d443
# mode: error
# mode: error
cdef
cdef
_yield
():
def
inner
():
pass
cpdef
cpdef
_yield
():
cpdef
cpdef
_yield
():
def
inner
():
def
inner
():
pass
pass
_ERRORS
=
u"""
_ERRORS
=
u"""
3:5: closures inside cdef functions not yet supported
3:6: closures inside cpdef functions not yet supported
7:6: closures inside cdef functions not yet supported
"""
"""
tests/run/closure_self.pyx
View file @
5302d443
...
@@ -38,3 +38,19 @@ cdef class SelfInClosure(object):
...
@@ -38,3 +38,19 @@ cdef class SelfInClosure(object):
def
nested
():
def
nested
():
return
self
.
x
,
t
.
x
return
self
.
x
,
t
.
x
return
nested
return
nested
def
call_closure_method_cdef_attr_c
(
self
,
Test
t
):
"""
>>> o = SelfInClosure()
>>> o.call_closure_method_cdef_attr_c(Test())()
(1, 2)
"""
return
self
.
closure_method_cdef_attr_c
(
t
)
cdef
closure_method_cdef_attr_c
(
self
,
Test
t
):
t
.
x
=
2
self
.
_t
=
t
self
.
x
=
1
def
nested
():
return
self
.
x
,
t
.
x
return
nested
tests/run/closure_tests_1.pyx
View file @
5302d443
# mode: run
# mode: run
# tag: closures
# tag: closures
# preparse: id
# preparse: def_to_cdef
#
#
# closure_tests_1.pyx
# closure_tests_1.pyx
#
#
...
...
tests/run/closure_tests_2.pyx
View file @
5302d443
# mode: run
# mode: run
# tag: closures
# tag: closures
# preparse: id
# preparse: def_to_cdef
#
#
# closure_tests_2.pyx
# closure_tests_2.pyx
#
#
...
...
tests/run/closure_tests_3.pyx
View file @
5302d443
# mode: run
# mode: run
# tag: closures
# tag: closures
# preparse: id
# preparse: def_to_cdef
#
#
# closure_tests_3.pyx
# closure_tests_3.pyx
#
#
...
...
tests/run/closure_tests_4.pyx
View file @
5302d443
# mode: run
# mode: run
# tag: closures
# tag: closures
# preparse: id
# preparse: def_to_cdef
#
#
# closure_tests_4.pyx
# closure_tests_4.pyx
#
#
...
...
tests/run/closures_T82.pyx
View file @
5302d443
# mode: run
# mode: run
# tag: closures
# tag: closures
# ticket: 82
# ticket: 82
# preparse: id
# preparse: def_to_cdef
cimport
cython
cimport
cython
...
...
tests/run/cpp_classes_def.pyx
View file @
5302d443
...
@@ -42,6 +42,21 @@ def test_Poly(int n, float radius=1):
...
@@ -42,6 +42,21 @@ def test_Poly(int n, float radius=1):
del
poly
del
poly
cdef
cppclass
WithStatic
:
@
staticmethod
double
square
(
double
x
):
return
x
*
x
def
test_Static
(
x
):
"""
>>> test_Static(2)
4.0
>>> test_Static(0.5)
0.25
"""
return
WithStatic
.
square
(
x
)
cdef
cppclass
InitDealloc
:
cdef
cppclass
InitDealloc
:
__init__
():
__init__
():
print
"Init"
print
"Init"
...
...
tests/run/cpp_templates.pyx
View file @
5302d443
...
@@ -22,6 +22,10 @@ cdef extern from "cpp_templates_helper.h":
...
@@ -22,6 +22,10 @@ cdef extern from "cpp_templates_helper.h":
cdef
cppclass
SubClass
[
T2
,
T3
](
SuperClass
[
T2
,
T3
]):
cdef
cppclass
SubClass
[
T2
,
T3
](
SuperClass
[
T2
,
T3
]):
pass
pass
cdef
cppclass
Div
[
T
]:
@
staticmethod
T
half
(
T
value
)
def
test_int
(
int
x
,
int
y
):
def
test_int
(
int
x
,
int
y
):
"""
"""
>>> test_int(3, 4)
>>> test_int(3, 4)
...
@@ -104,3 +108,12 @@ def test_cast_template_pointer():
...
@@ -104,3 +108,12 @@ def test_cast_template_pointer():
sup
=
sub
sup
=
sub
sup
=
<
SubClass
[
int
,
float
]
*>
sub
sup
=
<
SubClass
[
int
,
float
]
*>
sub
def
test_static
(
x
):
"""
>>> test_static(2)
(1, 1.0)
>>> test_static(3)
(1, 1.5)
"""
return
Div
[
int
].
half
(
x
),
Div
[
double
].
half
(
x
)
tests/run/cpp_templates_helper.h
View file @
5302d443
...
@@ -30,3 +30,9 @@ public:
...
@@ -30,3 +30,9 @@ public:
template
<
class
T2
,
class
T3
>
template
<
class
T2
,
class
T3
>
class
SubClass
:
public
SuperClass
<
T2
,
T3
>
{
class
SubClass
:
public
SuperClass
<
T2
,
T3
>
{
};
};
template
<
class
T
>
class
Div
{
public:
static
T
half
(
T
value
)
{
return
value
/
2
;
}
};
tests/run/py2_super.pyx
0 → 100644
View file @
5302d443
# mode: run
# tag: py3k_super
class
A
(
object
):
def
method
(
self
):
return
1
@
classmethod
def
class_method
(
cls
):
return
2
@
staticmethod
def
static_method
():
return
3
def
generator_test
(
self
):
return
[
1
,
2
,
3
]
class
B
(
A
):
"""
>>> obj = B()
>>> obj.method()
1
>>> B.class_method()
2
>>> B.static_method(obj)
3
>>> list(obj.generator_test())
[1, 2, 3]
"""
def
method
(
self
):
return
super
(
B
,
self
).
method
()
@
classmethod
def
class_method
(
cls
):
return
super
(
B
,
cls
).
class_method
()
@
staticmethod
def
static_method
(
instance
):
return
super
(
B
,
instance
).
static_method
()
def
generator_test
(
self
):
for
i
in
super
(
B
,
self
).
generator_test
():
yield
i
cdef
class
CClassBase
(
object
):
def
method
(
self
):
return
'def'
cpdef
method_cp
(
self
):
return
'cpdef'
# cdef method_c(self):
# return 'cdef'
# def call_method_c(self):
# return self.method_c()
cdef
class
CClassSub
(
CClassBase
):
"""
>>> CClassSub().method()
'def'
>>> CClassSub().method_cp()
'cpdef'
"""
# >>> CClassSub().call_method_c()
# 'cdef'
def
method
(
self
):
return
super
(
CClassSub
,
self
).
method
()
cpdef
method_cp
(
self
):
return
super
(
CClassSub
,
self
).
method_cp
()
# cdef method_c(self):
# return super(CClassSub, self).method_c()
cdef
class
Base
(
object
):
"""
>>> Base().method()
'Base'
>>> Base.method(Base())
'Base'
"""
cpdef
method
(
self
):
return
"Base"
cdef
class
Sub
(
Base
):
"""
>>> Sub().method()
'Sub'
>>> Sub.method(Sub())
'Sub'
>>> Base.method(Sub())
'Base'
"""
cpdef
method
(
self
):
return
"Sub"
tests/run/py3k_super.pyx
View file @
5302d443
...
@@ -63,13 +63,29 @@ def test_class_cell_empty():
...
@@ -63,13 +63,29 @@ def test_class_cell_empty():
cdef
class
CClassBase
(
object
):
cdef
class
CClassBase
(
object
):
def
method
(
self
):
def
method
(
self
):
return
1
return
'def'
# cpdef method_cp(self):
# return 'cpdef'
# cdef method_c(self):
# return 'cdef'
# def call_method_c(self):
# return self.method_c()
cdef
class
CClassSu
per
(
CClassBase
):
cdef
class
CClassSu
b
(
CClassBase
):
"""
"""
>>> CClassSu
per
().method()
>>> CClassSu
b
().method()
1
'def'
"""
"""
# >>> CClassSub().method_cp()
# 'cpdef'
# >>> CClassSub().call_method_c()
# 'cdef'
def
method
(
self
):
def
method
(
self
):
return
super
().
method
()
return
super
().
method
()
# cpdef method_cp(self):
# return super().method_cp()
# cdef method_c(self):
# return super().method_c()
tests/run/static_methods.pyx
0 → 100644
View file @
5302d443
cdef
class
A
:
@
staticmethod
def
static_def
(
int
x
):
"""
>>> A.static_def(2)
('def', 2)
>>> A().static_def(2)
('def', 2)
"""
return
'def'
,
x
@
staticmethod
cdef
static_cdef
(
int
*
x
):
return
'cdef'
,
x
[
0
]
# @staticmethod
# cpdef static_cpdef(int x):
# """
# >>> A.static_def
# >>> A.static_cpdef
#
# >>> A().static_def
# >>> A().static_cpdef
#
# >>> A.static_cpdef(2)
# ('cpdef', 2)
# >>> A().static_cpdef(2)
# ('cpdef', 2)
# """
# return 'cpdef', x
def
call_static_def
(
int
x
):
"""
>>> call_static_def(2)
('def', 2)
"""
return
A
.
static_def
(
x
)
def
call_static_cdef
(
int
x
):
"""
>>> call_static_cdef(2)
('cdef', 2)
"""
cdef
int
*
x_ptr
=
&
x
return
A
.
static_cdef
(
x_ptr
)
# def call_static_cpdef(int x):
# """
# >>> call_static_cpdef(2)
# ('cpdef', 2)
# """
# return A.static_cpdef(x)
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