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
Kirill Smelkov
cython
Commits
67290dbb
Commit
67290dbb
authored
Jul 15, 2014
by
Robert Bradshaw
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'static'
parents
9610ed34
49d90c94
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
155 additions
and
37 deletions
+155
-37
CHANGES.rst
CHANGES.rst
+24
-14
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+19
-8
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+37
-6
Cython/Compiler/Options.py
Cython/Compiler/Options.py
+2
-0
Cython/Compiler/ParseTreeTransforms.py
Cython/Compiler/ParseTreeTransforms.py
+10
-3
Cython/Compiler/PyrexTypes.py
Cython/Compiler/PyrexTypes.py
+5
-1
Cython/Compiler/Symtab.py
Cython/Compiler/Symtab.py
+6
-5
tests/run/static_methods.pyx
tests/run/static_methods.pyx
+52
-0
No files found.
CHANGES.rst
View file @
67290dbb
...
@@ -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``.
...
@@ -58,6 +47,27 @@ Features added
...
@@ -58,6 +47,27 @@ Features added
* Defines dynamic_cast et al. in `libcpp.cast`.
* 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
----------
----------
...
...
Cython/Compiler/ExprNodes.py
View file @
67290dbb
...
@@ -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
:
...
@@ -5316,10 +5324,13 @@ class AttributeNode(ExprNode):
...
@@ -5316,10 +5324,13 @@ class AttributeNode(ExprNode):
# as an ordinary function.
# as an ordinary function.
if
entry
.
func_cname
and
not
hasattr
(
entry
.
type
,
'op_arg_struct'
):
if
entry
.
func_cname
and
not
hasattr
(
entry
.
type
,
'op_arg_struct'
):
cname
=
entry
.
func_cname
cname
=
entry
.
func_cname
# Fix self type.
if
entry
.
type
.
is_static_method
:
ctype
=
copy
.
copy
(
entry
.
type
)
ctype
=
entry
.
type
ctype
.
args
=
ctype
.
args
[:]
else
:
ctype
.
args
[
0
]
=
PyrexTypes
.
CFuncTypeArg
(
'self'
,
type
,
'self'
,
None
)
# Fix self type.
ctype
=
copy
.
copy
(
entry
.
type
)
ctype
.
args
=
ctype
.
args
[:]
ctype
.
args
[
0
]
=
PyrexTypes
.
CFuncTypeArg
(
'self'
,
type
,
'self'
,
None
)
else
:
else
:
cname
=
"%s->%s"
%
(
type
.
vtabptr_cname
,
entry
.
cname
)
cname
=
"%s->%s"
%
(
type
.
vtabptr_cname
,
entry
.
cname
)
ctype
=
entry
.
type
ctype
=
entry
.
type
...
...
Cython/Compiler/Nodes.py
View file @
67290dbb
...
@@ -617,7 +617,7 @@ class CFuncDeclaratorNode(CDeclaratorNode):
...
@@ -617,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
]
...
@@ -2143,10 +2143,11 @@ class CFuncDefNode(FuncDefNode):
...
@@ -2143,10 +2143,11 @@ class CFuncDefNode(FuncDefNode):
# overridable whether or not this is a cpdef function
# overridable whether or not this is a cpdef function
# 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
# 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
...
@@ -2155,6 +2156,7 @@ class CFuncDefNode(FuncDefNode):
...
@@ -2155,6 +2156,7 @@ 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
...
@@ -2171,6 +2173,7 @@ class CFuncDefNode(FuncDefNode):
...
@@ -2171,6 +2173,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
,
...
@@ -2232,6 +2235,7 @@ class CFuncDefNode(FuncDefNode):
...
@@ -2232,6 +2235,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
,
...
@@ -2244,7 +2248,7 @@ class CFuncDefNode(FuncDefNode):
...
@@ -2244,7 +2248,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
...
@@ -2254,8 +2258,17 @@ class CFuncDefNode(FuncDefNode):
...
@@ -2254,8 +2258,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
,
...
@@ -2263,9 +2276,12 @@ class CFuncDefNode(FuncDefNode):
...
@@ -2263,9 +2276,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
...
@@ -2296,6 +2312,16 @@ class CFuncDefNode(FuncDefNode):
...
@@ -2296,6 +2312,16 @@ 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
:
type_entry
=
self
.
type
.
args
[
0
].
type
.
entry
type_entry
=
self
.
type
.
args
[
0
].
type
.
entry
type_arg
=
ExprNodes
.
NameNode
(
self
.
pos
,
name
=
type_entry
.
name
)
type_arg
=
ExprNodes
.
NameNode
(
self
.
pos
,
name
=
type_entry
.
name
)
...
@@ -2446,6 +2472,11 @@ class CFuncDefNode(FuncDefNode):
...
@@ -2446,6 +2472,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"
...
@@ -2901,10 +2932,10 @@ class DefNode(FuncDefNode):
...
@@ -2901,10 +2932,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 @
67290dbb
...
@@ -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 @
67290dbb
...
@@ -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
):
...
@@ -979,18 +979,23 @@ class InterpretCompilerDirectives(CythonTransform, SkipDeclarations):
...
@@ -979,18 +979,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
...
@@ -2708,6 +2713,8 @@ class TransformBuiltinMethods(EnvTransform):
...
@@ -2708,6 +2713,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/PyrexTypes.py
View file @
67290dbb
...
@@ -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
...
...
Cython/Compiler/Symtab.py
View file @
67290dbb
...
@@ -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
)
...
...
tests/run/static_methods.pyx
0 → 100644
View file @
67290dbb
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