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
ab8b5f9d
Commit
ab8b5f9d
authored
Jul 18, 2011
by
Mark Florisson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Cython Utility Code cname extclass decorator + extmethod prototypes
parent
0daf7250
Changes
12
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
394 additions
and
87 deletions
+394
-87
Cython/Compiler/CythonScope.py
Cython/Compiler/CythonScope.py
+70
-22
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+7
-4
Cython/Compiler/Main.py
Cython/Compiler/Main.py
+5
-2
Cython/Compiler/ModuleNode.py
Cython/Compiler/ModuleNode.py
+41
-32
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+55
-2
Cython/Compiler/ParseTreeTransforms.py
Cython/Compiler/ParseTreeTransforms.py
+7
-11
Cython/Compiler/Pipeline.py
Cython/Compiler/Pipeline.py
+2
-0
Cython/Compiler/Scanning.py
Cython/Compiler/Scanning.py
+4
-2
Cython/Compiler/Symtab.py
Cython/Compiler/Symtab.py
+18
-5
Cython/Compiler/TreeFragment.py
Cython/Compiler/TreeFragment.py
+2
-1
Cython/Compiler/UtilityCode.py
Cython/Compiler/UtilityCode.py
+72
-6
tests/run/cythonscope.pyx
tests/run/cythonscope.pyx
+111
-0
No files found.
Cython/Compiler/CythonScope.py
View file @
ab8b5f9d
...
@@ -63,20 +63,14 @@ class CythonScope(ModuleScope):
...
@@ -63,20 +63,14 @@ class CythonScope(ModuleScope):
defining
=
1
,
defining
=
1
,
cname
=
'PyObject_TypeCheck'
)
cname
=
'PyObject_TypeCheck'
)
self
.
test_cythonscope
()
#
self.test_cythonscope()
def
test_cythonscope
(
self
):
def
test_cythonscope
(
self
):
# A special function just to make it easy to test the scope and
# A special function just to make it easy to test the scope and
# utility code functionality in isolation. It is available to
# utility code functionality in isolation. It is available to
# "end-users" but nobody will know it is there anyway...
# "end-users" but nobody will know it is there anyway...
entry
=
self
.
declare_cfunction
(
cython_testscope_utility_code
.
declare_in_scope
(
self
)
'_testscope'
,
cython_test_extclass_utility_code
.
declare_in_scope
(
self
)
CFuncType
(
py_object_type
,
[
CFuncTypeArg
(
"value"
,
c_int_type
,
None
)]),
pos
=
None
,
defining
=
1
,
cname
=
'__pyx_testscope'
)
entry
.
utility_code_definition
=
cython_testscope_utility_code
#
#
# The view sub-scope
# The view sub-scope
...
@@ -85,29 +79,83 @@ class CythonScope(ModuleScope):
...
@@ -85,29 +79,83 @@ class CythonScope(ModuleScope):
self
.
declare_module
(
'view'
,
viewscope
,
None
)
self
.
declare_module
(
'view'
,
viewscope
,
None
)
viewscope
.
is_cython_builtin
=
True
viewscope
.
is_cython_builtin
=
True
viewscope
.
pxd_file_loaded
=
True
viewscope
.
pxd_file_loaded
=
True
entry
=
viewscope
.
declare_cfunction
(
'_testscope'
,
cythonview_testscope_utility_code
.
declare_in_scope
(
viewscope
)
CFuncType
(
py_object_type
,
[
CFuncTypeArg
(
"value"
,
c_int_type
,
None
)]),
pos
=
None
,
defining
=
1
,
def
create_cython_scope
(
context
,
create_testscope
):
cname
=
'__pyx_view_testscope'
)
entry
.
utility_code_definition
=
cythonview_testscope_utility_code
def
create_cython_scope
(
context
):
# One could in fact probably make it a singleton,
# One could in fact probably make it a singleton,
# but not sure yet whether any code mutates it (which would kill reusing
# but not sure yet whether any code mutates it (which would kill reusing
# it across different contexts)
# it across different contexts)
return
CythonScope
()
scope
=
CythonScope
()
if
create_testscope
:
scope
.
test_cythonscope
()
return
scope
cython_testscope_utility_code
=
CythonUtilityCode
(
u"""
cython_testscope_utility_code
=
CythonUtilityCode
(
u"""
@cname('__pyx_testscope')
@cname('__pyx_testscope')
cdef object _testscope(int value):
cdef object _testscope(int value):
return "hello from cython scope, value=%d" % value
return "hello from cython scope, value=%d" % value
"""
)
# #, name="cython utility code", prefix="__pyx_cython_")
"""
)
undecorated_methods_protos
=
UtilityCode
(
proto
=
u"""
/* These methods are undecorated and have therefore no prototype */
static PyObject *__pyx_TestClass_cdef_method(
struct __pyx_TestClass *self, int value);
static PyObject *__pyx_TestClass_cpdef_method(
struct __pyx_TestClass *self, int value, int skip_dispatch);
static PyObject *__pyx_TestClass_def_method(
PyObject *self, PyObject *value);
"""
)
cython_test_extclass_utility_code
=
CythonUtilityCode
(
name
=
"TestClassUtilityCode"
,
prefix
=
"__pyx_prefix_TestClass_"
,
requires
=
[
undecorated_methods_protos
],
impl
=
u"""
@cname('__pyx_TestClass')
cdef class TestClass(object):
cdef public int value
def __init__(self, int value):
self.value = value
def __str__(self):
return 'TestClass(%d)' % self.value
cdef cdef_method(self, int value):
print 'Hello from cdef_method', value
cpdef cpdef_method(self, int value):
print 'Hello from cpdef_method', value
def def_method(self, int value):
print 'Hello from def_method', value
@cname('cdef_cname')
cdef cdef_cname_method(self, int value):
print "Hello from cdef_cname_method", value
@cname('cpdef_cname')
cpdef cpdef_cname_method(self, int value):
print "Hello from cpdef_cname_method", value
@cname('def_cname')
def def_cname_method(self, int value):
print "Hello from def_cname_method", value
@cname('__pyx_TestClass_New')
cdef _testclass_new(int value):
return TestClass(value)
"""
)
cythonview_testscope_utility_code
=
CythonUtilityCode
(
u"""
cythonview_testscope_utility_code
=
CythonUtilityCode
(
u"""
@cname('__pyx_view_testscope')
@cname('__pyx_view_testscope')
cdef object _testscope(int value):
cdef object _testscope(int value):
return "hello from cython.view scope, value=%d" % value
return "hello from cython.view scope, value=%d" % value
"""
)
#, name="cython utility code", prefix="__pyx_cython_view_")
"""
)
Cython/Compiler/ExprNodes.py
View file @
ab8b5f9d
...
@@ -3615,10 +3615,13 @@ class AttributeNode(ExprNode):
...
@@ -3615,10 +3615,13 @@ class AttributeNode(ExprNode):
def
analyse_types
(
self
,
env
,
target
=
0
):
def
analyse_types
(
self
,
env
,
target
=
0
):
if
self
.
analyse_as_cimported_attribute
(
env
,
target
):
if
self
.
analyse_as_cimported_attribute
(
env
,
target
):
return
self
.
entry
.
used
=
True
if
not
target
and
self
.
analyse_as_unbound_cmethod
(
env
):
elif
not
target
and
self
.
analyse_as_unbound_cmethod
(
env
):
return
self
.
entry
.
used
=
True
else
:
self
.
analyse_as_ordinary_attribute
(
env
,
target
)
self
.
analyse_as_ordinary_attribute
(
env
,
target
)
if
self
.
entry
:
self
.
entry
.
used
=
True
def
analyse_as_cimported_attribute
(
self
,
env
,
target
):
def
analyse_as_cimported_attribute
(
self
,
env
,
target
):
# Try to interpret this as a reference to an imported
# Try to interpret this as a reference to an imported
...
...
Cython/Compiler/Main.py
View file @
ab8b5f9d
...
@@ -63,14 +63,17 @@ class Context(object):
...
@@ -63,14 +63,17 @@ class Context(object):
cython_scope
=
None
cython_scope
=
None
def
__init__
(
self
,
include_directories
,
compiler_directives
,
cpp
=
False
,
language_level
=
2
,
options
=
None
):
def
__init__
(
self
,
include_directories
,
compiler_directives
,
cpp
=
False
,
language_level
=
2
,
options
=
None
,
create_testscope
=
True
):
# cython_scope is a hack, set to False by subclasses, in order to break
# cython_scope is a hack, set to False by subclasses, in order to break
# an infinite loop.
# an infinite loop.
# Better code organization would fix it.
# Better code organization would fix it.
import
Builtin
,
CythonScope
import
Builtin
,
CythonScope
self
.
modules
=
{
"__builtin__"
:
Builtin
.
builtin_scope
}
self
.
modules
=
{
"__builtin__"
:
Builtin
.
builtin_scope
}
self
.
modules
[
"cython"
]
=
self
.
cython_scope
=
CythonScope
.
create_cython_scope
(
self
)
cyscope
=
CythonScope
.
create_cython_scope
(
self
,
create_testscope
=
create_testscope
)
self
.
modules
[
"cython"
]
=
self
.
cython_scope
=
cyscope
self
.
include_directories
=
include_directories
self
.
include_directories
=
include_directories
self
.
future_directives
=
set
()
self
.
future_directives
=
set
()
self
.
compiler_directives
=
compiler_directives
self
.
compiler_directives
=
compiler_directives
...
...
Cython/Compiler/ModuleNode.py
View file @
ab8b5f9d
...
@@ -951,6 +951,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
...
@@ -951,6 +951,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
# code.putln("static PyTypeObject %s;" % name)
# code.putln("static PyTypeObject %s;" % name)
def
generate_exttype_vtable_struct
(
self
,
entry
,
code
):
def
generate_exttype_vtable_struct
(
self
,
entry
,
code
):
if
not
entry
.
used
:
return
code
.
mark_pos
(
entry
.
pos
)
code
.
mark_pos
(
entry
.
pos
)
# Generate struct declaration for an extension type's vtable.
# Generate struct declaration for an extension type's vtable.
type
=
entry
.
type
type
=
entry
.
type
...
@@ -967,11 +970,14 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
...
@@ -967,11 +970,14 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
for
method_entry
in
scope
.
cfunc_entries
:
for
method_entry
in
scope
.
cfunc_entries
:
if
not
method_entry
.
is_inherited
:
if
not
method_entry
.
is_inherited
:
code
.
putln
(
code
.
putln
(
"%s;"
%
method_entry
.
type
.
declaration_code
(
"(*%s)"
%
method_entry
.
name
))
"%s;"
%
method_entry
.
type
.
declaration_code
(
"(*%s)"
%
method_entry
.
c
name
))
code
.
putln
(
code
.
putln
(
"};"
)
"};"
)
def
generate_exttype_vtabptr_declaration
(
self
,
entry
,
code
):
def
generate_exttype_vtabptr_declaration
(
self
,
entry
,
code
):
if
not
entry
.
used
:
return
code
.
mark_pos
(
entry
.
pos
)
code
.
mark_pos
(
entry
.
pos
)
# Generate declaration of pointer to an extension type's vtable.
# Generate declaration of pointer to an extension type's vtable.
type
=
entry
.
type
type
=
entry
.
type
...
@@ -1078,37 +1084,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
...
@@ -1078,37 +1084,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def
generate_cfunction_declarations
(
self
,
env
,
code
,
definition
):
def
generate_cfunction_declarations
(
self
,
env
,
code
,
definition
):
for
entry
in
env
.
cfunc_entries
:
for
entry
in
env
.
cfunc_entries
:
if
entry
.
inline_func_in_pxd
or
(
not
entry
.
in_cinclude
and
(
definition
generate_cfunction_declaration
(
entry
,
env
,
code
,
definition
)
or
entry
.
defined_in_pxd
or
entry
.
visibility
==
'extern'
)):
if
entry
.
visibility
==
'extern'
:
storage_class
=
"%s "
%
Naming
.
extern_c_macro
dll_linkage
=
"DL_IMPORT"
elif
entry
.
visibility
==
'public'
:
storage_class
=
"%s "
%
Naming
.
extern_c_macro
dll_linkage
=
"DL_EXPORT"
elif
entry
.
visibility
==
'private'
:
storage_class
=
"static "
dll_linkage
=
None
else
:
storage_class
=
"static "
dll_linkage
=
None
type
=
entry
.
type
if
entry
.
defined_in_pxd
and
not
definition
:
storage_class
=
"static "
dll_linkage
=
None
type
=
CPtrType
(
type
)
header
=
type
.
declaration_code
(
entry
.
cname
,
dll_linkage
=
dll_linkage
)
if
entry
.
func_modifiers
:
modifiers
=
"%s "
%
' '
.
join
(
entry
.
func_modifiers
).
upper
()
else
:
modifiers
=
''
code
.
putln
(
"%s%s%s; /*proto*/"
%
(
storage_class
,
modifiers
,
header
))
def
generate_variable_definitions
(
self
,
env
,
code
):
def
generate_variable_definitions
(
self
,
env
,
code
):
for
entry
in
env
.
var_entries
:
for
entry
in
env
.
var_entries
:
...
@@ -2413,6 +2389,39 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
...
@@ -2413,6 +2389,39 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
"%s = &%s;"
%
(
"%s = &%s;"
%
(
type
.
typeptr_cname
,
type
.
typeobj_cname
))
type
.
typeptr_cname
,
type
.
typeobj_cname
))
def
generate_cfunction_declaration
(
entry
,
env
,
code
,
definition
):
if
entry
.
inline_func_in_pxd
or
(
not
entry
.
in_cinclude
and
(
definition
or
entry
.
defined_in_pxd
or
entry
.
visibility
==
'extern'
)):
if
entry
.
visibility
==
'extern'
:
storage_class
=
"%s "
%
Naming
.
extern_c_macro
dll_linkage
=
"DL_IMPORT"
elif
entry
.
visibility
==
'public'
:
storage_class
=
"%s "
%
Naming
.
extern_c_macro
dll_linkage
=
"DL_EXPORT"
elif
entry
.
visibility
==
'private'
:
storage_class
=
"static "
dll_linkage
=
None
else
:
storage_class
=
"static "
dll_linkage
=
None
type
=
entry
.
type
if
entry
.
defined_in_pxd
and
not
definition
:
storage_class
=
"static "
dll_linkage
=
None
type
=
CPtrType
(
type
)
header
=
type
.
declaration_code
(
entry
.
cname
,
dll_linkage
=
dll_linkage
)
if
entry
.
func_modifiers
:
modifiers
=
"%s "
%
' '
.
join
(
entry
.
func_modifiers
).
upper
()
else
:
modifiers
=
''
code
.
putln
(
"%s%s%s; /*proto*/"
%
(
storage_class
,
modifiers
,
header
))
#------------------------------------------------------------------------------------
#------------------------------------------------------------------------------------
#
#
# Runtime support code
# Runtime support code
...
...
Cython/Compiler/Nodes.py
View file @
ab8b5f9d
...
@@ -3473,6 +3473,7 @@ class CClassDefNode(ClassDefNode):
...
@@ -3473,6 +3473,7 @@ class CClassDefNode(ClassDefNode):
api
=
self
.
api
,
api
=
self
.
api
,
buffer_defaults
=
self
.
buffer_defaults
(
env
),
buffer_defaults
=
self
.
buffer_defaults
(
env
),
shadow
=
self
.
shadow
)
shadow
=
self
.
shadow
)
if
self
.
shadow
:
if
self
.
shadow
:
home_scope
.
lookup
(
self
.
class_name
).
as_variable
=
self
.
entry
home_scope
.
lookup
(
self
.
class_name
).
as_variable
=
self
.
entry
if
home_scope
is
not
env
and
self
.
visibility
==
'extern'
:
if
home_scope
is
not
env
and
self
.
visibility
==
'extern'
:
...
@@ -6728,6 +6729,8 @@ class CnameDecoratorNode(StatNode):
...
@@ -6728,6 +6729,8 @@ class CnameDecoratorNode(StatNode):
cdef func(...):
cdef func(...):
...
...
In case of a cdef class the cname specifies the objstruct_cname.
node the node to which the cname decorator is applied
node the node to which the cname decorator is applied
cname the cname the node should get
cname the cname the node should get
"""
"""
...
@@ -6736,8 +6739,58 @@ class CnameDecoratorNode(StatNode):
...
@@ -6736,8 +6739,58 @@ class CnameDecoratorNode(StatNode):
def
analyse_declarations
(
self
,
env
):
def
analyse_declarations
(
self
,
env
):
self
.
node
.
analyse_declarations
(
env
)
self
.
node
.
analyse_declarations
(
env
)
self
.
node
.
entry
.
cname
=
self
.
cname
self
.
node
.
entry
.
func_cname
=
self
.
cname
self
.
is_function
=
isinstance
(
self
.
node
,
FuncDefNode
)
e
=
self
.
node
.
entry
if
self
.
is_function
:
e
.
cname
=
self
.
cname
e
.
func_cname
=
self
.
cname
else
:
scope
=
self
.
node
.
scope
e
.
cname
=
self
.
cname
e
.
type
.
objstruct_cname
=
self
.
cname
e
.
type
.
typeobj_cname
=
Naming
.
typeobj_prefix
+
self
.
cname
e
.
type
.
typeptr_cname
=
Naming
.
typeptr_prefix
+
self
.
cname
e
.
as_variable
.
cname
=
py_object_type
.
cast_code
(
e
.
type
.
typeptr_cname
)
scope
.
scope_prefix
=
self
.
cname
+
"_"
for
name
,
entry
in
scope
.
entries
.
iteritems
():
if
entry
.
func_cname
:
entry
.
func_cname
=
'%s_%s'
%
(
self
.
cname
,
entry
.
cname
)
def
analyse_expressions
(
self
,
env
):
self
.
node
.
analyse_expressions
(
env
)
def
generate_function_definitions
(
self
,
env
,
code
):
if
self
.
is_function
and
env
.
is_c_class_scope
:
# method in cdef class, generate a prototype in the header
h_code
=
code
.
globalstate
[
'utility_code_proto'
]
if
isinstance
(
self
.
node
,
DefNode
):
self
.
node
.
generate_function_header
(
h_code
,
with_pymethdef
=
False
,
proto_only
=
True
)
else
:
import
ModuleNode
entry
=
self
.
node
.
entry
cname
=
entry
.
cname
entry
.
cname
=
entry
.
func_cname
ModuleNode
.
generate_cfunction_declaration
(
entry
,
env
.
global_scope
(),
h_code
,
definition
=
True
)
entry
.
cname
=
cname
self
.
node
.
generate_function_definitions
(
env
,
code
)
def
generate_execution_code
(
self
,
code
):
self
.
node
.
generate_execution_code
(
code
)
#------------------------------------------------------------------------------------
#------------------------------------------------------------------------------------
...
...
Cython/Compiler/ParseTreeTransforms.py
View file @
ab8b5f9d
...
@@ -1250,6 +1250,9 @@ class CnameDirectivesTransform(CythonTransform, SkipDeclarations):
...
@@ -1250,6 +1250,9 @@ class CnameDirectivesTransform(CythonTransform, SkipDeclarations):
"""
"""
def
handle_function
(
self
,
node
):
def
handle_function
(
self
,
node
):
if
not
node
.
decorators
:
return
self
.
visit_Node
(
node
)
for
i
,
decorator
in
enumerate
(
node
.
decorators
):
for
i
,
decorator
in
enumerate
(
node
.
decorators
):
decorator
=
decorator
.
decorator
decorator
=
decorator
.
decorator
...
@@ -1271,18 +1274,16 @@ class CnameDirectivesTransform(CythonTransform, SkipDeclarations):
...
@@ -1271,18 +1274,16 @@ class CnameDirectivesTransform(CythonTransform, SkipDeclarations):
raise
AssertionError
(
raise
AssertionError
(
"argument to cname decorator must be a string literal"
)
"argument to cname decorator must be a string literal"
)
cname
=
args
[
0
].
compile_time_value
(
None
)
cname
=
args
[
0
].
compile_time_value
(
None
)
.
decode
(
'UTF-8'
)
del
node
.
decorators
[
i
]
del
node
.
decorators
[
i
]
node
=
Nodes
.
CnameDecoratorNode
(
pos
=
node
.
pos
,
node
=
node
,
node
=
Nodes
.
CnameDecoratorNode
(
pos
=
node
.
pos
,
node
=
node
,
cname
=
cname
)
cname
=
cname
)
break
break
self
.
visitchildren
(
node
)
return
self
.
visit_Node
(
node
)
return
node
visit_CFuncDefNode
=
handle_function
visit_FuncDefNode
=
handle_function
# visit_FuncDefNode = handle_function
visit_CClassDefNode
=
handle_function
# visit_ClassDefNode = handle_function
class
ForwardDeclareTypes
(
CythonTransform
):
class
ForwardDeclareTypes
(
CythonTransform
):
...
@@ -1570,10 +1571,6 @@ if VALUE is not None:
...
@@ -1570,10 +1571,6 @@ if VALUE is not None:
self
.
visitchildren
(
node
)
self
.
visitchildren
(
node
)
return
None
return
None
def
visit_CnameDecoratorNode
(
self
,
node
):
self
.
visitchildren
(
node
)
return
node
.
node
def
create_Property
(
self
,
entry
):
def
create_Property
(
self
,
entry
):
if
entry
.
visibility
==
'public'
:
if
entry
.
visibility
==
'public'
:
if
entry
.
type
.
is_pyobject
:
if
entry
.
type
.
is_pyobject
:
...
@@ -2567,4 +2564,3 @@ class DebugTransform(CythonTransform):
...
@@ -2567,4 +2564,3 @@ class DebugTransform(CythonTransform):
self
.
tb
.
start
(
'LocalVar'
,
attrs
)
self
.
tb
.
start
(
'LocalVar'
,
attrs
)
self
.
tb
.
end
(
'LocalVar'
)
self
.
tb
.
end
(
'LocalVar'
)
Cython/Compiler/Pipeline.py
View file @
ab8b5f9d
...
@@ -64,6 +64,8 @@ def use_utility_code_definitions(scope, target):
...
@@ -64,6 +64,8 @@ def use_utility_code_definitions(scope, target):
for
entry
in
scope
.
entries
.
itervalues
():
for
entry
in
scope
.
entries
.
itervalues
():
if
entry
.
used
and
entry
.
utility_code_definition
:
if
entry
.
used
and
entry
.
utility_code_definition
:
target
.
use_utility_code
(
entry
.
utility_code_definition
)
target
.
use_utility_code
(
entry
.
utility_code_definition
)
for
required_utility
in
entry
.
utility_code_definition
.
requires
:
target
.
use_utility_code
(
required_utility
)
elif
entry
.
as_module
:
elif
entry
.
as_module
:
use_utility_code_definitions
(
entry
.
as_module
,
target
)
use_utility_code_definitions
(
entry
.
as_module
,
target
)
...
...
Cython/Compiler/Scanning.py
View file @
ab8b5f9d
...
@@ -242,8 +242,10 @@ class StringSourceDescriptor(SourceDescriptor):
...
@@ -242,8 +242,10 @@ class StringSourceDescriptor(SourceDescriptor):
def
get_filenametable_entry
(
self
):
def
get_filenametable_entry
(
self
):
return
"stringsource"
return
"stringsource"
def
__hash__
(
self
):
# Do not hash on the name, an identical string source should be the
return
hash
(
self
.
name
)
# same object (name is often defaulted in other places)
# def __hash__(self):
# return hash(self.name)
def
__eq__
(
self
,
other
):
def
__eq__
(
self
,
other
):
return
isinstance
(
other
,
StringSourceDescriptor
)
and
self
.
name
==
other
.
name
return
isinstance
(
other
,
StringSourceDescriptor
)
and
self
.
name
==
other
.
name
...
...
Cython/Compiler/Symtab.py
View file @
ab8b5f9d
...
@@ -178,6 +178,7 @@ class Entry(object):
...
@@ -178,6 +178,7 @@ class Entry(object):
might_overflow = 0
might_overflow = 0
utility_code_definition = None
utility_code_definition = None
in_with_gil_block = 0
in_with_gil_block = 0
from_cython_utility_code = None
def __init__(self, name, cname, type, pos = None, init = None):
def __init__(self, name, cname, type, pos = None, init = None):
self.name = name
self.name = name
...
@@ -200,6 +201,7 @@ class Entry(object):
...
@@ -200,6 +201,7 @@ class Entry(object):
def all_alternatives(self):
def all_alternatives(self):
return [self] + self.overloaded_alternatives
return [self] + self.overloaded_alternatives
class Scope(object):
class Scope(object):
# name string Unqualified name
# name string Unqualified name
# outer_scope Scope or None Enclosing scope
# outer_scope Scope or None Enclosing scope
...
@@ -278,10 +280,14 @@ class Scope(object):
...
@@ -278,10 +280,14 @@ class Scope(object):
self.return_type = None
self.return_type = None
self.id_counters = {}
self.id_counters = {}
def merge_in(self, other):
def merge_in(self, other
, merge_unused=True
):
# Use with care...
# Use with care...
self.entries.update(other.entries)
entries = [(name, entry)
for x in ('const_entries',
for name, entry in other.entries.iteritems()
if entry.used or merge_unused]
self.entries.update(entries)
for attr in ('const_entries',
'type_entries',
'type_entries',
'sue_entries',
'sue_entries',
'arg_entries',
'arg_entries',
...
@@ -289,8 +295,10 @@ class Scope(object):
...
@@ -289,8 +295,10 @@ class Scope(object):
'pyfunc_entries',
'pyfunc_entries',
'cfunc_entries',
'cfunc_entries',
'c_class_entries'):
'c_class_entries'):
getattr(self, x).extend(getattr(other, x))
self_entries = getattr(self, attr)
for entry in getattr(other, attr):
if entry.used or merge_unused:
self_entries.append(entry)
def __str__(self):
def __str__(self):
return "
<%
s
%
s
>
" % (self.__class__.__name__, self.qualified_name)
return "
<%
s
%
s
>
" % (self.__class__.__name__, self.qualified_name)
...
@@ -1226,6 +1234,11 @@ class ModuleScope(Scope):
...
@@ -1226,6 +1234,11 @@ class ModuleScope(Scope):
if type.typeobj_cname and type.typeobj_cname != typeobj_cname:
if type.typeobj_cname and type.typeobj_cname != typeobj_cname:
error(pos, "Type object name differs from previous declaration")
error(pos, "Type object name differs from previous declaration")
type.typeobj_cname = typeobj_cname
type.typeobj_cname = typeobj_cname
# cdef classes are always exported, but we need to set it to
# distinguish between unused Cython utility code extension classes
entry.used = True
#
#
# Return new or existing entry
# Return new or existing entry
#
#
...
...
Cython/Compiler/TreeFragment.py
View file @
ab8b5f9d
...
@@ -22,7 +22,8 @@ Support for parsing strings into code trees.
...
@@ -22,7 +22,8 @@ Support for parsing strings into code trees.
class
StringParseContext
(
Main
.
Context
):
class
StringParseContext
(
Main
.
Context
):
def
__init__
(
self
,
name
,
include_directories
=
None
):
def
__init__
(
self
,
name
,
include_directories
=
None
):
if
include_directories
is
None
:
include_directories
=
[]
if
include_directories
is
None
:
include_directories
=
[]
Main
.
Context
.
__init__
(
self
,
include_directories
,
{})
Main
.
Context
.
__init__
(
self
,
include_directories
,
{},
create_testscope
=
False
)
self
.
module_name
=
name
self
.
module_name
=
name
def
find_module
(
self
,
module_name
,
relative_to
=
None
,
pos
=
None
,
need_pxd
=
1
):
def
find_module
(
self
,
module_name
,
relative_to
=
None
,
pos
=
None
,
need_pxd
=
1
):
...
...
Cython/Compiler/UtilityCode.py
View file @
ab8b5f9d
...
@@ -4,22 +4,68 @@ import Symtab
...
@@ -4,22 +4,68 @@ import Symtab
import
Naming
import
Naming
from
Cython.Compiler
import
Visitor
from
Cython.Compiler
import
Visitor
class
NonManglingModuleScope
(
Symtab
.
ModuleScope
):
def
add_imported_entry
(
self
,
name
,
entry
,
pos
):
entry
.
used
=
True
return
super
(
NonManglingModuleScope
,
self
).
add_imported_entry
(
name
,
entry
,
pos
)
def
mangle
(
self
,
prefix
,
name
=
None
):
if
name
:
if
prefix
in
(
Naming
.
typeobj_prefix
,
Naming
.
func_prefix
):
# Functions, classes etc. gets a manually defined prefix easily
# manually callable instead (the one passed to CythonUtilityCode)
prefix
=
self
.
prefix
return
"%s%s"
%
(
prefix
,
name
)
else
:
return
self
.
base
.
name
class
CythonUtilityCodeContext
(
StringParseContext
):
scope
=
None
def
find_module
(
self
,
module_name
,
relative_to
=
None
,
pos
=
None
,
need_pxd
=
1
):
if
module_name
!=
self
.
module_name
:
raise
AssertionError
(
"Not yet supporting any cimports/includes "
"from string code snippets"
)
if
self
.
scope
is
None
:
self
.
scope
=
NonManglingModuleScope
(
module_name
,
parent_module
=
None
,
context
=
self
)
self
.
scope
.
prefix
=
self
.
prefix
return
self
.
scope
class
CythonUtilityCode
(
object
):
class
CythonUtilityCode
(
object
):
"""
"""
Utility code written in the Cython language itself.
Utility code written in the Cython language itself.
The @cname decorator can set the cname for a function, method of cdef class.
Functions decorated with @cname('c_func_name') get the given cname.
For cdef classes the rules are as follows:
obj struct -> <cname>
obj type ptr -> __pyx_ptype_<cname>
methods -> <class_cname>_<method_cname>
For methods the cname decorator is optional, but without the decorator the
methods will not be prototyped. See Cython.Compiler.CythonScope and
tests/run/cythonscope.pyx for examples.
"""
"""
def
__init__
(
self
,
pyx
,
name
=
"<utility code>"
,
prefix
=
""
):
def
__init__
(
self
,
impl
,
name
=
"CythonUtilityCode"
,
prefix
=
""
,
requires
=
None
):
# 1) We need to delay the parsing/processing, so that all modules can be
# 1) We need to delay the parsing/processing, so that all modules can be
# imported without import loops
# imported without import loops
# 2) The same utility code object can be used for multiple source files;
# 2) The same utility code object can be used for multiple source files;
# while the generated node trees can be altered in the compilation of a
# while the generated node trees can be altered in the compilation of a
# single file.
# single file.
# Hence, delay any processing until later.
# Hence, delay any processing until later.
self
.
pyx
=
pyx
self
.
pyx
=
impl
self
.
name
=
name
self
.
name
=
name
self
.
prefix
=
prefix
self
.
prefix
=
prefix
self
.
requires
=
requires
or
[]
def
get_tree
(
self
):
def
get_tree
(
self
):
from
AnalysedTreeTransforms
import
AutoTestDictTransform
from
AnalysedTreeTransforms
import
AutoTestDictTransform
...
@@ -29,9 +75,9 @@ class CythonUtilityCode(object):
...
@@ -29,9 +75,9 @@ class CythonUtilityCode(object):
excludes
=
[
AutoTestDictTransform
]
excludes
=
[
AutoTestDictTransform
]
import
Pipeline
,
ParseTreeTransforms
import
Pipeline
,
ParseTreeTransforms
#
context = CythonUtilityCodeContext(self.name)
context
=
CythonUtilityCodeContext
(
self
.
name
)
#
context.prefix = self.prefix
context
.
prefix
=
self
.
prefix
context
=
StringParseContext
(
self
.
name
)
#
context = StringParseContext(self.name)
tree
=
parse_from_strings
(
self
.
name
,
self
.
pyx
,
context
=
context
)
tree
=
parse_from_strings
(
self
.
name
,
self
.
pyx
,
context
=
context
)
pipeline
=
Pipeline
.
create_pipeline
(
context
,
'pyx'
,
exclude_classes
=
excludes
)
pipeline
=
Pipeline
.
create_pipeline
(
context
,
'pyx'
,
exclude_classes
=
excludes
)
...
@@ -43,8 +89,28 @@ class CythonUtilityCode(object):
...
@@ -43,8 +89,28 @@ class CythonUtilityCode(object):
before
=
before
)
before
=
before
)
(
err
,
tree
)
=
Pipeline
.
run_pipeline
(
pipeline
,
tree
)
(
err
,
tree
)
=
Pipeline
.
run_pipeline
(
pipeline
,
tree
)
assert
not
err
assert
not
err
,
err
return
tree
return
tree
def
put_code
(
self
,
output
):
def
put_code
(
self
,
output
):
pass
pass
def
declare_in_scope
(
self
,
dest_scope
):
"""
Declare all entries from the utility code in dest_scope. Code will only
be included for used entries.
"""
self
.
tree
=
self
.
get_tree
()
entries
=
self
.
tree
.
scope
.
entries
entries
.
pop
(
'__name__'
)
entries
.
pop
(
'__file__'
)
entries
.
pop
(
'__builtins__'
)
entries
.
pop
(
'__doc__'
)
for
name
,
entry
in
entries
.
iteritems
():
entry
.
utility_code_definition
=
self
entry
.
used
=
False
dest_scope
.
merge_in
(
self
.
tree
.
scope
,
merge_unused
=
True
)
self
.
tree
.
scope
=
dest_scope
tests/run/cythonscope.pyx
View file @
ab8b5f9d
cimport
cython
cimport
cython
from
cython
cimport
_testscope
as
tester
from
cython
cimport
_testscope
as
tester
from
cython
cimport
TestClass
,
_testclass_new
as
TestClass_New
from
cython.view
cimport
_testscope
as
viewtester
from
cython.view
cimport
_testscope
as
viewtester
cdef
extern
from
*
:
# TestClass stuff
cdef
struct
__pyx_TestClass
:
int
value
# Type pointer
cdef
__pyx_TestClass
*
TestClassType
"__pyx_ptype___pyx_TestClass"
# This is a cdef function
cdef
__pyx_TestClass_New
(
int
)
# These are methods and therefore have no prototypes
cdef
__pyx_TestClass_cdef_method
(
TestClass
self
,
int
value
)
cdef
__pyx_TestClass_cpdef_method
(
TestClass
self
,
int
value
,
int
skip_dispatch
)
cdef
__pyx_TestClass_def_method
(
object
self
,
object
value
)
cdef
__pyx_TestClass_cdef_cname
(
TestClass
self
,
int
value
)
cdef
__pyx_TestClass_cpdef_cname
(
TestClass
self
,
int
value
,
int
skip_dispatch
)
cdef
__pyx_TestClass_def_cname
(
object
self
,
object
value
)
def
test_cdef_cython_utility
():
def
test_cdef_cython_utility
():
"""
"""
...
@@ -16,3 +37,93 @@ def test_cdef_cython_utility():
...
@@ -16,3 +37,93 @@ def test_cdef_cython_utility():
print
cython
.
view
.
_testscope
(
4
)
print
cython
.
view
.
_testscope
(
4
)
print
tester
(
3
)
print
tester
(
3
)
print
viewtester
(
3
)
print
viewtester
(
3
)
def
test_cdef_class_cython_utility
():
"""
>>> test_cdef_class_cython_utility()
7
14
TestClass(20)
TestClass(50)
"""
cdef
__pyx_TestClass
*
objstruct
obj
=
TestClass_New
(
7
)
objstruct
=
<
__pyx_TestClass
*>
obj
print
objstruct
.
value
obj
=
__pyx_TestClass_New
(
14
)
objstruct
=
<
__pyx_TestClass
*>
obj
print
objstruct
.
value
print
(
<
object
>
TestClassType
)(
20
)
print
TestClass
(
50
)
def
test_extclass_c_methods
():
"""
>>> test_extclass_c_methods()
Hello from cdef_method 1
Hello from cpdef_method 2
Hello from def_method 3
Hello from cdef_cname_method 4
Hello from cpdef_cname_method 5
Hello from def_cname_method 6
Hello from cdef_method 1
Hello from cpdef_method 2
Hello from def_method 3
Hello from cdef_cname_method 4
Hello from cpdef_cname_method 5
Hello from def_cname_method 6
"""
cdef
TestClass
obj1
=
TestClass
(
11
)
cdef
TestClass
obj2
=
TestClass_New
(
22
)
__pyx_TestClass_cdef_method
(
obj1
,
1
)
__pyx_TestClass_cpdef_method
(
obj1
,
2
,
True
)
__pyx_TestClass_def_method
(
obj1
,
3
)
__pyx_TestClass_cdef_cname
(
obj1
,
4
)
__pyx_TestClass_cpdef_cname
(
obj1
,
5
,
True
)
__pyx_TestClass_def_cname
(
obj1
,
6
)
__pyx_TestClass_cdef_method
(
obj2
,
1
)
__pyx_TestClass_cpdef_method
(
obj2
,
2
,
True
)
__pyx_TestClass_def_method
(
obj2
,
3
)
__pyx_TestClass_cdef_cname
(
obj2
,
4
)
__pyx_TestClass_cpdef_cname
(
obj2
,
5
,
True
)
__pyx_TestClass_def_cname
(
obj2
,
6
)
def
test_extclass_cython_methods
():
"""
>>> test_extclass_cython_methods()
Hello from cdef_method 1
Hello from cpdef_method 2
Hello from def_method 3
Hello from cdef_cname_method 4
Hello from cpdef_cname_method 5
Hello from def_cname_method 6
Hello from cdef_method 1
Hello from cpdef_method 2
Hello from def_method 3
Hello from cdef_cname_method 4
Hello from cpdef_cname_method 5
Hello from def_cname_method 6
"""
cdef
TestClass
obj1
=
TestClass
(
11
)
cdef
TestClass
obj2
=
TestClass_New
(
22
)
obj1
.
cdef
_method
(
1
)
obj1
.
cpdef
_method
(
2
)
obj1
.
def_method
(
3
)
obj1
.
cdef
_cname_method
(
4
)
obj1
.
cpdef
_cname_method
(
5
)
obj1
.
def_cname_method
(
6
)
obj2
.
cdef
_method
(
1
)
obj2
.
cpdef
_method
(
2
)
obj2
.
def_method
(
3
)
obj2
.
cdef
_cname_method
(
4
)
obj2
.
cpdef
_cname_method
(
5
)
obj2
.
def_cname_method
(
6
)
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