Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
cython
Commits
a2776020
Commit
a2776020
authored
Sep 22, 2018
by
scoder
Committed by
GitHub
Sep 22, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2620 from cython/directives_scope_gh459
Fix lambdas/genexpr in @cfunc functions
parents
1a91b07e
d89862f4
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
82 additions
and
43 deletions
+82
-43
CHANGES.rst
CHANGES.rst
+3
-0
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+3
-3
Cython/Compiler/Options.py
Cython/Compiler/Options.py
+9
-8
Cython/Compiler/ParseTreeTransforms.py
Cython/Compiler/ParseTreeTransforms.py
+29
-32
tests/run/exttype_freelist.pyx
tests/run/exttype_freelist.pyx
+16
-0
tests/run/purecdef.py
tests/run/purecdef.py
+22
-0
No files found.
CHANGES.rst
View file @
a2776020
...
@@ -102,6 +102,9 @@ Bugs fixed
...
@@ -102,6 +102,9 @@ Bugs fixed
* Fix declarations of builtin or C types using strings in pure python mode.
* Fix declarations of builtin or C types using strings in pure python mode.
(Github issue #2046)
(Github issue #2046)
* Generator expressions and lambdas failed to compile in ``@cfunc`` functions.
(Github issue #459)
* Several internal function signatures were fixed that lead to warnings in gcc-8.
* Several internal function signatures were fixed that lead to warnings in gcc-8.
(Github issue #2363)
(Github issue #2363)
...
...
Cython/Compiler/Nodes.py
View file @
a2776020
...
@@ -2340,7 +2340,7 @@ class CFuncDefNode(FuncDefNode):
...
@@ -2340,7 +2340,7 @@ class CFuncDefNode(FuncDefNode):
self
.
is_c_class_method
=
env
.
is_c_class_scope
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
.
get
(
'locals'
,
{})
)
if
self
.
directive_returns
is
not
None
:
if
self
.
directive_returns
is
not
None
:
base_type
=
self
.
directive_returns
.
analyse_as_type
(
env
)
base_type
=
self
.
directive_returns
.
analyse_as_type
(
env
)
if
base_type
is
None
:
if
base_type
is
None
:
...
@@ -2907,7 +2907,7 @@ class DefNode(FuncDefNode):
...
@@ -2907,7 +2907,7 @@ class DefNode(FuncDefNode):
self
.
py_wrapper
.
analyse_declarations
(
env
)
self
.
py_wrapper
.
analyse_declarations
(
env
)
def
analyse_argument_types
(
self
,
env
):
def
analyse_argument_types
(
self
,
env
):
self
.
directive_locals
=
env
.
directives
[
'locals'
]
self
.
directive_locals
=
env
.
directives
.
get
(
'locals'
,
{})
allow_none_for_extension_args
=
env
.
directives
[
'allow_none_for_extension_args'
]
allow_none_for_extension_args
=
env
.
directives
[
'allow_none_for_extension_args'
]
f2s
=
env
.
fused_to_specific
f2s
=
env
.
fused_to_specific
...
@@ -4959,7 +4959,7 @@ class CClassDefNode(ClassDefNode):
...
@@ -4959,7 +4959,7 @@ class CClassDefNode(ClassDefNode):
code
.
putln
(
"if (__Pyx_MergeVtables(&%s) < 0) %s"
%
(
code
.
putln
(
"if (__Pyx_MergeVtables(&%s) < 0) %s"
%
(
typeobj_cname
,
typeobj_cname
,
code
.
error_goto
(
entry
.
pos
)))
code
.
error_goto
(
entry
.
pos
)))
if
not
type
.
scope
.
is_internal
and
not
type
.
scope
.
directives
[
'internal'
]
:
if
not
type
.
scope
.
is_internal
and
not
type
.
scope
.
directives
.
get
(
'internal'
)
:
# scope.is_internal is set for types defined by
# scope.is_internal is set for types defined by
# Cython (such as closures), the 'internal'
# Cython (such as closures), the 'internal'
# directive is set by users
# directive is set by users
...
...
Cython/Compiler/Options.py
View file @
a2776020
...
@@ -170,8 +170,6 @@ _directive_defaults = {
...
@@ -170,8 +170,6 @@ _directive_defaults = {
'nonecheck'
:
False
,
'nonecheck'
:
False
,
'initializedcheck'
:
True
,
'initializedcheck'
:
True
,
'embedsignature'
:
False
,
'embedsignature'
:
False
,
'locals'
:
{},
'exceptval'
:
None
,
# (except value=None, check=True)
'auto_cpdef'
:
False
,
'auto_cpdef'
:
False
,
'auto_pickle'
:
None
,
'auto_pickle'
:
None
,
'cdivision'
:
False
,
# was True before 0.12
'cdivision'
:
False
,
# was True before 0.12
...
@@ -183,12 +181,8 @@ _directive_defaults = {
...
@@ -183,12 +181,8 @@ _directive_defaults = {
'wraparound'
:
True
,
'wraparound'
:
True
,
'ccomplex'
:
False
,
# use C99/C++ for complex types and arith
'ccomplex'
:
False
,
# use C99/C++ for complex types and arith
'callspec'
:
""
,
'callspec'
:
""
,
'final'
:
False
,
'nogil'
:
False
,
'nogil'
:
False
,
'internal'
:
False
,
'profile'
:
False
,
'profile'
:
False
,
'no_gc_clear'
:
False
,
'no_gc'
:
False
,
'linetrace'
:
False
,
'linetrace'
:
False
,
'emit_code_comments'
:
True
,
# copy original source code into C code comments
'emit_code_comments'
:
True
,
# copy original source code into C code comments
'annotation_typing'
:
True
,
# read type declarations from Python function annotations
'annotation_typing'
:
True
,
# read type declarations from Python function annotations
...
@@ -241,7 +235,6 @@ _directive_defaults = {
...
@@ -241,7 +235,6 @@ _directive_defaults = {
# experimental, subject to change
# experimental, subject to change
'binding'
:
None
,
'binding'
:
None
,
'freelist'
:
0
,
'formal_grammar'
:
False
,
'formal_grammar'
:
False
,
}
}
...
@@ -301,7 +294,9 @@ def normalise_encoding_name(option_name, encoding):
...
@@ -301,7 +294,9 @@ def normalise_encoding_name(option_name, encoding):
directive_types
=
{
directive_types
=
{
'language_level'
:
int
,
# values can be None/2/3, where None == 2+warning
'language_level'
:
int
,
# values can be None/2/3, where None == 2+warning
'auto_pickle'
:
bool
,
'auto_pickle'
:
bool
,
'locals'
:
dict
,
'final'
:
bool
,
# final cdef classes and methods
'final'
:
bool
,
# final cdef classes and methods
'nogil'
:
bool
,
'internal'
:
bool
,
# cdef class visibility in the module dict
'internal'
:
bool
,
# cdef class visibility in the module dict
'infer_types'
:
bool
,
# values can be True/None/False
'infer_types'
:
bool
,
# values can be True/None/False
'binding'
:
bool
,
'binding'
:
bool
,
...
@@ -310,7 +305,10 @@ directive_types = {
...
@@ -310,7 +305,10 @@ directive_types = {
'inline'
:
None
,
'inline'
:
None
,
'staticmethod'
:
None
,
'staticmethod'
:
None
,
'cclass'
:
None
,
'cclass'
:
None
,
'no_gc_clear'
:
bool
,
'no_gc'
:
bool
,
'returns'
:
type
,
'returns'
:
type
,
'exceptval'
:
type
,
# actually (type, check=True/False), but has its own parser
'set_initial_path'
:
str
,
'set_initial_path'
:
str
,
'freelist'
:
int
,
'freelist'
:
int
,
'c_string_type'
:
one_of
(
'bytes'
,
'bytearray'
,
'str'
,
'unicode'
),
'c_string_type'
:
one_of
(
'bytes'
,
'bytearray'
,
'str'
,
'unicode'
),
...
@@ -325,8 +323,10 @@ directive_scopes = { # defaults to available everywhere
...
@@ -325,8 +323,10 @@ directive_scopes = { # defaults to available everywhere
# 'module', 'function', 'class', 'with statement'
# 'module', 'function', 'class', 'with statement'
'auto_pickle'
:
(
'module'
,
'cclass'
),
'auto_pickle'
:
(
'module'
,
'cclass'
),
'final'
:
(
'cclass'
,
'function'
),
'final'
:
(
'cclass'
,
'function'
),
'nogil'
:
(
'function'
,),
'nogil'
:
(
'function'
,
'with statement'
),
'inline'
:
(
'function'
,),
'inline'
:
(
'function'
,),
'cfunc'
:
(
'function'
,
'with statement'
),
'ccall'
:
(
'function'
,
'with statement'
),
'returns'
:
(
'function'
,),
'returns'
:
(
'function'
,),
'exceptval'
:
(
'function'
,),
'exceptval'
:
(
'function'
,),
'locals'
:
(
'function'
,),
'locals'
:
(
'function'
,),
...
@@ -334,6 +334,7 @@ directive_scopes = { # defaults to available everywhere
...
@@ -334,6 +334,7 @@ directive_scopes = { # defaults to available everywhere
'no_gc_clear'
:
(
'cclass'
,),
'no_gc_clear'
:
(
'cclass'
,),
'no_gc'
:
(
'cclass'
,),
'no_gc'
:
(
'cclass'
,),
'internal'
:
(
'cclass'
,),
'internal'
:
(
'cclass'
,),
'cclass'
:
(
'class'
,
'cclass'
,
'with statement'
),
'autotestdict'
:
(
'module'
,),
'autotestdict'
:
(
'module'
,),
'autotestdict.all'
:
(
'module'
,),
'autotestdict.all'
:
(
'module'
,),
'autotestdict.cdef'
:
(
'module'
,),
'autotestdict.cdef'
:
(
'module'
,),
...
...
Cython/Compiler/ParseTreeTransforms.py
View file @
a2776020
...
@@ -958,30 +958,33 @@ class InterpretCompilerDirectives(CythonTransform):
...
@@ -958,30 +958,33 @@ class InterpretCompilerDirectives(CythonTransform):
else
:
else
:
assert
False
assert
False
def
visit_with_directives
(
self
,
body
,
directives
):
def
visit_with_directives
(
self
,
node
,
directives
):
olddirectives
=
self
.
directives
if
not
directives
:
newdirectives
=
copy
.
copy
(
olddirectives
)
return
self
.
visit_Node
(
node
)
newdirectives
.
update
(
directives
)
self
.
directives
=
newdirectives
old_directives
=
self
.
directives
assert
isinstance
(
body
,
Nodes
.
StatListNode
),
body
new_directives
=
dict
(
old_directives
)
retbody
=
self
.
visit_Node
(
body
)
new_directives
.
update
(
directives
)
directive
=
Nodes
.
CompilerDirectivesNode
(
pos
=
retbody
.
pos
,
body
=
retbody
,
directives
=
newdirectives
)
if
new_directives
==
old_directives
:
self
.
directives
=
olddirectives
return
self
.
visit_Node
(
node
)
return
directive
self
.
directives
=
new_directives
retbody
=
self
.
visit_Node
(
node
)
self
.
directives
=
old_directives
if
not
isinstance
(
retbody
,
Nodes
.
StatListNode
):
retbody
=
Nodes
.
StatListNode
(
node
.
pos
,
stats
=
[
retbody
])
return
Nodes
.
CompilerDirectivesNode
(
pos
=
retbody
.
pos
,
body
=
retbody
,
directives
=
new_directives
)
# Handle decorators
# Handle decorators
def
visit_FuncDefNode
(
self
,
node
):
def
visit_FuncDefNode
(
self
,
node
):
directives
=
self
.
_extract_directives
(
node
,
'function'
)
directives
=
self
.
_extract_directives
(
node
,
'function'
)
if
not
directives
:
return
self
.
visit_with_directives
(
node
,
directives
)
return
self
.
visit_Node
(
node
)
body
=
Nodes
.
StatListNode
(
node
.
pos
,
stats
=
[
node
])
return
self
.
visit_with_directives
(
body
,
directives
)
def
visit_CVarDefNode
(
self
,
node
):
def
visit_CVarDefNode
(
self
,
node
):
directives
=
self
.
_extract_directives
(
node
,
'function'
)
directives
=
self
.
_extract_directives
(
node
,
'function'
)
if
not
directives
:
return
self
.
visit_Node
(
node
)
for
name
,
value
in
directives
.
items
():
for
name
,
value
in
directives
.
items
():
if
name
==
'locals'
:
if
name
==
'locals'
:
node
.
directive_locals
=
value
node
.
directive_locals
=
value
...
@@ -990,29 +993,19 @@ class InterpretCompilerDirectives(CythonTransform):
...
@@ -990,29 +993,19 @@ class InterpretCompilerDirectives(CythonTransform):
node
.
pos
,
node
.
pos
,
"Cdef functions can only take cython.locals(), "
"Cdef functions can only take cython.locals(), "
"staticmethod, or final decorators, got %s."
%
name
))
"staticmethod, or final decorators, got %s."
%
name
))
body
=
Nodes
.
StatListNode
(
node
.
pos
,
stats
=
[
node
])
return
self
.
visit_with_directives
(
node
,
directives
)
return
self
.
visit_with_directives
(
body
,
directives
)
def
visit_CClassDefNode
(
self
,
node
):
def
visit_CClassDefNode
(
self
,
node
):
directives
=
self
.
_extract_directives
(
node
,
'cclass'
)
directives
=
self
.
_extract_directives
(
node
,
'cclass'
)
if
not
directives
:
return
self
.
visit_with_directives
(
node
,
directives
)
return
self
.
visit_Node
(
node
)
body
=
Nodes
.
StatListNode
(
node
.
pos
,
stats
=
[
node
])
return
self
.
visit_with_directives
(
body
,
directives
)
def
visit_CppClassNode
(
self
,
node
):
def
visit_CppClassNode
(
self
,
node
):
directives
=
self
.
_extract_directives
(
node
,
'cppclass'
)
directives
=
self
.
_extract_directives
(
node
,
'cppclass'
)
if
not
directives
:
return
self
.
visit_with_directives
(
node
,
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
:
return
self
.
visit_with_directives
(
node
,
directives
)
return
self
.
visit_Node
(
node
)
body
=
Nodes
.
StatListNode
(
node
.
pos
,
stats
=
[
node
])
return
self
.
visit_with_directives
(
body
,
directives
)
def
_extract_directives
(
self
,
node
,
scope_name
):
def
_extract_directives
(
self
,
node
,
scope_name
):
if
not
node
.
decorators
:
if
not
node
.
decorators
:
...
@@ -1059,7 +1052,7 @@ class InterpretCompilerDirectives(CythonTransform):
...
@@ -1059,7 +1052,7 @@ class InterpretCompilerDirectives(CythonTransform):
optdict
[
name
]
=
value
optdict
[
name
]
=
value
return
optdict
return
optdict
# Handle with
statements
# Handle with
-
statements
def
visit_WithStatNode
(
self
,
node
):
def
visit_WithStatNode
(
self
,
node
):
directive_dict
=
{}
directive_dict
=
{}
for
directive
in
self
.
try_to_parse_directives
(
node
.
manager
)
or
[]:
for
directive
in
self
.
try_to_parse_directives
(
node
.
manager
)
or
[]:
...
@@ -2385,6 +2378,10 @@ class AdjustDefByDirectives(CythonTransform, SkipDeclarations):
...
@@ -2385,6 +2378,10 @@ class AdjustDefByDirectives(CythonTransform, SkipDeclarations):
self
.
visitchildren
(
node
)
self
.
visitchildren
(
node
)
return
node
return
node
def
visit_LambdaNode
(
self
,
node
):
# No directives should modify lambdas or generator expressions (and also nothing in them).
return
node
def
visit_PyClassDefNode
(
self
,
node
):
def
visit_PyClassDefNode
(
self
,
node
):
if
'cclass'
in
self
.
directives
:
if
'cclass'
in
self
.
directives
:
node
=
node
.
as_cclass
()
node
=
node
.
as_cclass
()
...
...
tests/run/exttype_freelist.pyx
View file @
a2776020
...
@@ -451,3 +451,19 @@ cdef class ExtTypeWithRefCycle:
...
@@ -451,3 +451,19 @@ cdef class ExtTypeWithRefCycle:
def
__init__
(
self
,
obj
=
None
):
def
__init__
(
self
,
obj
=
None
):
self
.
attribute
=
obj
self
.
attribute
=
obj
@
cython
.
freelist
(
3
)
@
cython
.
cclass
class
DecoratedPyClass
(
object
):
"""
>>> obj1 = DecoratedPyClass()
>>> obj2 = DecoratedPyClass()
>>> obj3 = DecoratedPyClass()
>>> obj4 = DecoratedPyClass()
>>> obj1 = DecoratedPyClass()
>>> obj2 = DecoratedPyClass()
>>> obj3 = DecoratedPyClass()
>>> obj4 = DecoratedPyClass()
"""
tests/run/purecdef.py
View file @
a2776020
...
@@ -28,6 +28,17 @@ with cfunc:
...
@@ -28,6 +28,17 @@ with cfunc:
def
fwith2
(
a
):
def
fwith2
(
a
):
return
a
*
4
return
a
*
4
@
cython
.
test_assert_path_exists
(
'//CFuncDefNode'
,
'//LambdaNode'
,
'//GeneratorDefNode'
,
'//GeneratorBodyDefNode'
,
)
def
f_with_genexpr
(
a
):
f
=
lambda
x
:
x
+
1
return
(
f
(
x
)
for
x
in
a
)
with
cclass
:
with
cclass
:
@
cython
.
test_assert_path_exists
(
'//CClassDefNode'
)
@
cython
.
test_assert_path_exists
(
'//CClassDefNode'
)
class
Egg
(
object
):
class
Egg
(
object
):
...
@@ -123,3 +134,14 @@ def test_typed_return():
...
@@ -123,3 +134,14 @@ def test_typed_return():
"""
"""
x
=
cython
.
declare
(
int
,
5
)
x
=
cython
.
declare
(
int
,
5
)
assert
typed_return
(
cython
.
address
(
x
))[
0
]
is
x
assert
typed_return
(
cython
.
address
(
x
))[
0
]
is
x
def
test_genexpr_in_cdef
(
l
):
"""
>>> gen = test_genexpr_in_cdef([1, 2, 3])
>>> list(gen)
[2, 3, 4]
>>> list(gen)
[]
"""
return
f_with_genexpr
(
l
)
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